Control external egress in Istio using ServiceEntry and optional egress gateway, including REGISTRY_ONLY setup, VirtualService, Gateway, and DestinationRule examples
This lesson demonstrates how to control external egress traffic in Istio using ServiceEntry resources and (optionally) an Istio egress Gateway. You’ll learn how to:
Install Istio with a demo profile configured to REGISTRY_ONLY outbound policy so only hosts registered in Istio are reachable.
Run a test pod and observe how an Envoy sidecar enforces egress restrictions.
Create a ServiceEntry to allow www.wikipedia.org.
Configure an egress Gateway, DestinationRule, and VirtualService to force traffic through the egress gateway and understand why the mesh gateway entry is required.
Note: Istio routing and egress control apply only to namespaces with sidecar injection enabled.
Label any namespaces that should be managed by Istio (for example: kubectl label namespace default istio-injection=enabled) and recreate pods so the Envoy sidecar can be injected.
Find the meshConfig section and set the outbound traffic policy to REGISTRY_ONLY so the mesh only allows egress to hosts known to Istio (via ServiceEntry):
3. Enable sidecar injection and observe REGISTRY_ONLY effect
Label the namespace for automatic sidecar injection (using the default namespace in this guide), restart the pod, and confirm the sidecar is injected:
kubectl label namespace default istio-injection=enabledkubectl delete pod testkubectl run test --image=curlimages/curl:8.1.2 --restart=Never --command -- sleep 3600kubectl get pods# test 0/2 PodInitializing# test 2/2 Running
Enter the pod and attempt to curl Wikipedia again:
kubectl exec -ti test -- /bin/shcurl --head -L http://www.wikipedia.org
Because meshConfig.outboundTrafficPolicy.mode is REGISTRY_ONLY and www.wikipedia.org is not yet registered in Istio, Envoy will block the request and return:
HTTP/1.1 502 Bad Gatewaydate: ...server: envoy
This demonstrates that REGISTRY_ONLY prevents egress unless a ServiceEntry (or other Istio configuration) explicitly allows the external host.
To permit pods in an Istio-enabled namespace to reach external services, add ServiceEntry resources (or configure egress gateways) for those hosts.
kubectl apply -f serviceentry-wikipedia.yamlkubectl get serviceentries.networking.istio.io# NAME HOSTS LOCATION RESOLUTION AGE# wikipedia-egress ["www.wikipedia.org"] DNS 14s
Retry from the test pod:
kubectl exec -ti test -- /bin/shcurl --head -L http://www.wikipedia.org
Now the request should succeed (HTTP 200 after the redirect). The ServiceEntry allowed egress to that external host.
5. Route external traffic through an Istio egress gateway
Routing external traffic through an egress gateway centralizes outbound traffic, enabling monitoring, logging, and centralized policy enforcement.To route traffic through the egress gateway we need:
A Gateway resource that selects the egress gateway pods.
A DestinationRule pointing to the egress gateway service (and a subset).
A VirtualService that (a) routes mesh-originating traffic to the egress gateway and (b) routes traffic from the egress gateway to the external host.
Important: Gateway resources select pods in the same namespace as the Gateway. The built-in egress gateway pods live in istio-system, so create the Gateway in istio-system to match pods by label.First confirm the egress gateway pod and labels:
kubectl apply -f vs.yamlkubectl get virtualservices.networking.istio.io# NAME GATEWAYS HOSTS# wikipedia-egress-gateway ["istio-system/istio-egressgateway","mesh"] ["www.wikipedia.org"]
Important explanation: The mesh gateway entry is required so that traffic originating from inside the mesh (pod → external host) matches the first HTTP rule and is routed to the egress gateway subset wikipedia. When the egress gateway receives the request, the VirtualService matches the istio-system/istio-egressgateway gateway rule and forwards the request to www.wikipedia.org. If you omit the mesh match, internal traffic will bypass the egress gateway and will not be centrally controlled.
If you omit the mesh gateway entry in the VirtualService, traffic from inside the mesh will bypass the egress gateway, removing centralized control and visibility.
kubectl exec -ti test -- /bin/shcurl --head -L http://www.wikipedia.org
You should see normal responses, and the egress gateway logs will show the outbound request. This confirms that mesh traffic was routed to the egress gateway which then forwarded it to the external host.
If your VirtualService isn’t taking effect, confirm the Gateway exists in the correct namespace and the gateways entry in the VirtualService is properly namespace-qualified (istio-system/istio-egressgateway).
If traffic is still blocked after creating a ServiceEntry, ensure the ServiceEntry is in the same namespace as the client pod (or exported appropriately) and that DNS resolution is working as expected.
Use kubectl get virtualservices,destinationrules,gateways,serviceentries -A to verify configuration across namespaces.
Setting meshConfig.outboundTrafficPolicy.mode to REGISTRY_ONLY blocks egress to hosts not registered in Istio.
Use ServiceEntry to register external hosts so Istio allows egress.
To centralize and control external traffic, create an egress Gateway, a DestinationRule pointing to the egress gateway service, and a VirtualService that routes mesh-originating traffic to the egress gateway and the gateway to the external host.
The mesh gateway entry in the VirtualService is essential to route traffic originating from inside the mesh through the egress gateway.
Practice creating these resources (ServiceEntry, Gateway, DestinationRule, VirtualService) so you can apply them swiftly in real-world scenarios and assessments.