Skip to content
LinkState
Go back

Fault-Injecting a Lost PodCIDR Advertisement

Introduction to Steady-State Hypothesis

Definition of Steady-State Hypothesis

A steady‑state hypothesis is a formal statement about the expected behavior of a system when no external perturbations are applied. In networking, it describes the stable equilibrium of control‑plane state (RIB, FIB, adjacency tables) and data‑plane forwarding under normal traffic loads. The hypothesis includes:

Importance of Steady-State Hypothesis in Network Stability

Establishing a steady‑state baseline lets an operator isolate the effect of a deliberate fault injection. By comparing the observed post‑fault state to the hypothesis, one can determine whether:

The hypothesis also defines the stop condition for the experiment: when the observed metrics (packet loss, latency, route churn) return to the values predicted by the hypothesis, the system has re‑stabilized.

Understanding CNI and Pod Reachability

Overview of Container Network Interface (CNI)

The Container Network Interface (CNI) is a specification and library suite that configures network namespaces for containers. A CNI plugin is invoked by the container runtime (e.g., containerd, cri‑o) with a JSON network configuration and is responsible for:

  1. Allocating an IP address from an IPAM plugin.
  2. Creating the necessary virtual interfaces (veth pair, bridge, macvlan, etc.).
  3. Programming the host’s forwarding tables (routes, ARP/NDP entries, firewall rules) so that the pod’s IP is reachable from other nodes.
  4. Cleaning up resources on pod deletion.

CNI does not prescribe a particular control‑plane protocol; the method by which pod reachability is advertised depends on the plugin (e.g., host‑local routes, BGP, VXLAN encapsulation, or SRv6).

Role of CNI in Pod Reachability and Network Stability

In a Kubernetes cluster, pod reachability is typically expressed as a route to the pod’s IP (or to the node’s pod CIDR) in each node’s routing table. The CNI plugin ensures that:

If the CNI fails to program or withdraw a route correctly, the control plane diverges from the forwarding plane, leading to packet loss, suboptimal paths, or forwarding loops.

CNI Plugins and Their Impact on Network Behavior

PluginForwarding MechanismAdvertisement MethodFailure Containment Characteristics
host‑local (bridge)Direct L2 via cni0 bridge; host adds /32 route for each pod IP via ip route add <pod‑ip>/32 dev <veth>No external advertisement; reachability relies on node‑local routingLoss is confined to the node; other nodes unaffected unless they rely on the node as a gateway.
Flannel (VXLAN)Encapsulates pod traffic in VXLAN; each node programs a FDB entry mapping pod IP → remote VTEPImplicit via the flannel daemon; routes point to the flannel interface (flannel.1)A missing VTEP entry causes traffic to be dropped; does not affect other nodes’ VTEP tables.
Calico (BGP)Uses host routes (/32 for each pod IP) and advertises them via BGP (node‑to‑node or route‑reflector)BGP UPDATE messages; withdrawal when Felix detects pod deletion or link lossBGP withdrawal propagates quickly; if a node stops advertising, only its prefixes disappear – containment is strong unless route‑reflector misconfiguration causes blackholing of other prefixes.
Cilium (eBPF + optional BGP)Programs eBPF/XDP maps for L3/L4 forwarding; can also advertise via BGPeBPF maps updated by agent; BGP optionaleBPF updates are local; loss is local unless BGP advertisement is suppressed.

Suppressing Node Pod Reachability Advertisement

Methods for Suppressing Pod Reachability Advertisement

Suppression can be achieved at different layers of the CNI stack:

  1. Remove the host route for the pod CIDR/IP (ip route del …).
  2. Disable the CNI plugin’s agent (e.g., stop calico-node, flanneld, or cilium-agent).
  3. Withdraw the route via the plugin’s control plane (e.g., calicoctl node status --withdraw, flannel subnet update).
  4. Block traffic with firewall rules (iptables -A OUTPUT -d <pod‑cidr> -j DROP).
  5. Misconfigure IPAM so the plugin believes the node has no allocatable IPs, causing it to withdraw existing routes.

For a controlled experiment, the most repeatable method is to programmatically delete the host route that the CNI installed, leaving the CNI agent running but unable to forward traffic for the affected prefixes.

Tools and Techniques for Simulating Network Failures

Example Code for Suppressing Pod Reachability using CLI

#!/usr/bin/env bash
set -euo pipefail

NODE_NAME="worker-3"
POD_CIDR="10.244.3.0/24"   # adjust to match your cluster's CIDR allocation

# Identify the node's internal IP (used for SSH or direct exec)
NODE_IP=$(kubectl get node "$NODE_NAME" -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}')

# SSH into the node and delete the host route for the pod CIDR
ssh "$NODE_IP" "sudo ip route del $POD_CIDR"

echo "Suppressed pod reachability advertisement for $NODE_NAME ($POD_CIDR)"

If the cluster uses Flannel, replace the ip route del with sudo ip link set dev flannel.1 down to bring the VXLAN interface down, which implicitly withdraws the learned remote VTEP entries.
For Cilium, you could run cilium status --delete-endpoints <label> to force endpoint removal, which causes the agent to withdraw the associated L3 routes.

Measuring Network Behavior and CNI Response

Monitoring Network Traffic and Pod Reachability

After suppression, the operator should verify:

Analyzing CNI Logs and Network Metrics

Key metrics to collect:

MetricCollection MethodExpected Steady‑State Value
Route count for pod CIDRip route show | grep -c <cidr>1 per node (the node’s own CIDR)
Packet loss to pod IPping -c 100 <pod-ip>0 %
RTT to pod IPping -c 10 <pod-ip>< 2 ms intra‑node, < 5 ms inter‑node (depends on topology)
Felix/Flannel/Cilium agent CPUtop -p $(pgrep felix)< 5 % steady
Route churn (updates/sec)watch -n 1 "ip -s route show"~0 updates/sec after convergence

Example CLI Commands for Monitoring Network Behavior

# 1. Verify route suppression on the target node
ssh worker-3 "ip route show | grep 10.244.3.0/24"
# Expected: no output (route removed)

# 2. Test reachability from a pod on another node
kubectl run -i --tty --rm debug --image=alpine --restart=Never -- \
  sh -c "apk add --no-cache iputils && \
         for i in {1..10}; do \
           ping -c 1 10.244.3.42 && echo 'OK' || echo 'LOSS'; \
         done"

# 3. Collect Felix logs (Calico)
ssh worker-3 "journalctl -u calico-felix -f | grep -i route"

# 4. Measure inter‑node RTT to a healthy pod for comparison
kubectl exec -it debug -- ping -c 5 10.244.1.10   # pod on worker-1

# 5. Export Prometheus metrics (if CNI exposes them)
curl http://worker-3:9090/metrics | grep

Share this post on:

Previous Post
Refactoring brittle ECMP policy into deterministic failover
Next Post
Why Identical Topologies Fail Only in CI