Skip to content
Blog

eBPF for Networking, Security, and Observability in 2026

Cilium in production: eBPF ClusterIP replacement without kube-proxy, identity-aware NetworkPolicy, Hubble flow observability, Tetragon runtime security, and sidecar-free service mesh.

Published on • November 15, 2026

AI Assistant

In 2026, the interesting question about eBPF in Kubernetes is no longer “does it work?” — it is “which of the three jobs are you using it for?” Because Cilium, the flagship eBPF project (CNCF graduated in 2023, default dataplane in GKE Dataplane V2, available as Azure CNI Powered by Cilium on AKS and on EKS), quietly does all three at once: it routes and load-balances packets, it enforces security policy, and it emits the flow telemetry you troubleshoot with — all from programs attached to the same kernel hooks. This post walks the three pillars with the current production feature set.

Networking: The kube-proxy Replacement

The classic Kubernetes service implementation — iptables or IPVS rules generated per Service — degrades as rules scale into the tens of thousands and offers no visibility into why a connection was dropped. Cilium replaces it with eBPF programs on tc hooks and XDP:

  • Service load balancing in-kernel: a BPF_MAP_TYPE_HASH/LRU service map translates ClusterIP to backend endpoints before the packet ever reaches iptables. No per-Service rule chains, O(1) lookup regardless of Service count.
  • DSR and hybrid return paths: Direct Server Return (and DSR + SNAT hybrid) lets responses bypass the load-balancing node, cutting latency for high-throughput services.
  • Maglev consistent hashing: backend selection that stays stable when endpoints churn, avoiding the connection-rehash storms of iptables-based --mode=masquerade.
  • XDP early drop: DDoS and malformed-traffic filtering before sk_buff allocation, where packet rates are highest.
  • Full kube-proxy modes: ClusterIP, NodePort, LoadBalancer, and externalTrafficPolicy semantics are implemented in the datapath, so kubeproxy-free clusters are a supported production configuration, not an experiment.

The mechanism behind all of this is Cilium’s “life of a packet”: a socket-level connect() hook short-circuits the service translation inside the sending process’s context, ingress/egress tc programs enforce policy and NAT per endpoint, and XDP handles the earliest drops — each stage reading the same identity and service maps, so policy, load balancing, and telemetry never disagree about which endpoint a packet belongs to. IPAM is handled per platform (Kubernetes, cluster-pool, ENI, Azure), and transparent encryption via WireGuard or IPsec wraps east-west traffic without application changes.

Security: Identity-Aware NetworkPolicy

NetworkPolicy in iptables form matches on pod labels resolved at rule-write time; Cilium resolves security identities in the datapath — a numeric ID derived from labels, stored in a map, so policy follows pods across restarts and IP churn. The policy language goes further than the Kubernetes spec:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-only-from-frontend
spec:
  endpointSelector:
    matchLabels:
      app: payment-api
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "8080"
              protocol: TCP
          rules:
            http:
              - method: GET
                path: "/v1/invoices"
              - method: POST
                path: "/v1/invoices"

That example shows the L7 capability: HTTP method and path enforcement happens in a per-node Envoy proxy that Cilium programs transparently — no sidecar, no pod annotation. The same mechanism covers gRPC, Kafka, and DNS. DNS-based policies (toFQDNs) let you allow egress to api.stripe.com without enumerating IPs, enforced by Cilium’s DNS proxy. Add deny policies for explicit rejection (with configurable drop vs. reject responses), host firewall policies for nodes themselves, and egress gateway for controlled north-south traffic, and most clusters can drop their separate network-policy layer entirely.

Observability: Hubble’s Flow Plane

Policy without observability is a support ticket generator. Hubble rides the same eBPF hooks to capture L3/L4 flow events — source/destination identity, verdict, TCP flags, drop reason — plus L7 protocol visibility where enabled:

hubble observe --namespace payments --protocol http --method POST \
  --to-label app=payment-api --last 10m

The output carries Cilium security identities, not just IPs, so “who talked to whom” is answerable in label space. Hubble exposes this three ways: the CLI for ad-hoc queries, Hubble Relay aggregating flows cluster-wide into Hubble UI’s service map (edges annotated with DNS names and policy verdicts), and Prometheus metrics — hubble_flows_total, hubble_drop_total, hubble_http_requests_total by method/path/status — feeding the Grafana dashboards Cilium ships. The Hubble exporter can continuously stream selected flows to external sinks (Kafka, Elasticsearch, Splunk) for compliance retention.

This is the answer to the classic debugging loop: a pod cannot reach a database, and with Hubble the first question — was a packet sent, and what was its verdict? — takes one query instead of a tcpdump session.

Runtime Security: Tetragon

Flow data tells you what crossed the network; Tetragon tells you what ran. Open-sourced by Isovalent in 2022, it attaches kprobes and (since Linux 5.7) LSM hooks to observe:

  • process execution and exit (execve lineage, parent/child relationships, hashed binaries),
  • file opens and writes, including paths sensitive like /etc/shadow,
  • TCP connects and accepts, with socket-level metadata,
  • capability use and privileged-process creation,
  • kernel module loads.

Events are filtered by Kubernetes identity via the TracingPolicy CRD, and — crucially — the LSM hooks allow enforcement, not just logging: a policy can deny a container opening a host path even though the process has the syscall rights. The typical deployment ships a default TracingPolicy for exec/file/connect auditing, exports events to a SIEM via the JSON exporter or OTLP, and alerts on rules like “shell spawned in a payment container” or “process outside its image wrote to /usr/bin.”

Service Mesh Without Sidecars

Cilium’s mesh story is the cleanest demonstration of the “one datapath” thesis: L7 routing, retries, and mTLS run in per-node eBPF and Envoy instances managed by Cilium itself, so pods carry zero sidecar containers. There is no Envoy-per-pod memory tax, no proxy-injection ordering problem, and no second agent to operate. Gateway API and Ingress resources are served by the same stack, and mutual authentication rides the existing encryption layer with identities tied to Kubernetes service accounts.

The trade-off is honest: you are choosing Cilium’s implementation of mesh semantics rather than a Istio/Consul-compatible control plane, and the feature set (traffic splitting, circuit breaking, fault injection) is narrower than a mature sidecar mesh — though it has been converging steadily across the 1.17 and 1.18 lines.

Production Status in 2026

The deployment evidence is now overwhelming rather than anecdotal: Cilium is the default CNI in GKE Dataplane V2, offered natively in AKS and EKS Anywhere, and embedded in Rancher and OpenShift distributions; its BPF/XDP reference guide and threat model are maintained documentation, not blog posts; and the operational surface (Hubble metrics, cilium-bugtool, pre-flight upgrade checks, Prometheus/Grafana dashboards) is what you would expect from software running at large scale for years. The kernel floor is Linux 4.9 for the base datapath, with 5.10+ unlocking the modern feature set — a range that every current LTS distribution satisfies.

The pattern behind all four capabilities is the same: make the kernel the single enforcement and observation point. Networking, policy, telemetry, and security share one identity model and one set of hooks — and that is what eBPF rewired.

References