Reference¶
Scope
Look-up facts for Cilium: versions and support windows, Kubernetes and kernel requirements, ports, key Helm values and defaults, eBPF map limits, feature maturity, deprecations and removals, IPAM and routing modes, and performance/scale figures. Everything here was checked against the v1.20 release branch of cilium/cilium on 2026-09-25 unless stated otherwise. For why things work this way see Explanation; for tasks see How-to Guides.
Release and Support Matrix¶
Cilium ships a feature release (X.Y.0) about every six months and keeps three stable branches (the latest minor plus the two before it). Patch releases for all maintained branches usually land around the middle of each month. Pre-releases of main come out monthly. Dates below are the publication times of the Helm charts in the cilium/charts index (UTC).
| Branch | First release | Latest patch (date) | Status (2026-09-25) |
|---|---|---|---|
| 1.21 | Not released; no date published (about early 2027 if the ~6-month cadence holds) | 1.21.0-pre.2 (2026-09-09) |
Development (main reports 1.21.0-dev) |
| 1.20 | 2026-07-29 | 1.20.2 (2026-09-15) | Current stable (stable.txt = v1.20.2) |
| 1.19 | 2026-02-04 | 1.19.8 (2026-09-16) | Maintained |
| 1.18 | 2025-07-29 | 1.18.14 (2026-09-15) | Maintained (oldest supported) |
| 1.17 | 2025-02-04 | 1.17.18 (2026-07-16) | End of life (dropped when 1.20 shipped) |
Upgrade rule
Only upgrades and rollbacks between consecutive minor releases are tested. Move to the latest patch of your current minor first, then go up one minor at a time (for example 1.18.14 -> 1.19.8 -> 1.20.2).
Related tools:
| Component | Latest (date) | Where to check |
|---|---|---|
| cilium-cli | v0.20.1 (2026-09) | https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt |
| Hubble CLI | v1.19.4 (2026-09) | https://raw.githubusercontent.com/cilium/hubble/main/stable.txt |
| Tetragon (Helm chart) | 1.7.1 (2026-08-25) | helm search repo cilium/tetragon |
| cilium-envoy | v1.37.x in Cilium 1.20 | Cilium 1.20 CHANGELOG |
Kubernetes Compatibility¶
Versions listed are the ones e2e-tested for each Cilium minor. Newer Kubernetes versions depend on Kubernetes backward compatibility.
| Cilium | Tested Kubernetes versions |
|---|---|
| 1.20 | 1.33, 1.34, 1.35, 1.36 |
| 1.19 | 1.31, 1.32, 1.33, 1.34 |
| 1.18 | 1.30, 1.31, 1.32, 1.33 |
System Requirements¶
| Requirement | Minimum (Cilium 1.18 - 1.20) | Notes |
|---|---|---|
| Linux kernel | >= 5.10 (or 4.18 on RHEL 8.10) | Cilium 1.16 and 1.17 accepted >= 5.4. The rise to 5.10 came in 1.18 |
| CPU architecture | AMD64, AArch64 | Images are built for both |
| clang/LLVM | >= 18.1 | Only when running cilium-agent natively. Already in the cilium/cilium image |
| etcd (optional kvstore) | >= 3.1.0 | CRD-based identity is the default. A kvstore helps very large clusters |
| Privileges | CAP_SYS_ADMIN (or root/privileged), host network namespace |
Granted automatically by the DaemonSet |
| BPF filesystem | /sys/fs/bpf |
Auto-mounted if missing. Keeps maps across agent restarts |
| cgroup v2 | Mounted at /run/cilium/cgroupv2 by default |
Needed for socket-level load balancing |
Features that need newer kernels:
| Feature | Minimum kernel |
|---|---|
| Multicast (AMD64) | 5.10 |
| IPv6 BIG TCP | 5.19 |
| Multicast (AArch64) | 6.0 |
| IPv4 BIG TCP | 6.3 |
| netkit device mode | 6.8 |
| WireGuard (in-tree) | 5.6 (or out-of-tree module) |
Distributions documented as known to work: Amazon Linux 2, Bottlerocket, CentOS >= 8.6, Container-Optimized OS >= 85, Debian >= 10, Fedora CoreOS, Flatcar, LinuxKit, openSUSE (Tumbleweed, Leap >= 15.4), RHEL >= 8.6, RHCOS >= 4.12, Talos >= 1.5.0, Ubuntu >= 20.04.
Ports¶
| Port / protocol | Component |
|---|---|
| 4240/tcp | cilium-health cluster health checks (ICMP echo is the alternative) |
| 4244/tcp | Hubble server (per node) |
| 4245/tcp | Hubble Relay |
| 4250/tcp | Mutual authentication (deprecated feature) |
| 4251/tcp | SPIRE agent health check (localhost) |
| 6060, 6061, 6062/tcp | pprof: agent, operator, Hubble Relay (localhost) |
| 8472/udp | VXLAN overlay (Linux default) |
| 6081/udp | Geneve overlay |
| 51871/udp | WireGuard tunnel endpoint |
| 9878, 9879/tcp | cilium-envoy health, agent health API (localhost) |
| 9890, 9891, 9893/tcp | gops: agent, operator, Hubble Relay (localhost) |
| 9901/tcp | cilium-envoy admin API (localhost) |
| 9962, 9963, 9964/tcp | Prometheus metrics: agent, operator, cilium-envoy |
| 15008/tcp | HBONE, used by ztunnel encryption (beta) |
| ESP (IP proto 50) | IPsec encryption. AWS security groups block it by default |
| 2379-2380/tcp | etcd (kvstore mode) |
Cilium also reserves routing table IDs 200 (IPsec), 202 (VTEP), 2004 and 2005 (proxy), and 10 + <ENI index> in ENI IPAM mode.
Key Helm Values¶
Chart: cilium/cilium from https://helm.cilium.io/ or oci://quay.io/cilium/charts/cilium (OCI charts, cosign-signed, since 1.19). Defaults are from install/kubernetes/cilium/values.yaml on the v1.20 branch.
| Helm value | Default | Purpose |
|---|---|---|
kubeProxyReplacement |
"false" |
true = full eBPF kube-proxy replacement. false still load-balances ClusterIP per packet |
k8sServiceHost / k8sServicePort |
"" |
API server address. Needed when kube-proxy is removed |
k8s.apiServerURLs |
unset | Several API servers for agent fail-over (replaces removed --k8s-api-server) |
routingMode |
tunnel |
tunnel or native |
tunnelProtocol |
vxlan |
vxlan or geneve |
autoDirectNodeRoutes |
false |
Install direct routes between nodes on the same L2 (native routing) |
ipv4NativeRoutingCIDR |
"" |
CIDR that should not be masqueraded in native routing |
ipam.mode |
cluster-pool |
cluster-pool, kubernetes, multi-pool, eni, azure, alibabacloud, delegated-plugin |
bpf.masquerade |
false |
eBPF masquerading instead of iptables |
bpf.hostLegacyRouting |
false |
false = eBPF host routing when the kernel supports it |
bpf.datapathMode |
veth |
veth, netkit, netkit-l2, auto (1.20+) |
bpf.mapDynamicSizeRatio |
0.0025 |
Share of node memory used to size the large maps (CT, NAT, neighbor) |
bpf.ctTcpMax |
524288 |
TCP connection-tracking entries |
bpf.policyMapMax |
16384 |
Policy entries per endpoint |
bpf.lbMapMax |
65536 |
Service/backend map entries |
bpf.tproxy |
false |
eBPF TPROXY (beta). Not compatible with netkit |
loadBalancer.algorithm |
random |
random or maglev |
loadBalancer.mode |
snat |
snat, dsr, hybrid |
loadBalancer.acceleration |
disabled |
XDP acceleration: disabled, native, best-effort |
socketLB.enabled |
false |
Socket-level (connect-time) load balancing. Turned on by kube-proxy replacement |
hubble.enabled |
true |
Hubble server on each agent |
hubble.relay.enabled / hubble.ui.enabled |
false / false |
Cluster-wide flow API and web UI |
envoy.enabled |
true for new installs |
Run Envoy as the standalone cilium-envoy DaemonSet |
l7Proxy |
true |
Needed for L7 policy, Ingress and Gateway API |
gatewayAPI.enabled |
false |
Gateway API controller (needs kubeProxyReplacement=true) |
ingressController.enabled |
false |
Kubernetes Ingress controller |
encryption.enabled / encryption.type |
false / ipsec |
ipsec, wireguard, or ztunnel (beta) |
bgpControlPlane.enabled |
false |
BGP control plane (CiliumBGP* v2 CRDs) |
l2announcements.enabled |
false |
ARP/NDP announcements for LoadBalancer IPs |
egressGateway.enabled |
false |
Egress gateway (static egress IPs) |
bandwidthManager.enabled / .bbr |
false / false |
EDT-based pod rate limiting, optional BBR |
cluster.name / cluster.id |
default / 0 |
Must be unique per cluster for Cluster Mesh (ID 1-255, or 1-511) |
clustermesh.maxConnectedClusters |
255 |
511 halves cluster-local identities. Can only be set at install |
operator.replicas |
2 |
cilium-operator replicas |
policyEnforcementMode |
default |
default, always, never |
configDriftDetection.enabled |
enabled | ConfigMap drift detection and metric (1.20+) |
eBPF Map Limits¶
Default capacities from the Cilium eBPF maps documentation (v1.20). Going past a limit makes insertions fail, which caps datapath scale.
| Map | Scope | Default limit | Scale implication |
|---|---|---|---|
| Connection tracking | node | 512k TCP / 256k UDP | Concurrent connections per node |
| NAT | node | 512k | NAT entries per node |
| Neighbor table | node | 512k | Neighbor entries |
| Endpoints | node | 64k | Local endpoints + host IPs per node |
| IP cache | node | 512k | Endpoints across all clusters |
| Service load balancer | node | 64k | About 3k ClusterIP/NodePort services across all clusters |
| Service backends | node | 64k | Unique backends across all services |
| Policy | endpoint | 16k | Allowed identity + port + protocol pairs per endpoint |
| Egress policy | node | 16k | Endpoints across all egress-gateway destination CIDRs |
| Node | node | 16k | Distinct node IPs across all clusters |
| IPv4/IPv6 fragmentation | node | 8k | Fragmented datagrams in flight |
| Auth | node | 512k | Authenticated relations (mutual auth) |
Override flags: --bpf-ct-global-tcp-max, --bpf-ct-global-any-max, --bpf-nat-global-max, --bpf-neigh-global-max, --bpf-policy-map-max, --bpf-lb-map-max, --bpf-fragments-map-max, --bpf-auth-map-max. --bpf-map-dynamic-size-ratio sizes the CT, NAT, neighbor and reverse-socket maps from total memory (0.0025 = 0.25%). The NAT table must not exceed 2/3 of the combined CT size.
eBPF Map Types Used¶
| Map Type | Purpose |
|---|---|
| Hash map | Policy rules, service → endpoint mapping |
| LRU hash | Conntrack entries (connection state) |
| Array | Per-CPU counters, configuration |
| Perf event array / ring buffer | Datapath events to the agent (monitor, Hubble). Ring-buffer support added in 1.18 |
| LPM trie | CIDR-based policy matching, IP cache |
Gateway API Support¶
| Cilium | Gateway API version | Notes |
|---|---|---|
| 1.20 | v1.6.1 (minimum) | TLSRoute moved to v1. Adds TCPRoute, UDPRoute, ListenerSet, ExternalAuth filter (GEP-1494), CORS, BackendTLSPolicy |
| 1.19 | v1.4 | GAMMA supports GRPCRoute as well as HTTPRoute |
| 1.18 | v1.3.0 |
Resources supported in 1.20: GatewayClass, Gateway, HTTPRoute, GRPCRoute, TLSRoute, BackendTLSPolicy, ReferenceGrant, ListenerSet, TCPRoute, UDPRoute, plus the CiliumGatewayClassConfig CRD for parametersRef. TCPRoute, UDPRoute and ListenerSet CRDs are optional. If they are missing, Cilium turns those features off.
TLSRoute upgrade trap (1.20)
If you install the Standard v1.6 TLSRoute CRD over existing v1alpha2 objects, the API server can no longer read them from etcd and they effectively disappear. Back up TLSRoutes and install the Experimental v1.6.1 TLSRoute CRD (which still serves v1alpha2) before upgrading Cilium to 1.20.
Prerequisites: kubeProxyReplacement=true, l7Proxy=true, and either LoadBalancer Service support or host-network mode (since 1.16). With the default bpf.tproxy=false, nodes need iptables TPROXY modules.
Feature Maturity¶
| Feature | Status (1.20) | Since / notes |
|---|---|---|
| Multi-Pool IPAM | Stable | Promoted in 1.19 |
| MCS-API (Cluster Mesh) | Stable | Promoted in 1.20. Uses v1beta1 CRDs (v1alpha1 still works) |
| Kubernetes ClusterNetworkPolicy (KCNP) | New in 1.20 | From SIG Network Policy API |
PreferSameZone / PreferSameNode traffic distribution |
New in 1.20 | |
| ztunnel transparent encryption (mTLS) | Beta | Added 1.19. Namespaces opt in with label io.cilium/mtls-enabled=true |
| netkit datapath | Beta | Kernel >= 6.8 plus eBPF host routing. auto mode added in 1.20 |
eBPF TPROXY (bpf.tproxy) |
Beta | Removes the iptables dependency for Gateway/L7 |
| ENI IPAM with IPv6 prefixes | Beta | New in 1.20 |
| Datapath plugins (third-party extensions) | Beta | New in 1.20 |
| IPsec / WireGuard strict mode | Available | Added in 1.19 |
| Mutual authentication (SPIFFE/SPIRE) | Beta, deprecated in 1.20 | Replacement suggested: ztunnel encryption |
| Kafka L7 policy, Envoy Go extensions (proxylib) | Removed in 1.20 | Deprecated in 1.18 |
| Docker libnetwork plugin | Removed in 1.20 | |
| Local REST policy API | Deprecated in 1.18 | Removal announced for a later release |
Deprecations and Removals (1.20)¶
| Item | Change | Action |
|---|---|---|
kafka, l7, l7proto rules in CNP/CCNP |
Removed | Delete those rules sections before upgrading |
CiliumNodeConfig cilium.io/v2alpha1 |
Removed | Use cilium.io/v2 (available since 1.16) |
clustermesh.enableMCSAPISupport |
Removed | Use clustermesh.mcsapi.enabled |
--node-port-algorithm, --node-port-mode |
Removed | Use loadBalancer.algorithm, loadBalancer.mode |
encryption.strictMode.* (old keys) |
Removed | Use encryption.strictMode.egress.* |
--k8s-api-server |
Removed | Use k8s.apiServerURLs |
encryption.ipsec.interface, encryption.ipsec.encryptedOverlay |
Removed | No-ops before removal |
hubble.redact.kafka.apiKey |
Removed | Part of dropping Kafka |
hubble.preferIpv6 |
Deprecated | Use top-level preferIpv6 |
dnsProxy.preCache (--tofqdns-pre-cache) |
Deprecated | Removal planned in 1.21 |
cilium-dbg bgp / REST BGP listing |
Deprecated | Use cilium-dbg shell -- bgp/* |
Empty CNP/CCNP (no spec/specs) |
Now rejected at admission (CEL) | Fix manifests |
| Cluster Mesh auto certificates | Default validity cut to 1 year | Upgrade at least yearly (helm mode) or use cronJob/certmanager |
| CNI spec version | Default now 1.0.0 |
Update custom CNI configs |
IPAM Modes¶
| Mode | How it works | When to use |
|---|---|---|
| Cluster Pool (Helm default) | Cilium Operator allocates per-node CIDRs from a configured pool and records them in CiliumNode resources. |
Default for new installs. Environments where kube-controller-manager does not allocate CIDRs |
| Kubernetes | Uses the Node resource .spec.podCIDR set by kube-controller-manager (--allocate-node-cidrs). |
Clusters where Kubernetes already allocates node CIDRs |
| Multi-Pool | Several CiliumPodIPPool pools, chosen per pod or namespace. Stable since 1.19. 1.20 adds migration from cluster-pool and allowFirstIP/allowLastIP. |
Several IP ranges, per-tenant pools |
| ENI | Allocates AWS Elastic Network Interface IPs (or prefixes) directly to pods. IPv6 prefixes in beta since 1.20. | AWS EKS or self-managed AWS clusters |
| Azure IPAM | Allocates IPs from Azure VNet subnets directly to pods. | Azure (self-managed). AKS uses its own "Azure CNI Powered by Cilium" integration |
| AlibabaCloud | Allocates ENI IPs on Alibaba Cloud. | Alibaba Cloud |
| Delegated plugin | Delegates IPAM to another CNI IPAM plugin (IPv6 supported since 1.18). | Chaining setups |
Routing Modes¶
| Mode | Description | When to use |
|---|---|---|
| Tunnel (VXLAN/Geneve) (default, VXLAN) | Encapsulates pod traffic in VXLAN (UDP 8472) or Geneve (UDP 6081) between nodes. No underlay routing needed. IPv6 underlay supported since 1.18. | Cloud environments, any network fabric |
| Native Routing (direct) | Pod CIDRs are routed by the underlay, by autoDirectNodeRoutes, BGP, or the cloud router. |
Bare-metal, on-prem, cloud VPCs with custom routing |
| Hybrid | Native routing within the same L2 segment, tunneling across subnets. | Mixed environments |
kube-proxy Replacement Coverage¶
| Service Type | kube-proxy (iptables) | Cilium (eBPF) |
|---|---|---|
| ClusterIP | iptables DNAT rules | TC eBPF + socket-level connect-time LB |
| NodePort | iptables DNAT + kube-proxy port binding | TC eBPF on host interfaces (SNAT, DSR or hybrid) |
| LoadBalancer | iptables DNAT via kube-proxy | TC eBPF, optional XDP acceleration |
| ExternalIPs | iptables DNAT | TC eBPF |
| HostPort | portmap CNI plugin | TC eBPF (portmap not needed) |
Current kubeProxyReplacement values are true and false. The old strict/partial/probe modes no longer exist. Maglev table sizes (maglev.tableSize) are primes such as 16381 (~160 backends) and 65521 (~650 backends). All agents must share maglev.hashSeed.
Security Policy Layers¶
| Layer | Enforcement Point | Capabilities |
|---|---|---|
| L3/L4 | TC eBPF (ingress/egress) | Identity-based allow/deny by label, CIDR, FQDN, entity, port, protocol |
| L4+ NAT | Socket BPF / TC eBPF | Service load balancing, kube-proxy replacement |
| L7 HTTP | Envoy (cilium-envoy DaemonSet by default) |
HTTP method/path/header filtering, URL regex |
| L7 gRPC | Envoy | gRPC matched as HTTP/2 paths (/package.Service/Method) |
| L7 Kafka | Removed in 1.20 | Use CiliumEnvoyConfig-based alternatives |
| L7 DNS | DNS proxy in the agent | DNS query pattern filtering, toFQDNs IP learning (**. multi-level wildcard since 1.19) |
| TLS | Envoy with stored certs | TLS interception for L7 inspection |
| Runtime | Tetragon (kprobes/tracepoints/LSM) | Process, file, and socket event monitoring and enforcement |
| Encryption | WireGuard / IPsec / ztunnel (beta) | Transparent pod-to-pod and node-to-node encryption |
Cluster Mesh Limits¶
maxConnectedClusters |
Max cluster-local identities | Cluster ID range |
|---|---|---|
| 255 (default) | 65535 | 1-255 |
| 511 | 32767 | 1-511 |
All clusters in a mesh must use the same maxConnectedClusters. It can only be set at install time. Every cluster needs a unique cluster.name and cluster.id. The mesh is one trust domain.
Benchmarks¶
Old test setups
The Cilium project publishes two measured studies. Both are old, so treat them as the shape of the curve, not as numbers for Cilium 1.20. Official hard limits are in eBPF Map Limits and Cluster Mesh Limits.
eBPF Performance¶
The official CNI benchmark (checked 2026-09-27) used Cilium 1.9.6 on two AMD Ryzen 9 3950X nodes linked back to back by 100 Gbit/s Intel E810 NICs. It ran netperf TCP_STREAM, TCP_RR and TCP_CRR tests and WireGuard and IPsec tests. The results are published as charts, not tables. Its conclusions:
| Test | Finding (Cilium 1.9.6) |
|---|---|
| TCP throughput (1 and 32 streams) | eBPF host-routing gets close to the no-CNI baseline on modern kernels and needs less CPU per Gbit than legacy host-routing |
| TCP_RR (request/response rate) | eBPF comes close to the baseline rate with only slightly more CPU |
| TCP_CRR (new connection per request) | Pays extra kernel cost at the sender once network namespaces are involved |
| WireGuard vs IPsec | WireGuard reaches higher maximum throughput; IPsec uses less CPU to reach 10 Gbit/s |
Not published: current per-release throughput or latency figures (checked 2026-09-27). The older rows on this page (40+ Gbps same-node, 9.5+ Gbps cross-node, +5-15% for kube-proxy replacement) had no recorded test conditions and were removed on 2026-09-27.
Scaling Limits¶
| Dimension | Limit | Notes |
|---|---|---|
| Nodes per cluster | No Cilium-published maximum | Kubernetes documents 5,000 nodes. The official scalability report tested 1,000 worker nodes |
| Endpoints per node | 64k map capacity | Official endpoint map default. Practical density is far lower (kubelet max-pods) |
| Network policies | No published count limit | The per-endpoint policy map (bpf.policyMapMax, default 16,384 entries) is the real constraint |
| Identities (security) | 65,535 | Cluster-local identities with the default maxConnectedClusters=255 |
Resource Consumption¶
From the official scalability report: Kubernetes 1.18.3 on Google Cloud, 1,000 workers (2 vCPU, 4 GB), CRD mode without kube-proxy.
| Scenario | Measured result |
|---|---|
| Growing from 2 to 1,000 nodes | No significant growth in agent or operator memory |
| 50,000 pods across 1,000 nodes | Agent memory at most 573 MiB, average 438 MiB. eBPF map memory at most 462.7 MiB. About 10.5 KiB more agent memory per pod in the cluster |
| 250 L4/L7 policies selecting 10,000 pods | No significant memory change. p99 endpoint regeneration under 5 s; policy enforced on an endpoint in under 600 ms |
| Node scale-up | Agents peaked at 6.8% CPU on a 2 vCPU node |
The earlier CPU and memory sizing table by cluster size had no source and was removed on 2026-09-27.