Pod Network Connectivity
CKA Domain 3 — Pod network communication mechanisms, kube-proxy modes and CNI plugin comparison
Overview
Kubernetes networking model requirements:
- All Pods can communicate directly with each other without NAT
- All nodes can communicate directly with all Pods without NAT
- The IP address a Pod sees for itself is the same as what other Pods see for it
1. Intra-Pod Container Communication
All containers within a Pod share the same network namespace.
┌─────────────────────────────┐
│ Pod │
│ ┌─────────┐ ┌─────────┐ │
│ │ Container│ │ Container│ │
│ │ App A │ │ App B │ │
│ │ localhost:8080 │ │
│ └─────────┘ └─────────┘ │
│ lo interface │
│ eth0: 10.244.1.5 │
└─────────────────────────────┘
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
- name: sidecar
image: busybox:1.28
command: ["sleep", "3600"]
# sidecar can access nginx via localhost:80
Key Points:
- Communicate via
localhost - Share the same IP address and port space
- Can access each other without needing a Service
2. Pod Communication on the Same Node
Pods on the same node communicate through the node's network bridge (typically cbr0 or a bridge created by the CNI).
┌───────────── Node ─────────────┐
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Pod A │ │ Pod B │ │
│ │ veth pair│ │ veth pair│ │
│ └────┼────┘ └────┼────┘ │
│ │ │ │
│ ┌──┴───────────┴──┐ │
│ │ cni0 (bridge) │ │
│ └────────┬─────────┘ │
│ │ eth0 │
│ Node IP: 192.168.1.10 │
└────────────────────────────────┘
- Pods connect to the bridge via virtual Ethernet pairs (veth pairs)
- Communication happens directly through the bridge, no encapsulation needed
- Low latency, good performance
3. Cross-Node Pod Communication
Cross-node Pod communication relies on the CNI plugin's overlay network implementation.
┌────── Node 1 ──────┐ ┌────── Node 2 ──────┐
│ Pod A: 10.244.1.5 │ │ Pod C: 10.244.2.7 │
│ │ │ │ │ │
│ ┌──┴──┐ │ │ ┌──┴──┐ │
│ │cni0 │ │ │ │cni0 │ │
│ └──┬──┘ │ │ └──┬──┘ │
│ │ │ │ │ │
│ eth0: 192.168.1.10 │ │ eth0: 192.168.2.10│
└────────┬───────────┘ └────────┬───────────┘
│ │
└──── Overlay (VXLAN) ───┘
or direct routing
4. Service ClusterIP Communication Mechanism
When Pods communicate via Service ClusterIP, kube-proxy is responsible for forwarding traffic to backend Pods.
kube-proxy Modes
iptables Mode (default)
# View iptables rules
kubectl get svc
# On the node, view iptables rules for the Service
sudo iptables -t nat -L -n | grep <cluster-ip>
# View the KUBE-SERVICES chain
sudo iptables -t nat -L KUBE-SERVICES -n
# View a specific Service rule chain
sudo iptables -t nat -L KUBE-SVC-XXXXXXXX -n
# View Endpoints load balancing rules
sudo iptables -t nat -L KUBE-SEP-XXXXXXXX -n
iptables Forwarding Flow:
PREROUTING→KUBE-SERVICES- Match ClusterIP destination → jump to the corresponding
KUBE-SVC-*chain KUBE-SVC-*chain performs random load balancing → jumps toKUBE-SEP-*chainKUBE-SEP-*chain performs DNAT → replaces destination IP with Pod IP
Characteristics:
- Default mode, mature and stable
- Number of rules is proportional to the number of Services + Endpoints
- Rule updates can become slow at large scale
IPVS Mode (recommended for large-scale clusters)
# Check current kube-proxy mode
kubectl get configmap -n kube-system kube-proxy -o yaml | grep mode
# Switch to IPVS mode (modify ConfigMap)
kubectl edit configmap -n kube-system kube-proxy
# Set mode: ipvs
# Restart kube-proxy
kubectl rollout restart -n kube-system daemonset kube-proxy
# View IPVS rules
sudo ipvsadm -L -n
# View IPVS connections
sudo ipvsadm -L -n -c
Characteristics:
- Based on the kernel's IPVS module
- More efficient: hash table lookup, O(1) time complexity
- Supports more load balancing algorithms (rr, wrr, lc, wlc, sh, dh, etc.)
- Suitable for large-scale clusters (thousands of Services)
Load Balancing Algorithms:
| Algorithm | Description |
|---|---|
rr | Round Robin (default) |
wrr | Weighted Round Robin |
lc | Least Connections |
wlc | Weighted Least Connections |
sh | Source Hashing |
dh | Destination Hashing |
5. CNI Plugin Comparison
| Feature | Calico | Flannel | Weave | Cilium |
|---|---|---|---|---|
| Base Technology | BGP + iptables | VXLAN/Host-GW | VXLAN/Weave Mesh | eBPF |
| NetworkPolicy | Full support | Limited support (needs additional plugins) | Full support | Full support |
| Encryption | WireGuard optional | Not built-in | Built-in encryption | WireGuard optional |
| Performance | High | Medium | Medium-low | Very high |
| Complexity | Medium | Low | Low | Medium-high |
| Recommended Scenario | Production, needs NetworkPolicy | Small cluster, simple networking | Small to medium clusters | High-performance production |
| eBPF | Supported (eBPF mode) | Not supported | Not supported | Native eBPF |
Installing Calico (CKA Focus)
# Install Calico (via Tigera Operator)
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/tigera-operator.yaml
# Configuration file
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/custom-resources.yaml
# Wait for all Pods to be ready
kubectl get pods -n calico-system -w
Installing Flannel
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
6. Network Troubleshooting Commands
Connectivity Testing
# Use busybox to test network connectivity
kubectl run test-pod --image=busybox:1.28 --rm -it --restart=Never -- wget -qO- http://<service-ip>
# Use netshoot (recommended, includes more tools)
kubectl run netshoot --image=nicolaka/netshoot --rm -it --restart=Never -- curl http://my-svc:80
# Test DNS resolution
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup my-svc
# Test direct Pod IP communication
kubectl run test-pod --image=busybox:1.28 --rm -it --restart=Never -- sh
# Inside the container
ping <target-pod-ip>
wget -qO- http://<target-pod-ip>:8080
Network Diagnostic Tool Pod
apiVersion: v1
kind: Pod
metadata:
name: network-tools
spec:
containers:
- name: netshoot
image: nicolaka/netshoot
command: ["sleep", "3600"]
# Enter the container after creation
kubectl exec -it network-tools -- sh
# The following tools are available inside the container
curl http://my-svc:80
dig my-svc.default.svc.cluster.local
nslookup kubernetes.default
ping 10.96.0.1
traceroute 10.244.1.5
mtr 10.244.1.5
tcpdump -i eth0
ip addr
ip route
ss -tunap
Node-Level Troubleshooting
# View kube-proxy logs
kubectl logs -n kube-system -l k8s-app=kube-proxy
# View node routing table
ip route show
# View bridges
brctl show
ip link show type bridge
# View network interfaces and veth pairs
ip link
# View iptables NAT rules (run on the node)
sudo iptables-save | grep <service-name>
🧪 Complete Hands-On Example: Verify Cross-Node Pod Connectivity
Scenario
In a multi-node cluster, create Pods on different nodes and verify they can communicate directly via Pod IP and also perform service discovery via Service ClusterIP.
Prerequisites
- Cluster has at least 2 available nodes
- CNI plugin is working properly on all nodes
- kubectl is configured with cluster access
Steps
Step 1: View cluster node topology
# View node list and labels
kubectl get nodes -o wide
# NAME STATUS ROLES INTERNAL-IP OS-IMAGE
# node-1 Ready <none> 192.168.1.10 Ubuntu 22.04
# node-2 Ready <none> 192.168.1.20 Ubuntu 22.04
# View node labels, determine which labels can be used to schedule Pods
kubectl get nodes --show-labels
# Record node names for subsequent scheduling
Step 2: Create Pod on Node 1
# Create Pod on node-1 using nodeName to force scheduling
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: pod-node1
labels:
app: test
node: node1
spec:
nodeName: node-1 # Force scheduling to node-1
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
EOF
# Expected output: pod/pod-node1 created
# Verify Pod is running on node-1
kubectl get pod pod-node1 -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# pod-node1 1/1 Running 0 10s 10.244.1.10 node-1
Step 3: Create Pod on Node 2
# Create Pod on node-2
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: pod-node2
labels:
app: test
node: node2
spec:
nodeName: node-2
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
EOF
# Expected output: pod/pod-node2 created
# Verify Pod is running on node-2
kubectl get pod pod-node2 -o wide
# NAME READY STATUS RESTARTS AGE IP NODE
# pod-node2 1/1 Running 0 10s 10.244.2.20 node-2
Step 4: Cross-node direct communication via Pod IP
# Record both Pod IPs
POD1_IP=$(kubectl get pod pod-node1 -o jsonpath='{.status.podIP}')
POD2_IP=$(kubectl get pod pod-node2 -o jsonpath='{.status.podIP}')
echo "Pod1 IP: $POD1_IP, Pod2 IP: $POD2_IP"
# Expected output: Pod1 IP: 10.244.1.10, Pod2 IP: 10.244.2.20
# Access pod-node2 from pod-node1 (cross-node)
kubectl exec pod-node1 -- curl -s -m 5 http://$POD2_IP
# Expected output: nginx welcome page HTML
# Access pod-node1 from pod-node2 (reverse cross-node)
kubectl exec pod-node2 -- curl -s -m 5 http://$POD1_IP
# Expected output: nginx welcome page HTML
# Test ICMP connectivity with ping (some CNIs may block ICMP)
kubectl exec pod-node1 -- ping -c 2 $POD2_IP
# Expected output: 2 packets transmitted, 2 received (may timeout depending on CNI config)
Step 5: Cross-node communication via Service ClusterIP
# Create Service to expose both Pods
kubectl expose pod pod-node1 --name=test-svc --port=80 --target-port=80
# Or use label selector
kubectl create service clusterip test-svc --tcp=80:80
# Manually set selector to point to both Pods
kubectl patch svc test-svc -p '{"spec":{"selector":{"app":"test"}}}'
# Expected output: service/test-svc patched
# View Service ClusterIP
kubectl get svc test-svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# test-svc ClusterIP 10.96.200.50 <none> 80/TCP 10s
SVC_IP=$(kubectl get svc test-svc -o jsonpath='{.spec.clusterIP}')
echo "Service ClusterIP: $SVC_IP"
# Expected output: Service ClusterIP: 10.96.200.50
# Access from pod-node1 via Service name (DNS resolution)
kubectl exec pod-node1 -- curl -s -m 5 http://test-svc
# Expected output: nginx welcome page HTML
# Access from pod-node2 via Service ClusterIP
kubectl exec pod-node2 -- curl -s -m 5 http://$SVC_IP
# Expected output: nginx welcome page HTML
Step 6: Complete network debugging workflow
# Create a diagnostic Pod with full network tools
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: network-debug
spec:
containers:
- name: netshoot
image: nicolaka/netshoot
command: ["sleep", "3600"]
EOF
# Expected output: pod/network-debug created
# Enter the diagnostic Pod
kubectl exec -it network-debug -- sh
# Run the following debug commands inside the diagnostic container:
# 1. IP and routing information
ip addr
ip route
# 2. DNS resolution test
dig test-svc.default.svc.cluster.local
nslookup kubernetes.default
# 3. Connectivity test
curl -m 5 http://$POD1_IP # Access pod-node1
curl -m 5 http://$POD2_IP # Access pod-node2
curl -m 5 http://test-svc # Access via Service DNS
# 4. Trace route
traceroute $POD2_IP
# 5. Packet capture (optional)
tcpdump -i eth0 -c 10
# Exit container
exit
Verification
# Check Endpoints to confirm Service backends
kubectl get endpoints test-svc
# NAME ENDPOINTS AGE
# test-svc 10.244.1.10:80,10.244.2.20:80 2m
# On the node, view iptables forwarding rules (requires sudo)
# sudo iptables -t nat -L KUBE-SERVICES -n | grep $SVC_IP
# View kube-proxy logs (when troubleshooting Service issues)
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=10
# Clean up resources
kubectl delete pod pod-node1 pod-node2 network-debug
kubectl delete svc test-svc
Exam Tips
-
K8s networking model core: All Pods can communicate directly without NAT, regardless of whether they are on the same node
-
nodeNameis the simplest way to force schedule to a specific node (no need to handle taint/toleration) -
Cross-node communication depends on CNI (Overlay like VXLAN / direct routing like Calico BGP). If it is not working, first check CNI Pod status
-
ping may not always work: Some CNIs or Network Policies block ICMP. Prefer
curlorwgetfor testing -
Service debugging three-step method: ①
kubectl get endpointsconfirm backends ②kubectl exectest Service DNS ③ check kube-proxy -
Recommended diagnostic tool:
nicolaka/netshootimage includes curl, dig, tcpdump, traceroute, and a full suite of network tools -
https://kubernetes.io/docs/concepts/cluster-administration/networking/
-
https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
-
https://kubernetes.io/docs/concepts/services-networking/cluster-networking/
-
https://kubernetes.io/docs/tasks/debug/debug-application/debug-service/
-
https://kubernetes.io/docs/reference/networking/virtual-ips/