eBPF & Cilium Architecture
Cilium is a Kubernetes CNI plugin that leverages eBPF (extended Berkeley Packet Filter) to provide high-performance networking, security, and observability. Unlike traditional CNIs that rely on iptables chains, Cilium programs the Linux kernel directly using eBPF bytecode.
The core architectural differences from traditional CNIs:
- Kernel-level packet processing — eBPF programs attach at tc (traffic control) and XDP (eXpress Data Path) hooks, processing packets before they hit the full network stack
- Identity-based security — Pods get cryptographic identities based on labels rather than IP addresses, surviving pod restarts and rescheduling
- No iptables dependency — Eliminates the iptables bottleneck for service routing, NAT, and policy enforcement
- L7 awareness — eBPF programs can parse HTTP, gRPC, DNS, and Kafka protocols natively
Install Cilium
Cilium provides a CLI tool for installation and management. Install the CLI first, then deploy Cilium to your cluster:
# Install the Cilium CLI
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
GOOS=$(go env GOOS)
GOARCH=$(go env GOARCH)
curl -L --fail --remote-name-all \
https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-${GOOS}-${GOARCH}.tar.gz
sudo tar xzvfC cilium-${GOOS}-${GOARCH}.tar.gz /usr/local/bin
rm cilium-${GOOS}-${GOARCH}.tar.gz
# Install Cilium into the cluster
cilium install --version 1.16.0
# Verify the installation
cilium status --wait
# Expected: All components show "OK"
After installation, run the connectivity test to verify end-to-end functionality:
# Run the full connectivity test suite
cilium connectivity test
# This deploys test pods and validates:
# - Pod-to-Pod connectivity (same node and cross-node)
# - Pod-to-Service connectivity
# - Pod-to-external connectivity
# - Network policy enforcement
# - DNS resolution
CiliumNetworkPolicy
CiliumNetworkPolicy extends standard Kubernetes NetworkPolicy with L7 awareness, DNS-based rules, and identity-based selectors. It uses the same label-matching approach but adds powerful filtering capabilities.
A basic L3/L4 ingress policy restricting traffic to a backend service:
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
tier: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
tier: web
toPorts:
- ports:
- port: "8080"
protocol: TCP
- port: "8443"
protocol: TCP
Egress policy with CIDR-based rules for external access control:
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: backend-egress-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
# Allow DNS resolution
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
# Allow access to specific external CIDR
- toCIDR:
- 10.0.0.0/8
toPorts:
- ports:
- port: "5432"
protocol: TCP
# Deny all other egress (implicit with egress rules present)
Identity-Based Security
Cilium assigns numeric identities to groups of pods sharing the same security-relevant labels. These identities are cluster-wide and survive pod IP changes, making policies resilient to rescheduling.
# View Cilium identities assigned to endpoints
cilium endpoint list
# Check identity for a specific pod
kubectl exec -n kube-system cilium-xxxxx -- cilium identity list
# Example output:
# IDENTITY LABELS (source:key[=value])
# 1 reserved:host
# 2 reserved:world
# 4 reserved:health
# 12345 k8s:app=frontend, k8s:io.kubernetes.pod.namespace=production
# 12346 k8s:app=backend, k8s:io.kubernetes.pod.namespace=production
Policy using identity-aware selectors for cross-namespace communication:
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: allow-monitoring-scrape
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: prometheus
k8s:io.kubernetes.pod.namespace: monitoring
toPorts:
- ports:
- port: "9090"
protocol: TCP
kube-proxy Replacement
Cilium can fully replace kube-proxy for service load balancing, eliminating iptables rules for ClusterIP, NodePort, and LoadBalancer services. This provides O(1) service lookup via eBPF maps and enables Direct Server Return (DSR) mode.
# Install Cilium with kube-proxy replacement enabled
cilium install --version 1.16.0 \
--set kubeProxyReplacement=true \
--set k8sServiceHost=${API_SERVER_IP} \
--set k8sServicePort=${API_SERVER_PORT}
# Enable DSR mode for improved performance (skip reverse NAT on return path)
cilium install --version 1.16.0 \
--set kubeProxyReplacement=true \
--set loadBalancer.mode=dsr \
--set k8sServiceHost=${API_SERVER_IP} \
--set k8sServicePort=${API_SERVER_PORT}
# Verify kube-proxy replacement is active
cilium status | grep KubeProxyReplacement
# Expected: KubeProxyReplacement: True [eth0 (Direct Routing)]
# Remove kube-proxy DaemonSet (no longer needed)
kubectl -n kube-system delete ds kube-proxy
kubectl -n kube-system delete cm kube-proxy
Exercises
cilium connectivity test and kubectl exec curl tests.
app=external-client to reach only api.example.com (use toFQDNs for DNS-based filtering). Block all other external traffic. Test by exec-ing into the pod and running curl against allowed and blocked domains.
kubeProxyReplacement=true on a fresh Kind or k3s cluster. Deploy a NodePort service and verify traffic flows correctly. Compare the number of iptables rules (iptables-save | wc -l) with and without kube-proxy replacement.
Key Takeaways & Next Steps
- Cilium uses eBPF for kernel-level packet processing, eliminating iptables overhead
- CiliumNetworkPolicy supports L3/L4 rules with identity-based selectors and CIDR filtering
- Identities are label-based and IP-independent, surviving pod rescheduling
- kube-proxy replacement provides O(1) service routing with optional DSR mode
- The connectivity test validates the entire networking stack end-to-end
Next in the Series
In Part 2: Hubble & L7 Observability, we'll enable Hubble for network flow visibility, explore L7 protocol-aware policies for HTTP and gRPC, and set up Prometheus metrics from eBPF.