Architecture Decision Record

ADR 008: Cilium as the CNI, with kube-proxy Replaced

eBPF networking with kube-proxy fully replaced, and an egress "lanes" model that makes internet access an explicit, reviewable choice.

Status: Accepted  ·  Date: Nov 2025  ·  ← All ADRs


Context

Talos ships with Flannel by default, and it works — so this was a decision to replace a working default, not to fill a hole. (The k0s-era cluster likely defaulted to Flannel too; I did little with the CNI back then and it didn’t much matter.) What changed the calculus was two things I actually wanted: real network policy, and the move to Istio ambient mode (ADR 009) — where Cilium turned out to be a powerful ally rather than just a CNI. To run it, I set Talos to cni: none and proxy.disabled: true and let Cilium own both jobs.

Options:

Decision

Cilium as the sole CNI, running in kube-proxy replacement mode (there is no kube-proxy on the cluster at all), with cni.exclusive: false so it chains correctly with Istio’s CNI plugin. Hubble relay and UI are enabled.

Bootstrap ordering matters: Cilium is installed once, immediately after Talos bootstrap, via helm template | kubectl apply — deliberately not helm install, so no Helm release object exists to conflict with ArgoCD, which adopts and manages the same resources from its first sync onward.

Reasoning

Tradeoffs

Outcome

Egress denial is the default posture for application namespaces. Policy lives in Git next to the workloads it governs, and Hubble provides the evidence when a policy is wrong. Cilium has survived Talos upgrades and the Istio ambient rollout intact.