CNI, CSI and CRI

The three plug-in points for running containers, Pod networking and storage, and where to find each one on a node.

35 min 2 hands-on tasksArchitecture · 25% of the exam

Key ideas in this lesson · tap one for a simple explanation

What you will be able to do

  • Say what CRI, CNI and CSI each plug in, and which part of Kubernetes calls each one.
  • Find a node's container runtime endpoint and the CNI configuration it loads.
  • Use crictl on a node to list Pod sandboxes and containers and print their full IDs.
  • Tell from a symptom which interface to check first.

Kubernetes does not run , build networks or attach disks by itself. It hands each job to a plug-in, through a standard interface. Think of a power socket: any device with the right plug works. That is why you can swap for CRI-O, or for another network plug-in, without changing Kubernetes.

  • (Container Runtime Interface): the asks a , such as containerd, to start and stop containers.
  • (Container Network Interface): the container runtime asks a network plug-in, such as Calico, to give each new Pod an IP address.
  • (Container Storage Interface): Kubernetes asks a storage driver to create volumes and mount them for Pods.
Who asks whom

CRI

runs containers

kubelet

asks

containerd

starts the containers

CNI

connects Pods to the network

containerd

asks, for each new Pod

Calico

gives the Pod an IP

CSI

attaches storage

kubelet and helpers

ask

Storage driver

creates and mounts volumes

Each interface joins a part of Kubernetes to a plug-in. On this lab the plug-ins are containerd and Calico; the lab has no CSI driver.

Exam tasks here are short. You find a value on a and write it to a file. You use crictl where kubectl cannot reach. Or you say which interface a broken node or Pod points at.

InterfaceOn this labWhere to look
CRIcontainerdThe socket /run/containerd/containerd.sock and the config /etc/containerd/config.toml on each node. kubectl get nodes -o wide shows the runtime and its version.
CNICalicoConfig files in /etc/cni/net.d and plug-in programs in /opt/cni/bin on each node, plus the calico-node
CSINone: the standard uses a provisioner that is not CSIkubectl get csidrivers, kubectl get csinode, and the provisioner of each StorageClass

CRI: how the kubelet reaches the runtime

The kubelet never starts containers itself. It asks the container runtime, through the CRI, over a socket file on the node. To find that socket, read containerRuntimeEndpoint in the kubelet's config file, /var/lib/kubelet/config.yaml.

  • On this lab and most clusters the runtime is containerd, and the endpoint is unix:///run/containerd/containerd.sock.
  • Older clusters may set it as a flag instead: --container-runtime-endpoint in /var/lib/kubelet/kubeadm-flags.env.
  • How containerd itself is set up, such as its cgroup driver, is part of Installing a cluster with kubeadm.

crictl: look below the API

crictl talks to the same socket as the kubelet. It shows what the runtime sees on one node, and it still works when the or the kubelet is down. Do not mix it up with :

ToolTalks toRuns onShows
kubectlThe API serverYour workstationKubernetes objects in the whole cluster
The container runtimeOne node, in a node shellThe Pod sandboxes and containers on that node only

A Pod sandbox is the runtime's home for one Pod. It holds the Pod's network, and the Pod's containers run inside it. crictl pods lists sandboxes, and crictl ps lists containers.

Runtime facts and crictl, from a node shell
docker exec -it cka-worker bash                 # exam: ssh <node>, then sudo -i

grep containerRuntimeEndpoint /var/lib/kubelet/config.yaml
cat /var/lib/kubelet/kubeadm-flags.env           # extra kubelet flags kubeadm wrote

crictl pods --namespace kube-system              # pod sandboxes (POD ID)
crictl ps -a --name coredns                      # containers, including exited ones (CONTAINER)
crictl ps --name web --no-trunc -q               # full 64-character IDs only

Reading logs and debugging with crictl is taught in kubectl debug, ephemeral containers and crictl.

CNI: which network config a node uses

Each time a Pod starts, the container runtime calls the CNI plug-in to set up the Pod's network. Pod networking and CNI walks through the whole flow. For this lesson's task, three facts are enough:

  • The runtime reads the config files in /etc/cni/net.d and uses only the first one in lexical order. Lexical means sorted character by character, like a dictionary. Only .conflist, .conf and .json files count.
  • Each plug-in in that file has a type. The type is the name of a program in /opt/cni/bin.
  • A leftover file such as 05-old.conf sorts before 10-calico.conflist, so it wins. New Pods then get the wrong network.
The CNI pieces on this lab
docker exec cka-worker ls -l /etc/cni/net.d       # 10-calico.conflist and calico-kubeconfig
docker exec cka-worker cat /etc/cni/net.d/10-calico.conflist   # plugins: "calico" (ipam "calico-ipam"), then "portmap"
docker exec cka-worker ls /opt/cni/bin            # calico, calico-ipam, host-local, loopback, portmap, ...

CSI: storage drivers

A CSI driver lets Kubernetes use a storage system, such as cloud disks, without that system's code being part of Kubernetes. A driver usually has two parts:

  • A node plugin: a DaemonSet with one Pod per node. It registers with the kubelet and mounts volumes into Pods.
  • A controller: a whose helper containers create, attach and resize volumes when claims ask for them.

A StorageClass names its driver in provisioner, for example ebs.csi.aws.com. StorageClasses and dynamic provisioning covers how claims use it.

CSI objects, read from the API
kubectl get csidrivers
kubectl get csinode
kubectl get csinode cka-worker -o jsonpath='{.spec.drivers[*].name}'
kubectl get volumeattachments

From a symptom to an interface

When something breaks, the symptom tells you which interface to look at. The troubleshooting module shows the fixes, starting with Worker node failures.

SymptomInterfaceLook first at
Node NotReady, with the message cni plugin not initializedCNI/etc/cni/net.d on that node, and the network plug-in's Pod there
Pod stuck in ContainerCreating, event failed to setup network for sandboxCNIThe network plug-in's Pod on that node and its logs
Node NotReady, and the kubelet log says the runtime socket is missing or refusedCRIsystemctl status containerd, then the endpoint in the kubelet config
Pending, waiting for a volume to be createdCSI or another provisionerThe provisioner's Pods and logs, and the StorageClass's provisioner
Pod in ContainerCreating with FailedMount or FailedAttachVolumeCSIkubectl get csinode, kubectl get volumeattachments, and the driver's Pod on that node

In the official docs· open on exam day too

Hands-on task 1 of 2ar-ext-1
~5 min4% weightArchitecture

Record a node's CNI and runtime configuration

Inspect node cka-worker (lab: docker exec -it cka-worker bash; exam: ssh cka-worker) and write these answers to files on your workstation under /tmp/cka/ext/: in cni-config.txt, the file name (without its directory) of the CNI network configuration the container runtime loads on that node; in cni-plugin.txt, the type of the first plugin in that configuration; in runtime-endpoint.txt, the container runtime endpoint the kubelet on that node is configured to use.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-ext-1/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-ext-1/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-ext-1/cleanup | bash
Hands-on task 2 of 2ar-ext-2
~6 min4% weightArchitecture

Find a container below the API with crictl

Pod storefront in namespace arx-ext runs two containers. On the node where it runs, use crictl to find the ID of the Pod's sandbox and write it to /tmp/cka/ext/storefront-sandbox.txt, then find the ID of its log-agent container and write it to /tmp/cka/ext/log-agent-id.txt. Write the full, untruncated IDs.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-ext-2/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-ext-2/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-ext-2/cleanup | bash

Finished this lesson?

0 of 2 tasks passed. Your readiness counts tasks, so run them before you move on.