In ASM Ambient mode, you can manage outbound traffic for services within the mesh at two levels: fine-grained, per-service control using ServiceEntry and Waypoint, or global policy enforcement using EgressPolicy.
Choose a method
|
Method |
Use cases |
Control granularity |
Typical uses |
|
ServiceEntry + Waypoint |
Configure routing, observability, or access control for specific external services. |
Single external service |
TLS termination, request authorization, and traffic auditing |
|
EgressPolicy |
Apply allow or deny policies to all outbound traffic from the mesh. |
Global (by namespace or CIDR block) |
Block access to internal CIDR blocks or allow traffic from specific namespaces. |
Note You can use both methods together. The mesh treats external services declared with a ServiceEntry as known destinations, so EgressPolicy does not affect their traffic. EgressPolicy applies only to traffic that does not match a known Service or Workload in the mesh.
Important EgressPolicy requires an ASM instance of version 1.29 or later.
Prerequisites
-
You have created an ASM instance with Ambient mode enabled.
-
You have added a cluster to the ASM instance.
-
You have enabled Ambient mode for the namespaces where you want to manage outbound traffic.
-
You have created an
egress-gatewaynamespace to deploy the egress proxy.
Method 1: ServiceEntry and Waypoint
Use a ServiceEntry to declare an external service as a known destination in the mesh, then use a Waypoint proxy to apply routing, observability, or access control to its traffic.
-
Deploy an egress Waypoint
Create a dedicated Waypoint proxy for egress traffic. This proxy acts as a unified exit point for services in the mesh that access external services:
kubectl apply -n egress-gateway -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: egress-waypoint spec: gatewayClassName: istio-waypoint listeners: - name: mesh port: 15008 protocol: HBONE EOFVerify that the Waypoint is ready:
kubectl get pods -n egress-gateway -l gateway.istio.io/managed=istio.io-mesh-controllerIn the expected output, the pod status is
Running:NAME READY STATUS RESTARTS AGE egress-waypoint-xxxxxxxxx-xxxxx 1/1 Running 0 30s -
Create a ServiceEntry
Take
httpbin.orgas an example. Create a ServiceEntry to declare this external service as a known destination in the mesh and bind it to the Waypoint deployed in the previous step:apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: httpbin namespace: egress-gateway labels: istio.io/use-waypoint: egress-waypoint spec: hosts: - httpbin.org location: MESH_EXTERNAL ports: - number: 80 name: http protocol: HTTP - number: 443 name: https protocol: HTTPS resolution: DNSNote
The
istio.io/use-waypoint: egress-waypointlabel routes traffic for this ServiceEntry to the specified Waypoint proxy.resolution: DNSindicates that the mesh obtains the external service's actual IP address through DNS resolution.kubectl apply -f httpbin-serviceentry.yaml -
(Optional) Configure an access policy
Use an AuthorizationPolicy to restrict which services can access this external service:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: allow-frontend-to-httpbin namespace: egress-gateway spec: targetRefs: - kind: ServiceEntry group: networking.istio.io name: httpbin action: ALLOW rules: - from: - source: namespaces: ["default"] to: - operation: methods: ["GET"] paths: ["/get", "/headers"]kubectl apply -f httpbin-authz.yamlThis policy allows services in the
defaultnamespace to access the/getand/headerspaths ofhttpbin.orgusing the GET method. -
Verify the results
Send a request from a pod in the
defaultnamespace to verify that the traffic passes through the Waypoint proxy:kubectl exec -n default deploy/test-pod -- curl -sI http://httpbin.org/headersAn HTTP 200 response is expected.
Check the Waypoint access logs to confirm that the request was recorded:
kubectl logs -n egress-gateway -l gateway.istio.io/managed=istio.io-mesh-controller --tail=20The logs are expected to contain records of requests to
httpbin.org, including the source namespace, request path, and response status code.Send a request from an unauthorized namespace to verify that access is denied:
kubectl exec -n other-ns deploy/test-pod -- curl -sI http://httpbin.org/headersAn
RBAC: access deniedresponse is expected, indicating the AuthorizationPolicy is enforced.
Method 2: EgressPolicy
Use an EgressPolicy to apply allow or deny rules to all unrecognized outbound traffic from the mesh. This method requires an ASM instance of version 1.29 or later.
For detailed instructions on EgressPolicy, see Ztunnel Configuration Instructions. The following section provides a configuration example.
Configuration example
Configure the EgressPolicy in the ztunnel-config ConfigMap within the istio-system namespace:
kubectl apply -n istio-system -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: ztunnel-config
data:
ztunnel-config.yaml: |
egressPolicies:
# Allows pods in the specified namespaces to directly access external services
- namespaces:
- common-infrastructure
policy: Passthrough
# Prevents all namespaces from accessing internal CIDR blocks
- matchCidrs:
- 172.16.0.0/16
- 2001:0db8::/32
policy: Deny
EOF
Important The EgressPolicy feature requires an ASM instance of version 1.29 or later.
Verification
Send a request from a pod in the default namespace to a destination in the denied CIDR block:
kubectl exec -n default deploy/test-pod -- curl -sI --connect-timeout 5 http://172.16.0.1
The connection should be refused, indicating the Deny policy is enforced.
Combining the methods
In production, we recommend combining the two methods:
-
Use ServiceEntry and Waypoint to configure routing and access control for external services that require fine-grained management, such as an API gateway or third-party payment services. This enables features like observability, authorization, and TLS termination.
-
Use EgressPolicy as a global fallback policy to block services within the mesh from accessing sensitive internal CIDR blocks and prevent unauthorized network access.
EgressPolicy does not affect external services declared with a ServiceEntry. The two methods do not conflict.
Usage notes
-
EgressPolicy does not guarantee interception of all outbound traffic at the mesh level. Workloads explicitly excluded from the mesh can bypass these policies. We recommend using Kubernetes NetworkPolicy as part of a defense-in-depth strategy.
-
The order of rules in an EgressPolicy determines the matching priority. The first matching rule is applied.
-
To implement global control based on domain names instead of IP addresses, use the ServiceEntry method. The
matchCidrsfield in an EgressPolicy only matches destination IP addresses.