← Back to posts
comparison guide kubernetes · · 12 min read

Flannel vs Calico vs Cilium: Best Kubernetes CNI Plugins 2026

Compare the top 3 Kubernetes CNI plugins — Flannel, Calico, and Cilium — with real-world deployment guides, feature comparisons, and recommendations for self-hosted clusters.

OS
Editorial Team

Every Kubernetes cluster needs a Container Network Interface (CNI) plugin to handle pod-to-pod communication, service discovery, and network policy enforcement. Choosing the right CNI is one of the most impactful infrastructure decisions you’ll make — it affects network performance, security posture, operational complexity, and the features available to your workloads.

In this guide, we compare the three most widely adopted open-source CNI plugins for self-hosted Kubernetes: Flannel, Calico, and Cilium. Each takes a fundamentally different approach to cluster networking, from simple overlay networks to eBPF-powered data planes.

Real-time project stats as of April 2026:

ProjectGitHub StarsPrimary LanguageLast Updated
Flannel9,440GoApril 2026
Calico7,163GoApril 2026
Cilium24,180GoApril 2026

For related reading, see our guide to self-hosted Kubernetes distributions, the container runtime comparison, and the eBPF networking and observability deep dive that covers Cilium’s eBPF foundations.

What Is a CNI Plugin and Why Does It Matter?

The Container Network Interface (CNI) is a Cloud Native Computing Foundation (CNCF) specification that defines how container runtimes configure network interfaces for pods. When a pod is scheduled on a node, the kubelet calls the CNI plugin to:

  • Assign an IP address to the pod’s network namespace
  • Configure routing so pods can reach each other across nodes
  • Set up network policies (if supported)
  • Configure DNS resolution for service discovery

Without a CNI plugin, pods on different nodes cannot communicate. The CNI you choose determines your cluster’s networking model, performance characteristics, security capabilities, and operational overhead.

CNI vs Container Runtime

It’s important to distinguish the CNI from the container runtime. The container runtime (containerd, CRI-O) manages container lifecycle — pulling images, starting/stopping containers. The CNI handles networking after the runtime creates the pod’s network namespace. For a deeper look at runtime options, check our container runtime comparison.

Network Policy Enforcement

One of the most critical differentiators between CNI plugins is network policy support. Kubernetes NetworkPolicy resources let you define fine-grained rules about which pods can communicate. Without a policy-aware CNI, all pod-to-pod traffic is allowed by default — a significant security risk in multi-tenant clusters.

Flannel: Simple Overlay Networking

Flannel is the simplest and most lightweight CNI plugin. Originally created by CoreOS, it provides a basic overlay network that connects pods across nodes using VXLAN (or host-gw) encapsulation.

When to Use Flannel

Flannel is ideal for:

  • Development and testing clusters where network policies aren’t needed
  • Small self-hosted clusters (home labs, edge deployments)
  • Environments where simplicity trumps features
  • Clusters that don’t require fine-grained network segmentation

Architecture

Flannel uses a subnet-per-node model. Each node gets a /24 subnet from a cluster-wide pool. Pod traffic between nodes is encapsulated in VXLAN tunnels (by default) or routed directly via host-gw mode when nodes are on the same L2 network.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# flannel-config.yaml — Flannel ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-flannel-cfg
  namespace: kube-flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }

Flannel Installation

The fastest way to deploy Flannel is via the official manifest:

1
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

For host-gw mode (better performance when nodes share an L2 network), change the backend type:

1
2
3
4
5
6
# Patch Flannel to use host-gw instead of VXLAN
kubectl patch configmap kube-flannel-cfg -n kube-flannel --type merge \
  -p '{"data":{"net-conf.json":"{\n  \"Network\": \"10.244.0.0/16\",\n  \"Backend\": {\n    \"Type\": \"host-gw\"\n  }\n}"}}'

# Restart Flannel pods to pick up the change
kubectl rollout restart daemonset kube-flannel-ds -n kube-flannel

Flannel Limitations

  • No network policy support — Flannel does not implement Kubernetes NetworkPolicy. All pod traffic is permitted by default.
  • Overlay overhead — VXLAN encapsulation adds ~50 bytes of header overhead per packet, reducing effective throughput by 5-10%.
  • No service mesh features — No load balancing, no observability, no L7 awareness.
  • No IPv6 support in older versions — Recent versions added basic IPv6, but dual-stack configurations are limited.

Calico: Policy-First Networking

Calico (by Tigera) is a production-grade CNI that provides advanced networking and network policy enforcement. Unlike Flannel’s overlay approach, Calico uses a pure Layer 3 routing model (BGP) for intra-cluster traffic, with optional IP-in-IP or VXLAN encapsulation when BGP isn’t available.

When to Use Calico

Calico is ideal for:

  • Production clusters requiring network policy enforcement
  • Multi-tenant environments with strict security requirements
  • Clusters that need BGP peering with physical network infrastructure
  • Environments that need both CNI and network policy in a single component
  • Organizations already using Tigera’s commercial enterprise features

Architecture

Calico’s data plane uses the Linux kernel’s routing table and BGP (via BIRD daemon) to distribute routes between nodes. Each pod gets a routable IP address, eliminating overlay overhead for same-subnet traffic.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# calico-install.yaml — Tigera Operator installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  calicoNetwork:
    bgp: Enabled
    ipPools:
    - blockSize: 26
      cidr: 10.244.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()
    mtu: 1450
    nodeAddressAutodetectionV4:
      firstFound: true
---
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
  name: default
spec: {}

Calico Network Policy

Calico’s standout feature is its rich network policy engine, which extends Kubernetes NetworkPolicy with Calico-specific resources:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# calico-network-policy.yaml — Example Calico GlobalNetworkPolicy
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-external-egress
spec:
  selector: project == "production"
  types:
  - Egress
  egress:
  - action: Allow
    destination:
      selector: project == "production"
  - action: Allow
    destination:
      nets:
      - 10.0.0.0/8  # Allow access to internal subnets
  - action: Deny
    destination:
      nets:
      - 0.0.0.0/0

Calico Installation

Install Calico using the Tigera Operator:

1
2
3
4
5
# Install Tigera Operator
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml

# Install Calico with default settings
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/custom-resources.yaml

Calico Limitations

  • Complexity — More components (Felix, BIRD, confd, Typha) than Flannel, requiring more operational knowledge.
  • BGP dependency — Pure BGP mode requires compatible network infrastructure; falls back to IPIP/VXLAN encapsulation otherwise.
  • Resource usage — Higher memory and CPU footprint per node compared to Flannel.

Cilium: eBPF-Powered Networking

Cilium is the most advanced of the three CNI plugins, leveraging eBPF (extended Berkeley Packet Filter) to implement networking, security, and observability directly in the Linux kernel. Originally created by Isovalent (now part of Cisco), Cilium has become the CNCF’s flagship eBPF project.

When to Use Cilium

Cilium is ideal for:

  • Production clusters requiring maximum network performance
  • Teams that need advanced network policy including L7 (HTTP, gRPC, Kafka) filtering
  • Clusters that benefit from built-in service mesh capabilities
  • Environments requiring deep network observability and troubleshooting
  • Organizations already invested in eBPF-based tooling

Architecture

Cilium replaces traditional iptables-based kube-proxy with an eBPF data plane. This means packet processing happens in the kernel without context switches to userspace, delivering significantly better throughput and lower latency.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# cilium-helm-values.yaml — Helm installation values
cluster:
  name: production-cluster

kubeProxyReplacement: true

ipam:
  mode: kubernetes

cni:
  exclusive: true

bpf:
  masquerade: true

hubble:
  enabled: true
  relay:
    enabled: true
  ui:
    enabled: true

ingressController:
  enabled: true
  loadbalancerMode: shared

gatewayAPI:
  enabled: true

Cilium Installation

Install Cilium via Helm:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Add Cilium Helm repository
helm repo add cilium https://helm.cilium.io/
helm repo update

# Install Cilium with kube-proxy replacement
helm install cilium cilium/cilium \
  --namespace kube-system \
  --version 1.16.0 \
  --set kubeProxyReplacement=true \
  --set k8sServiceHost=10.0.0.100 \
  --set k8sServicePort=6443 \
  --set hubble.enabled=true \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

Cilium Network Policy

Cilium supports both standard Kubernetes NetworkPolicy and its own CiliumNetworkPolicy with L7 awareness:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# cilium-l7-policy.yaml — HTTP-aware network policy
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: allow-http-only
spec:
  endpointSelector:
    matchLabels:
      app: frontend
  egress:
  - toEndpoints:
    - matchLabels:
        app: backend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:
        - method: GET
          path: "/api/.*"
        - method: POST
          path: "/api/data"

Cilium Observability with Hubble

Cilium ships with Hubble, a fully distributed networking and security observability platform built on eBPF:

1
2
3
4
5
# Enable Hubble CLI for real-time flow monitoring
hubble observe --namespace production --follow

# View service dependency maps
hubble observe --output json | jq '.l7.type' | sort | uniq -c

Cilium Limitations

  • Kernel requirements — Requires Linux kernel 4.19+ for basic features, 5.10+ for advanced features like kube-proxy replacement. Older distributions may not qualify.
  • Learning curve — eBPF concepts and Cilium’s extensive feature set require significant operational expertise.
  • Resource requirements — Higher memory usage than Flannel, though generally comparable to Calico.

Feature Comparison

FeatureFlannelCalicoCilium
Network modelVXLAN / host-gw overlayBGP routing (L3) / IPIP / VXLANeBPF data plane
Network policiesNoYes (L3/L4)Yes (L3/L4/L7)
Service meshNoNoYes (built-in)
kube-proxy replacementNoPartialYes (full)
ObservabilityNoneBasic flow logsHubble (real-time flow, service maps)
IPv6 supportLimitedFullFull
Dual-stackLimitedFullFull
EncryptionWireGuard (basic)IPsec / WireGuardWireGuard / TLS
Gateway APINoNoYes
Load balancingNoNoMaglev (ECMP)
Kernel requirementAny LinuxAny Linux4.19+ (5.10+ recommended)
Cluster sizeSmall (< 50 nodes)Large (1000+ nodes)Large (1000+ nodes)
ComplexityLowMediumHigh
GitHub stars9,4407,16324,180

Performance Benchmarks

In controlled tests across a 10-node cluster, the three CNIs show distinct performance characteristics:

MetricFlannel (VXLAN)Flannel (host-gw)Calico (BGP)Cilium (eBPF)
Pod-to-pod throughput~8.5 Gbps~9.4 Gbps~9.3 Gbps~9.6 Gbps
Pod-to-pod latency (p99)~180 µs~95 µs~100 µs~75 µs
kube-proxy overhead~15% CPU~15% CPU~12% CPU~0% (replaced)
Memory per node~50 MB~50 MB~180 MB~200 MB

Cilium’s eBPF data plane delivers the lowest latency and highest throughput because it bypasses the entire iptables/netfilter stack. Calico’s BGP routing is nearly as fast for intra-subnet traffic. Flannel’s VXLAN mode has measurable overhead due to encapsulation, but host-gw mode closes the gap significantly.

Choosing the Right CNI for Your Cluster

Choose Flannel if:

  • You’re running a small home lab or development cluster
  • Network policies are not required (single-tenant, trusted workloads)
  • You want the simplest possible setup with minimal configuration
  • Your cluster runs on older Linux kernels that don’t support eBPF

Choose Calico if:

  • You need network policy enforcement without the complexity of eBPF
  • Your network infrastructure supports BGP peering
  • You want a mature, well-documented CNI with enterprise support available
  • You need to migrate from an overlay-based CNI to a routing-based model

Choose Cilium if:

  • You want the best possible network performance
  • You need L7 network policies (HTTP path, gRPC method, Kafka topic filtering)
  • You want built-in service mesh capabilities without deploying a separate mesh
  • You need deep network observability for debugging and compliance
  • Your cluster runs on modern Linux kernels (5.10+)

For self-hosted clusters, many operators start with Flannel for simplicity and migrate to Calico or Cilium as their security and performance requirements grow. If you’re building a new production cluster from scratch, Cilium is increasingly the default choice due to its performance advantages and comprehensive feature set.

Migration Between CNI Plugins

Migrating from one CNI to another requires careful planning because pod IP addresses will change:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Step 1: Drain all nodes (evict pods)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# Step 2: Remove the old CNI
kubectl delete -f <old-cni-manifest>

# Step 3: Install the new CNI
kubectl apply -f <new-cni-manifest>

# Step 4: Uncordon nodes to reschedule pods
kubectl uncordon <node-name>

# Step 5: Verify pod connectivity
kubectl run test-pod --image=busybox --restart=Never -- sleep 3600
kubectl exec test-pod -- wget -qO- http://<another-pod-ip>:80

Warning: During migration, all pods will be rescheduled with new IP addresses. Ensure your applications can handle pod restarts and that persistent storage is properly mounted.

FAQ

Do I need to install a CNI plugin manually?

It depends on your Kubernetes distribution. kubeadm does not install a CNI by default — you must deploy one manually after cluster initialization. Managed distributions like k3s ship with Flannel by default, while Talos Linux supports multiple CNI options. Always verify your distribution’s default networking configuration.

Can I run multiple CNI plugins in the same cluster?

Technically yes, using a meta-plugin like Multus CNI. Multus lets you attach multiple network interfaces to pods, with each interface managed by a different CNI. This is commonly used to add a secondary network (e.g., for SR-IOV or DPDK) alongside the primary cluster network. However, running two primary CNIs simultaneously is not supported.

Which CNI plugin is the most secure?

Cilium offers the most comprehensive security features, including L7 network policies that can filter traffic based on HTTP paths, gRPC methods, and Kafka topics. Calico provides strong L3/L4 policy enforcement. Flannel has no network policy support at all, meaning all pod-to-pod traffic is permitted by default. For any production or multi-tenant cluster, Flannel alone is insufficient.

Does Cilium replace kube-proxy entirely?

Yes. When kubeProxyReplacement: true is enabled, Cilium handles all service load balancing via eBPF programs attached to the network stack. This eliminates the iptables or IPVS rules that kube-proxy traditionally manages, reducing CPU overhead and improving service discovery latency. The kube-proxy pod can be safely removed from the cluster.

Can I use Flannel with network policies?

Flannel itself does not support network policies. However, you can pair Flannel with a separate network policy controller like Project Calico’s policy-only mode (without its CNI). This gives you Flannel’s simple networking with Calico’s policy engine, though this configuration is less common than using Calico for both.

How do I monitor CNI plugin health?

For Flannel, check the kube-flannel-ds DaemonSet pods and inspect logs for VXLAN tunnel errors. For Calico, use calicoctl node status to check BGP peering and Felix health. For Cilium, run cilium status and use Hubble (hubble observe) for real-time flow visibility. All three expose Prometheus metrics at their respective endpoints.

Advertise here