Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article shows you how to deploy egress gateways for the Istio service mesh add-on for Azure Kubernetes Service (AKS) cluster.
Overview
The Istio egress gateway can serve as a centralized point to monitor and restrict outbound traffic from applications in the mesh. With the Istio add-on, you can deploy multiple egress gateways across different namespaces, allowing you to set up an egress gateway topology of your choice: egress gateways per-cluster, per-namespace, per-workload, etc. While AKS manages the provisioning and lifecycle of the Istio add-on egress gateways, you must create Istio custom resources to route traffic from applications in the mesh through the egress gateway and apply policies and telemetry collection.
The Istio add-on egress gateway also builds on top of and requires the Static Egress Gateway feature, which assigns a fixed source IP address prefix to the Istio egress Pods. You can use this predicable egress IP range for firewall rules and other outbound traffic filtering mechanisms. By using Istio egress gateway on top of Static Egress Gateway, you can apply Istio L7, identity-based policies, and IP-based restrictions for defense-in-depth egress traffic control. Additionally, directing outbound traffic through the Istio egress gateway allows multiple workloads to route traffic via the Static Egress Gateway node pools without modifying those application pods/deployments directly.
Limitations and requirements
- You can enable a maximum of
500Istio add-on egress gateways per cluster. - Istio add-on egress gateway names must be unique per namespace.
- Istio add-on egress gateway names must be between
1-53characters, must only consist of lowercase alphanumerical characters, '-' and '.,' and must start and end with an alphanumerical character. Names should also be a valid Domain Name System (DNS) name. The regex used for name validation is^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$. - Using the Kubernetes Gateway API for egress traffic management with the Istio add-on is only supported for the manual deployment model.
Prerequisites
Enable Istio add-on
This guide assumes you followed the documentation to enable the Istio add-on on an AKS cluster.
Install the aks-preview Azure CLI extension
Install the aks-preview extension if you're using Azure CLI. You must use aks-preview version 14.0.0b2 or higher.
Install the
aks-previewextension using theaz extension addcommand.az extension add --name aks-previewUpdate to the latest version of the extension using the
az extension updatecommand.az extension update --name aks-preview
Enable and configure Static Egress Gateway
Follow the instructions in the Static Egress Gateway documentation to enable Static Egress Gateway on your cluster, create a node pool of mode gateway, and create a StaticGatewayConfiguration resource.
Enable an Istio egress gateway
Note
The Istio add-on egress gateway pods don't get scheduled onto the gateway node pool. The gateway node pool is only used to route egress traffic and doesn't serve general-purpose workloads. If you need the egress gateway pods scheduled onto particular nodes, you can use AKS system nodes or the azureservicemesh/istio.replica.preferred node label. The pods have node affinities with a weighted preference of 100 for AKS system nodes (labeled kubernetes.azure.com/mode: system), and a weighted preference of 50 for nodes labeled azureservicemesh/istio.replica.preferred: true.
Use az aks mesh enable-egress-gateway to enable an Istio egress gateway on your AKS cluster. You must specify a name for the Istio egress gateway and the name of the StaticGatewayConfiguration that you created in the prerequisites step. You can also specify a namespace to deploy the Istio egress gateway in, which must be the same namespace that the StaticGatewayConfiguration was created in. If you don't specify a namespace, the egress gateway gets provisioned in the aks-istio-egress namespace.
As a best-practice, you should wait until the StaticGatewayConfiguration is assigned an egressIpPrefix before enabling the Istio egress gateway using that gateway configuration.
az aks mesh enable-egress-gateway --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --istio-egressgateway-name $ISTIO_EGRESS_NAME --istio-egressgateway-namespace $ISTIO_EGRESS_NAMESPACE --gateway-configuration-name $ISTIO_SGC_NAME
Verify that the service gets created for the egress gateway.
kubectl get svc $ISTIO_EGRESS_NAME -n $ISTIO_EGRESS_NAMESPACE
You should see a ClusterIP service for the egress gateway:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
asm-egress-test ClusterIP 10.0.128.17 <none> 15021/TCP,80/TCP,443/TCP 6d4h
You can also verify that a deployment gets created for the Istio egress gateway and that the egress gateway pods have the kubernetes.azure.com/static-gateway-configuration annotation set to the gatewayConfigurationName.
ASM_REVISION=$(az aks show -g $RESOURCE_GROUP -n $CLUSTER_NAME | jq '.serviceMeshProfile.istio.revisions[0]' | sed 's/"//g')
kubectl get deployment $ISTIO_EGRESS_NAME-$ASM_REVISION -n $ISTIO_EGRESS_NAMESPACE -o jsonpath={.spec.template.metadata.annotations."kubernetes\.azure\.com\/static-gateway-configuration"}
You can run the az aks mesh enable-egress-gateway command again to create another Istio egress gateway.
Note
When you perform a minor revision upgrade of the Istio add-on, another deployment for each egress gateway gets created for the new control plane revision.
Route traffic through the Istio egress gateway
Set outboundTrafficPolicy.mode
By default, the Istio outboundTrafficPolicy.mode is set to ALLOW_ANY, meaning that Envoy passes through requests for unknown services. As a security best-practice, you should set the Istio outboundTrafficPolicy.mode to REGISTRY_ONLY so that the Istio proxy blocks requests to services that weren't added to Istio's Service Registry. You can add hosts outside of the cluster to Istio's service registry with a ServiceEntry.
You can configure the outboundTrafficPolicy.mode on a mesh-wide level using the Istio add-on shared MeshConfig, or use the Sidecar Custom Resource to target specific namespaces or workloads.
apiVersion: v1
kind: ConfigMap
metadata:
name: istio-shared-configmap-asm-1-24
namespace: aks-istio-system
data:
mesh: |-
outboundTrafficPolicy:
mode: REGISTRY_ONLY
Deploy sample application
In this example, we deploy the curl application in the same namespace as the Istio add-on egress gateway. Remember to label the ISTIO_EGRESS_NAMESPACE with the istio.io/rev label so that the deployed application pod gets injected with a sidecar:
kubectl label namespace $ISTIO_EGRESS_NAMESPACE istio.io/rev=$ASM_REVISION
Then, deploy the sample application:
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.24/samples/curl/curl.yaml -n $ISTIO_EGRESS_NAMESPACE
You should see the curl pod running with an injected sidecar container:
NAME READY STATUS RESTARTS AGE
curl-5b549b49b8-bcgts 2/2 Running 0 13s
Try sending a request from curl directly to edition.cnn.com:
SOURCE_POD=$(kubectl get pod -n $ISTIO_EGRESS_NAMESPACE -l app=curl -o jsonpath={.items..metadata.name})
kubectl exec -n $ISTIO_EGRESS_NAMESPACE "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics
If you set outboundTrafficPolicy.mode to REGISTRY_ONLY, then the curl request should fail because you didn't create a ServiceEntry for edition.cnn.com. If outboundTrafficPolicy.mode is ALLOW_ANY, then the request should succeed.
To actually route requests to edition.cnn.com from the curl pod to the Istio add-on egress gateway, you need to create a ServiceEntry and configure other Istio custom resources. Follow instructions one of the subsequent sections to configure an HTTP Egress Gateway, HTTPS Egress Gateway, or an Egress Gateway that originates a Transport Layer Security (TLS) connection.
Before starting any of the following scenarios, set these environment variables:
ISTIO_EGRESS_DEPLOYMENT=$ISTIO_EGRESS_NAME-$ASM_REVISION
EGRESS_GTW_SELECTOR=$(kubectl get deployment $ISTIO_EGRESS_DEPLOYMENT -n $ISTIO_EGRESS_NAMESPACE -o jsonpath={.metadata.labels.istio})
You can also enable Envoy access logging either through the MeshConfig or Telemetry API. Once you have access logging enabled, you can verify that traffic is flowing through the egress gateway by inspecting the istio-proxy container logs:
kubectl logs -l istio=$EGRESS_GTW_SELECTOR -n $ISTIO_EGRESS_NAMESPACE
Configure an HTTP Istio egress gateway
- Create a
ServiceEntryforedition.cnn.com:
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
- Create the
Gateway,VirtualService, andDestinationRuleto route HTTP traffic from thecurlapplication toedition.cnn.comthrough the egress gateway. Be sure to set the gateway selector and service Fully Qualified Domain Name (FQDN) accordingly based on theistiolabel selector in the egress gateway deployment.
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: $EGRESS_GTW_SELECTOR
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- edition.cnn.com
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
subsets:
- name: cnn
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 80
weight: 100
EOF
- Try sending an HTTP request from the
curlpod toedition.cnn.com:
kubectl exec -n $ISTIO_EGRESS_NAMESPACE "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics
You should see an HTTP/2 200 response.
- Clean up resources
kubectl delete serviceentry cnn -n $ISTIO_EGRESS_NAMESPACE
kubectl delete gateway istio-egressgateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete virtualservice direct-cnn-through-egress-gateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule egressgateway-for-cnn -n $ISTIO_EGRESS_NAMESPACE
Configure an HTTPS Istio egress gateway
- Create an HTTPS
ServiceEntryforedition.cnn.com:
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 443
name: tls
protocol: TLS
resolution: DNS
EOF
- Create the
Gateway,VirtualService, andDestinationRuleto route HTTP traffic from thecurlapplication toedition.cnn.comthrough the egress gateway. Be sure to set the gateway selector and service FQDN accordingly based on theistiolabel selector in the egress gateway deployment.
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: $EGRESS_GTW_SELECTOR
servers:
- port:
number: 443
name: tls
protocol: TLS
hosts:
- edition.cnn.com
tls:
mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
subsets:
- name: cnn
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- mesh
- istio-egressgateway
tls:
- match:
- gateways:
- mesh
port: 443
sniHosts:
- edition.cnn.com
route:
- destination:
host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
subset: cnn
port:
number: 443
- match:
- gateways:
- istio-egressgateway
port: 443
sniHosts:
- edition.cnn.com
route:
- destination:
host: edition.cnn.com
port:
number: 443
weight: 100
EOF
- Try sending an HTTPS request from
curltoedition.cnn.com:
kubectl exec "$SOURCE_POD" -n $ISTIO_EGRESS_NAMESPACE -c curl -- curl -sSL -o /dev/null -D - https://edition.cnn.com/politics
You should see an HTTP/2 200 response.
- Clean up resources
kubectl delete serviceentry cnn -n $ISTIO_EGRESS_NAMESPACE
kubectl delete gateway istio-egressgateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete virtualservice direct-cnn-through-egress-gateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule egressgateway-for-cnn -n $ISTIO_EGRESS_NAMESPACE
Configure an Istio egress gateway to perform TLS Origination
- Create a
ServiceEntryforedition.cnn.com:
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
- Create the
Gateway,VirtualService, andDestinationRuleto route HTTP traffic from thecurlapplication toedition.cnn.comthrough the egress gateway, and to perform TLS origination at the egress gateway. Be sure to set the gateway selector and service FQDN accordingly based on theistiolabel selector in the egress gateway deployment.
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: $EGRESS_GTW_SELECTOR
servers:
- port:
number: 80
name: https-port-for-tls-origination
protocol: HTTPS
hosts:
- edition.cnn.com
tls:
mode: ISTIO_MUTUAL
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
subsets:
- name: cnn
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 80
tls:
mode: ISTIO_MUTUAL
sni: edition.cnn.com
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 443
weight: 100
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: originate-tls-for-edition-cnn-com
spec:
host: edition.cnn.com
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 443
tls:
mode: SIMPLE # initiates HTTPS for connections to edition.cnn.com
EOF
- Try sending a request form
curltoedition.cnn.comwith the egress gateway performing TLS origination;
kubectl exec "${SOURCE_POD}" -n $ISTIO_EGRESS_NAMESPACE -c curl -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics
You should see a 200 status response.
- Clean up resources
kubectl delete serviceentry cnn -n $ISTIO_EGRESS_NAMESPACE
kubectl delete gateway istio-egressgateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete virtualservice direct-cnn-through-egress-gateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule originate-tls-for-edition-cnn-com -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule egressgateway-for-cnn -n $ISTIO_EGRESS_NAMESPACE
Disable the Istio egress gateway
Run the az aks mesh disable-egress-gateway command to disable the Istio add-on egress gateway that you created:
az aks mesh disable-egress-gateway --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --istio-egressgateway-name $ISTIO_EGRESS_NAME --istio-egressgateway-namespace $ISTIO_EGRESS_NAMESPACE
Once you disable the Istio egress gateway, you should be able to delete the StaticGatewayConfiguration, namespace, and gateway node pool that the egress gateway was using if no other Istio egress gateway is using them.
Next steps
- Deploy external or internal ingresses for Istio service mesh add-on
- Configure egress gateway Horizontal Pod Autoscaler (HPA)
Note
If there are any issues encountered with deploying the Istio egress gateway or configuring egress traffic routing, refer to article on troubleshooting Istio add-on egress gateways