This episode covers Cilium's traffic gateways: CiliumEgressGatewayPolicy to centralize outgoing traffic through a specific IP using NAT, as well as CiliumIngressGateway and Gateway API integration for incoming traffic. You will create real policies and routes that connect your cluster to the outside world.

So far we have focused on traffic inside the cluster. Episode 12 flips the direction: how traffic in and out crosses the cluster boundary. For outgoing traffic, many organizations want all outbound requests to appear from a single set of fixed IPs so external parties can allowlist them. For incoming traffic, we need a solid gateway in front of the Service.
We will cover two Cilium mechanisms: CiliumEgressGatewayPolicy for centralized egress, and CiliumIngressGateway with the Gateway API for ingress. Both show how Cilium goes beyond the typical CNI role toward a complete networking platform.
In a normal setup, pod traffic leaving the cluster is NATed with the originating node's IP. The problem: if pods are spread across many nodes, outgoing traffic appears from many different IPs. External sites that allowlist IPs will struggle, as will audit logging that relies on a single source IP.
An egress gateway centralizes this: all traffic leaving a group of pods is routed through one specific node (or a group of nodes), NATed into one consistent egress IP. From the outside, it looks as if all requests come from a single gateway. Enable this feature at install time:
cilium install --set egressGateway.enabled=truecilium install --set egressGateway.enabled=true enables the egress gateway component in Cilium. Without this, the CiliumEgressGatewayPolicy resource will not work.
This resource defines three things: which pods have their outgoing traffic routed to the gateway, where that egress traffic applies, and which gateway IP is used as the source. Here is an example policy for an accounting workload:
apiVersion: cilium.io/v2
kind: CiliumEgressGatewayPolicy
metadata:
name: egress-akunting
spec:
selectors:
- podSelector:
matchLabels:
app: akunting
destinationCIDRs:
- "0.0.0.0/0"
egressGateway:
nodeSelector:
matchLabels:
node-role.kubernetes.io/gateway: "true"
egressIP: 10.0.100.10podSelector selects the accounting pods, destinationCIDRs defines the destination (here all IPs), and egressGateway points to the node labeled as a gateway with the egress IP 10.0.100.10. Traffic leaving the accounting pods now appears to come from 10.0.100.10, regardless of which node the pod is running on.
Verify the egress address with Hubble by filtering egress flows:
hubble observe --namespace akunting --verdict FORWARDEDhubble observe --namespace akunting --verdict FORWARDED displays outgoing flows; on the egress lines, the source address will show the gateway IP 10.0.100.10 instead of the pod's originating node IP.
For incoming traffic, Cilium offers two paths: the classic ingress controller and the Gateway API implementation. The Gateway API is the next-generation Kubernetes standard that replaces Ingress v1 with the more expressive Gateway, GatewayClass, and route concepts. Enable its support:
cilium install --set gatewayAPI.enabled=truecilium install --set gatewayAPI.enabled=true enables Cilium's Gateway API implementation. After that, define the gateway and the route:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gw-utama
spec:
gatewayClassName: cilium
listeners:
- name: http
port: 80
protocol: HTTP
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: route-frontend
spec:
parentRefs:
- name: gw-utama
rules:
- backendRefs:
- name: frontend
port: 8080gatewayClassName: cilium selects Cilium's implementation, and the HTTPRoute maps incoming requests to the frontend backend on port 8080. Compared to classic Ingress, this structure is modular: the Gateway belongs to the platform operator, while the HTTPRoute can be owned by application teams.
To verify that the route works, send a request through the gateway address:
curl -s http://$(kubectl get gateway gw-utama -o jsonpath='{.status.addresses[0].value}')kubectl get gateway gw-utama -o jsonpath='{.status.addresses[0].value}' retrieves the address allocated to the gateway, and a curl to it will be routed to the frontend service by Cilium.
Warning
The egress gateway adds one hop to outgoing traffic. For workloads that are highly latency-sensitive, limit egress gateway usage to workloads that genuinely must exit from a fixed IP, not all pods.
Key takeaways:
CiliumEgressGatewayPolicy selects the pods, the destination, and the egress IP.egressGateway.enabled=true must be active before the policy can be used.gatewayClassName: cilium selects Cilium's implementation for the Gateway API.In the next episode 13, we will cover L7 policies and API-aware security — HTTP-, gRPC-, and Kafka-based rules inside CNPs and CCNPs, per-endpoint L7 visibility, and CiliumClusterwideNetworkPolicy for cross-namespace policies. This takes our policies from the port level to the application content level.