Pod networking and CNI

How Pods get IP addresses and reach each other, the two address ranges of a cluster, and how to test a connection.

35 min 2 hands-on tasksNetworking · 20% of the exam

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

What you will be able to do

  • State the three rules of the Kubernetes network model, and say which part makes each one work.
  • Read the Pod and Service ranges from the control plane, and tell them apart from a node's podCIDR.
  • Find any Pod's IP and node, then test Pod-to-Pod traffic from a temporary client Pod.

Every in a cluster gets its own IP address, and any Pod can reach any other Pod at that address. This lesson shows who hands out those addresses, how traffic travels between , and how to test it. The exam calls this Understand connectivity between Pods. It is rarely a task on its own, but every , and troubleshooting question builds on it.

The network model in three rules

Kubernetes sets three rules for the network. Every cluster must follow them.

  • Every Pod gets its own IP address. All in one Pod share it, and they reach each other on localhost. So two containers in one Pod cannot both use port 8080.
  • Any Pod can reach any other Pod at its real IP. A Pod on cka-worker calls a Pod on cka-worker2 directly. No address is rewritten on the way (no NAT), so the receiver sees the caller's real IP.
  • Programs on a node can reach every Pod on that node. That is how the runs liveness and .

CNI plugin and kube-proxy: two parts, two jobs

Kubernetes only writes these rules down. Two other parts make them work, and their jobs are easy to mix up:

PartIts jobExample
plugin: the cluster's network add-on ( in this lab)Gives each Pod an IP address and carries traffic from Pod to PodPod A calls Pod B at 10.244.157.130
: a helper on every nodeMakes Service addresses work, on top of the Pod networkPod A calls Service api and lands on one of its Pods

So Pod-to-Pod is the CNI plugin, and Pod-to-Service is kube-proxy. Other CNI plugins you may meet are Cilium and Flannel. This lesson covers the CNI side; Services covers kube-proxy.

Two address ranges: Pod CIDR and Service CIDR

Every cluster has two separate ranges of IP addresses. Pods get their addresses from one, Services from the other. A range is written as a CIDR: 10.244.0.0/16 means every address that starts with 10.244..

Two address ranges

Pod CIDR

Pod IPs, handed out by the CNI plugin

10.244.0.0/​16

Service CIDR

Service IPs, handed out by the API server

10.96.0.0/​16

The two ranges never overlap. Pod addresses are real; a Service address is virtual and sits on no network interface.

RangeWhat uses itWhere it is setThis lab
Pod CIDR (also called the cluster CIDR)Pod IPs. The CNI plugin hands them out.--cluster-cidr on (networking.podSubnet in ). The CNI plugin's own pool must match it.10.244.0.0/16
Node podCIDROne node's slice of the Pod CIDRspec.podCIDR on each Node. The controller manager fills it in when --allocate-node-cidrs=true.10.244.0.0/24, 10.244.1.0/24, …
Service CIDRService ClusterIPs. No network interface ever has these addresses.--service-cluster-ip-range on (networking.serviceSubnet in kubeadm)10.96.0.0/16
Read both ranges from the control plane
# Node shell. Lab: docker exec. Exam: ssh <control-plane-node>, then sudo -i if needed.
docker exec cka-control-plane grep -- --cluster-cidr /etc/kubernetes/manifests/kube-controller-manager.yaml
docker exec cka-control-plane grep -- --service-cluster-ip-range /etc/kubernetes/manifests/kube-apiserver.yaml

# Each node's own slice of the Pod range (not the cluster's Pod CIDR)
kubectl get nodes -o custom-columns=NAME:.metadata.name,PODCIDR:.spec.podCIDR

No node shell? The same flags are visible through the API too, as Control plane and node components shows.

How the CNI plugin connects a Pod

When a new Pod starts on a node, the calls the CNI plugin. The plugin does three jobs:

  1. 1.It plugs the Pod in. It creates a veth pair: a virtual network cable with two ends. One end becomes eth0 inside the Pod. The other end stays on the node; with Calico its name starts with cali.
  2. 2.It picks an address. Its IPAM part (IP address management) takes a free IP from the pool. The plugin gives the Pod that IP, and adds a route on the node that points to the veth.
  3. 3.It connects the nodes. It adds routes to the other nodes' Pod blocks. Calico here uses an IP-in-IP tunnel; many other setups use VXLAN. Both wrap the Pod's packet inside a packet between the two nodes.
A packet from Pod A to Pod B

Pod A

on cka-worker

10.244.89.67

Node cka-worker

the veth carries the packet out; a route sends it to the other node

Node cka-worker2

a route hands it to Pod B's veth

Pod B

sees Pod A's real IP

10.244.157.130

The CNI plugin builds every step: the veth pair into each Pod, and the routes between the nodes.

When the Pod is deleted, the plugin frees its IP again. CNI, CSI and CRI shows where the plugin's files live on the node, and why a node without them stays NotReady.

See it on a node
docker exec -it cka-worker bash          # exam: ssh <node>
ip -br link | grep cali                  # host ends of the veth pairs, one per local Pod
ip route                                 # one /32 per local Pod, one route per remote node's block
#   10.244.89.67 dev caliad73dda8ffa scope link        (a local Pod)
#   10.244.157.128/26 via 172.19.0.3 dev tunl0 onlink  (another node's block, IP-in-IP)

Find a Pod, then reach it

Most networking tasks start with three facts about a Pod: its name, its IP and its node. These commands print them.

Terminal
kubectl get pods -o wide                                     # IP and NODE columns
kubectl get pod web-0 -o jsonpath='{.status.podIP}{"\n"}'
kubectl get pod web-0 -o jsonpath='{.spec.nodeName}{"\n"}'
kubectl get pods -l tier=cache -o custom-columns=NAME:.metadata.name,IP:.status.podIP,NODE:.spec.nodeName

# A Pod IP is not stable. Delete the Pod and its replacement gets a new one,
# which is the whole reason Services exist.

To test a connection, start a small client Pod and call the other Pod's IP from inside it. busybox:1.36 makes a good client: it is tiny, and it has wget and nslookup.

Test connectivity from a client Pod
# Interactive: the one-liner you will type on the exam.
# --rm deletes the Pod afterwards; -T 3 stops wget waiting forever on a blocked port.
kubectl run tmp --image=busybox:1.36 --rm -it --restart=Never -- wget -qO- -T 3 http://10.244.89.67:8080/hostname

# Non-interactive (scripts, repeated checks): a long-lived client, then exec
kubectl run client --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl wait --for=condition=Ready pod/client --timeout=60s
kubectl exec client -- wget -qO- -T 3 http://10.244.89.67:8080/hostname
kubectl delete pod client --now

In the official docs· open on exam day too

Hands-on task 1 of 2nw-cni-1
~4 min3% weightNetworking

Record the Pod and Service address ranges

Find the address range this cluster allocates Pod IPs from, as configured on the control plane, and write it to /tmp/cka/pod-cidr.txt. Find the range Service ClusterIPs are allocated from and write it to /tmp/cka/service-cidr.txt. Each file must contain only the CIDR.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/nw-cni-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/nw-cni-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/nw-cni-1/cleanup | bash
Hands-on task 2 of 2nw-cni-2
~5 min4% weightNetworking

Locate a Pod and reach it by IP

Several Pods run in namespace nw-cni. For the Pod labeled tier=cache: write its Pod IP to /tmp/cka/cache-ip.txt and the name of the node it runs on to /tmp/cka/cache-node.txt. Then, from a temporary Pod using image busybox:1.36 in the same namespace, request http://<that IP>:8080/hostname and save the response body to /tmp/cka/cache-hostname.txt. Remove the temporary Pod afterwards.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/nw-cni-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/nw-cni-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/nw-cni-2/cleanup | bash

Finished this lesson?

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