Istio’s egress gateway isn’t just another way to send traffic out; it’s a fundamental shift in how you reason about outbound connections, turning them from a free-for-all into a tightly controlled, observable system.
Let’s see it in action. Imagine a details service that needs to call an external API, say httpbin.org. Without an egress gateway, details would connect directly. With one, details sends its request to the Istio sidecar, which then routes it to the egress gateway pod, and that pod makes the actual outbound connection.
Here’s a simplified ServiceEntry to allow traffic to httpbin.org:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: httpbin-external
spec:
hosts:
- httpbin.org
ports:
- number: 443
name: https
protocol: HTTPS
resolution: DNS
location: MESH_EXTERNAL
Now, a VirtualService to direct traffic from our details service to this ServiceEntry via the egress gateway:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: details-egress-httpbin
spec:
hosts:
- httpbin.org
gateways:
- egressgateway # This refers to the gateway resource defined below
http:
- route:
- destination:
host: httpbin.org
port:
number: 443
And finally, the Gateway resource that defines the egress gateway itself:
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: egressgateway
spec:
selector:
istio: egressgateway # This selector points to the actual egress gateway pods
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "httpbin.org"
The problem this solves is the inherent insecurity and lack of visibility in traditional microservice architectures where services can reach any external endpoint. This creates a large attack surface and makes it difficult to enforce policies or audit outbound communication. The egress gateway acts as a single, controlled exit point. All outbound traffic from your mesh is funneled through it, allowing you to apply Istio’s powerful routing, security, and telemetry features to these external connections.
Internally, the egress gateway works by having its own Istio sidecar. When a service in the mesh wants to reach an external host defined in a ServiceEntry, its sidecar intercepts the traffic. Based on the VirtualService and Gateway configurations, it rewrites the destination to point to the egress gateway’s IP address and port. The egress gateway’s sidecar then receives this traffic, looks up the actual external destination based on the original request, and initiates the connection to the external service. This effectively makes the egress gateway the source IP for all outbound traffic originating from the mesh.
The location: MESH_EXTERNAL field in the ServiceEntry is crucial. It tells Istio that this host is outside the mesh, and therefore traffic destined for it should be routed through an egress gateway if one is configured to handle it. If you omit this, Istio might try to resolve it internally or route it as if it were another service within the mesh, leading to unexpected behavior or connection failures.
Many users struggle with getting TLS termination right at the egress gateway for external services. While the Gateway resource can specify HTTPS for its port, the actual TLS handshake with the external service is performed by the egress gateway pod itself. This means you don’t need to import certificates for external services into Istio; Istio’s sidecar handles the outbound TLS connection using its own trust store. The VirtualService simply needs to specify the correct port and protocol for the external host.
The next step in controlling outbound traffic is understanding how to apply authorization policies to these egress connections, limiting which internal services can reach which external destinations.