Skip to main content

Cilium — eBPF-Based Networking & Observability

Cilium replaces the default k3s CNI (Flannel) and kube-proxy with an eBPF-based data plane. It runs directly in the Linux kernel — faster, more observable, and capable of things traditional networking stacks cannot do.


Why Cilium Over Default Flannel

Flannel + kube-proxyCilium
Data planeiptables (user space)eBPF (kernel)
PerformanceBaselineUp to 2x faster
Network policiesBasicRich L3/L4/L7 policies
mTLS between podsNoYes (built-in)
Traffic visibilityNoneHubble UI (full flow map)
Load balancingkube-proxyeBPF (replaces kube-proxy)

Hubble UI Preview

Cilium includes Hubble — a real-time network traffic visualizer showing which pod is talking to which, with latency and error rates:

┌─────────────────────────────────────────────┐
│ Hubble UI │
│ │
│ [frontend] ──────→ [backend] │
│ │ │ │
│ └──────→ [redis] └──→ [postgres] │
│ │
│ Flows: 1,243/s Drops: 0 Errors: 0 │
└─────────────────────────────────────────────┘

Install Cilium (replaces Flannel)

warning

This replaces the existing CNI. Do this on a fresh k3s install or be prepared to reinstall k3s.

Install k3s without default CNI

# On set-hog (control plane) — fresh install
curl -sfL https://get.k3s.io | sh -s - \
--flannel-backend=none \
--disable-network-policy \
--disable=traefik

Install Cilium CLI

curl -L --remote-name-all \
https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz

sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin

Deploy Cilium

cilium install \
--set k8sServiceHost=10.0.0.2 \
--set k8sServicePort=6443 \
--set kubeProxyReplacement=true \
--set ipam.mode=kubernetes

cilium status --wait

Enable Hubble (Observability)

cilium hubble enable --ui

# Port-forward the UI
cilium hubble ui

Opens http://localhost:12000 — a live flow map of all traffic in the cluster.


Enable Hubble CLI

export HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --remote-name-all \
https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz
sudo tar xzvfC hubble-linux-amd64.tar.gz /usr/local/bin

cilium hubble port-forward &
hubble observe --follow

Real-time stream of all network flows across the cluster.


Network Policy Example (L7)

Cilium can enforce policies at HTTP level — not just IP/port:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-get-only
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: GET
path: "/api/.*"

This allows frontend to call GET /api/* on backend — and nothing else. iptables cannot do this.


Done When

✔ cilium status shows all green
✔ kubectl get pods -n kube-system shows cilium pods Running
✔ Hubble UI shows live traffic flows
✔ kube-proxy replaced (verify: no kube-proxy pods running)