Skip to main content
This guide demonstrates how to configure an egress gateway in a Cilium-enabled Kubernetes cluster and how to inspect traffic flows before and after enabling it. You’ll see how pods are SNAT’d by default, how to enforce egress via a chosen node, and how Cilium forwards traffic (often using VXLAN encapsulation) to the egress node. What we’ll demonstrate
  • Default behavior: pod egress is SNAT’d to the node IP.
  • Enabling Cilium egress gateway and applying a CiliumEgressGatewayPolicy.
  • Capturing traffic to confirm egress from a single gateway node and inspecting VXLAN encapsulation.
Environment overview
Prerequisites: Cilium must be installed with kube-proxy replacement enabled (kubeProxyReplacement), eBPF masquerade (bpf.masquerade) turned on, and a Cilium release that supports the egress gateway feature. Confirm your cluster networking and node labeling permissions before proceeding.
Cluster pod listing (example)
Verify outbound connectivity from a pod (example)
Default behavior (no egress gateway)
  • Flow: pod IP → node → router → internet. The node performs SNAT, so the router and external services see the node IP as the source address, not the pod IP.
  • If pods run on multiple worker nodes, external services observe different source IPs depending on the node used.
Example router tcpdump showing node IP as source
Node interface example (worker1)
Explanation diagram:
A simple Kubernetes network diagram showing a control-plane and two worker nodes, each with an ens33 interface IP and a pod CIDR (worker1: 10.0.1.0/24, worker2: 10.0.2.0/24), all connected via a central router with additional interface IPs and external DNS 8.8.8.8.
How the egress gateway changes traffic flow
  • Cilium egress gateway centralizes outbound traffic from selected pods through one or more chosen node(s). Those egress node(s) perform SNAT so the external source IP is the chosen egress IP.
  • Internally, Cilium forwards traffic from source nodes to the egress gateway node. In overlay networks (common with Cilium), this forwarding is encapsulated (VXLAN or similar). The egress node decapsulates, performs SNAT, and sends traffic to the internet.
Enable required Cilium options
  1. kube-proxy replacement (ensure kubeProxyReplacement is enabled in values):
  1. eBPF masquerade (native BPF SNAT):
  1. Enable egress gateway support (depends on Cilium version and values layout). After editing Helm values, upgrade and restart Cilium:
Create and apply a CiliumEgressGatewayPolicy
  • Label the node(s) you want to act as egress gateway(s) and reference that label in the policy nodeSelector.
  • Note: label values in YAML matchLabels must be strings. Quote boolean-like values (e.g., “true”).
Label the chosen node (example)
Confirm the label
Example CiliumEgressGatewayPolicy (egress-gateway.yaml)
  • This example selects pods with label app=app1, matches all destinations (0.0.0.0/0), and configures the node labeled egress: “true” to use egress IP 192.168.44.128.
Apply the policy
When authoring CiliumEgressGatewayPolicy YAML, always quote label values (for example: egress: “true”) so they are treated as strings. Also ensure your Cilium version supports the egress gateway feature and that kubeProxyReplacement and bpf.masquerade are enabled.
Verify Cilium BPF egress entries
  • Check the BPF egress table from a Cilium agent pod to confirm source pods are mapped to the configured egress IP:
Confirm behavior with packet capture
  • Start a capture on your router. To write a pcap file and capture ICMP on all interfaces:
  • From a pod on worker1 (not the egress gateway), ping 8.8.8.8 and stop the capture after a few packets:
Expected router capture after enabling egress gateway
  • Router should now see the configured egress IP (192.168.44.128) as the source for traffic from pods matched by the policy instead of the pod’s local node IP.
Example tcpdump showing traffic egressing from the egress node (worker2/egress IP)
Inspecting the packets (VXLAN encapsulation)
  • When the source pod is on a different node than the configured egress node, Cilium forwards the packet across nodes using overlay encapsulation (often VXLAN). The outer header shows node→egress-node (physical IPs) and the inner payload contains the original pod→internet packet. The egress node decapsulates, SNATs to the egress IP, and sends the packet to the internet. Replies are received by the egress node and forwarded/decapsulated back to the source node as needed.
Wireshark view example:
A Wireshark packet-capture window showing a list of network packets (TCP, UDP, ICMP, TLS) with columns for source/destination, ports, and info. The lower panes display the selected packet's protocol details and hex/ASCII dump.
Representative Wireshark decoded summary (illustrative)
Decapsulated packet leaving the egress node:
Reply returned and delivered back to the pod (encapsulated back if required):
Summary and best practices
  • Default: each node SNATs pod outbound traffic to its node IP; external servers will see multiple source IPs if pods are distributed across nodes.
  • With Cilium egress gateway: you can centralize egress IPs by selecting one or more egress nodes. Matched pod traffic is forwarded (often via VXLAN), SNAT’d at the egress node, and sent to the internet — useful for predictable outbound IPs, firewalling, and auditing.
  • Ensure:
    • kubeProxyReplacement is enabled,
    • eBPF masquerade (bpf.masquerade) is enabled,
    • quoting label values (e.g., egress: “true”) in YAML to avoid boolean parsing issues.
  • For production: consider multiple egress nodes and failover strategies to avoid single points of egress.
Links and references If you’d like, I can also provide:
  • A granular policy example selecting a single destination IP (e.g., “8.8.8.8/32”),
  • Steps to configure multiple egress nodes with failover,
  • Commands to inspect Cilium policy state and logs for troubleshooting.

Watch Video

Practice Lab