Cilium Egress Gateway lets you route outbound traffic from your Kubernetes pods through a specific, static IP address, bypassing the ephemeral IPs typically assigned by cloud providers.
Let’s see this in action. Imagine you have a Kubernetes cluster and you want all traffic from a specific application, say my-app, to exit the cluster using a dedicated IP address, 203.0.113.10. This is crucial for whitelisting at external services or for consistent logging.
Here’s a simplified view of how it works. You define a CiliumEgressGatewayPolicy. This policy tells Cilium: "For traffic originating from pods matching this selector, send it through this specific gateway IP."
apiVersion: cilium.io/v1alpha1
kind: CiliumEgressGatewayPolicy
metadata:
name: egress-gateway-policy
spec:
selectors:
- matchLabels:
app: my-app
destinationCIDRs:
- "0.0.0.0/0" # Applies to all outbound traffic
egressGateway:
# This is the IP address that will be used for egress
# It must be an IP address assigned to a node in your cluster,
# or a dedicated IP you've configured for this purpose.
ippools:
- cidr: "203.0.113.10/32"
When a pod with the label app: my-app sends traffic, Cilium intercepts it. If the traffic matches the CiliumEgressGatewayPolicy, Cilium rewrites the source IP address of the outgoing packet to 203.0.113.10 using NAT. The underlying mechanism is often iptables or eBPF, depending on your Cilium configuration.
This solves a common problem: external services that require a fixed IP for access control. Without an Egress Gateway, your application’s egress IP might change if the pod is rescheduled or if the underlying node’s IP changes, breaking whitelisting rules.
The key components you control are:
spec.selectors: This is how you target which pods should use the egress gateway. You can usematchLabels,matchExpressions, or a combination. This allows for granular control – maybe only your database access pods need a static IP, not your frontend.spec.destinationCIDRs: This defines the destination ranges for which the egress policy applies.0.0.0.0/0means all outbound traffic. You could restrict this to specific external API endpoints if needed.spec.egressGateway.ippools.cidr: This is the heart of it – the static IP address (or a range of IPs) that will be used as the source for the egress traffic. This IP must be routable from your cluster’s network and accessible by the egress gateway node(s).
The magic is that Cilium doesn’t require a separate proxy or load balancer for this simple NAT. It integrates directly into the network dataplane. The ippools field is particularly interesting because it allows for high availability; if you list multiple IPs here and configure Cilium correctly, it can distribute egress traffic across them or use them for failover.
A common pitfall is forgetting that the IP specified in egressGateway.ippools.cidr must be routable and present on the node that will perform the NAT. If it’s not, traffic will simply fail to egress, or the NAT won’t happen as expected. You might need to assign secondary IP addresses to your Kubernetes nodes or use a dedicated IP managed by your cloud provider.
Once you have your egress gateway policy in place, the next logical step is to explore how to make this egress gateway highly available.