服务网格 ASM(Service Mesh)在出口流量管理方面,提供了多种灵活且高效的解决方案,为应用程序的安全性、可观测性和可靠性提供支持。本文将介绍ASM在出口流量管理方面提供的多种功能以及为什么要使用ASM出口网关。
丰富的出口流量管理能力
服务网格提供了丰富的管理L7出口流量的能力(流量路由、可观测、安全等),您可以根据需求选择要如何进行配置来实现相应的功能。
如果应用直接发起HTTPS请求,网格代理只能将其当成普通的TLS流量处理,网格的L7能力将会失效。因此,请确保您的应用发出的请求为HTTP明文请求。网格会根据您的配置,直接将HTTP请求转发给外部服务,或者自动将请求转换成HTTPS请求发往外部服务。
流量路由
在访问集群外HTTP服务时,您只需要在服务网格中配置对应的Service Entry,就可以使用例如出口【Mirroring】镜像流量、出口流量按比例路由和虚拟服务中的其他高级能力。如果您访问的服务是HTTPS协议,需要再配置一个对应的DestinationRule。流量路由能力并不依赖ASM出口网关。
观测出口流量
如果请求是明文流量,您无需做任何操作即可通过日志、监控指标和链路追踪等方式观测出口流量。如果请求的流量需要加密,您只需要配置Service Entry和DestinationRule。应用发起明文流量,Sidecar自动将明文流量加密后进行转发。此时可以使用网格完整的可观测能力,该功能并不依赖ASM出口网关。
集群外服务管理简介
在Ambient模式中,Ztunnel会拦截进出业务Pod的所有流量,并且对于业务Pod发出的流量,如果Ztunnel并不知道该服务的具体信息,就会选择原样转发。
默认情况下,客户端发出一个访问外部服务请求时,Ztunnel中并没有这个服务的信息,因此会直接转发。
当我们想要严格控制外部服务的访问时,应该首先拒绝当前业务Pod访问任何集群外的IP。
禁止业务Pod直接访问外部服务之后,您可以在网格中通过ServiceEntry注册合法的外部服务,并且通过给ServiceEntry启用Waypoint(不要限制Waypoint Pod的外部访问),让所有访问ServiceEntry的流量被转发给Waypoint,在Waypoint处执行各种请求转换、安全策略以及可观测策略之后,再通过Waypoint转发给真正的外部服务。流量路径如下图所示:
操作示例
步骤一:部署测试应用
部署示例应用。
apiVersion: v1 kind: ServiceAccount metadata: name: sleep --- apiVersion: v1 kind: Service metadata: name: sleep labels: app: sleep service: sleep spec: ports: - port: 80 name: http selector: app: sleep --- apiVersion: apps/v1 kind: Deployment metadata: name: sleep spec: replicas: 1 selector: matchLabels: app: sleep template: metadata: labels: app: sleep spec: terminationGracePeriodSeconds: 0 serviceAccountName: sleep containers: - name: sleep image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/curl:asm-sleep command: ["/bin/sleep", "infinity"] imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /etc/sleep/tls name: secret-volume volumes: - name: secret-volume secret: secretName: sleep-secret optional: true ---
说明请确保测试应用所在的命名空间已经启用Amient模式。
测试访问外部服务。
kubectl exec deployment/sleep -- curl aliyun.com -s -I
预期输出:
HTTP/1.1 301 Moved Permanently Server: Tengine Date: Wed, 20 Aug 2025 07:56:27 GMT Content-Type: text/html Content-Length: 239 Connection: keep-alive Location: https://aliyun.com/ EagleEye-TraceId: 0b87b7b217556765878011141ee221 Timing-Allow-Origin: *
步骤二:使用ASM统一管理外部服务访问
在ASM控制台新建命名空间:istio-egress,并且为该命名空间开启Ambient模式。
在istio-egress命名空间下创建Waypiont。
kubectl apply -n istio-egress -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: waypoint spec: gatewayClassName: istio-waypoint listeners: - name: mesh port: 15008 protocol: HBONE EOF
为当前命名空间启用Waypoint。
kubectl label namespace istio-egress istio.io/use-waypoint=waypoint --overwrite
步骤三:创建ServiceEntry并测试
创建ServiceEntry。
kubectl apply -n istio-egress -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: external-svc-aliyun spec: hosts: - aliyun.com location: MESH_EXTERNAL ports: - number: 80 name: http protocol: HTTP - number: 443 name: https protocol: HTTPS resolution: DNS EOF
测试访问。
kubectl exec deployment/sleep -- curl aliyun.com -s -I
预期输出:
HTTP/1.1 301 Moved Permanently server: envoy date: Mon, 18 Aug 2025 09:36:30 GMT content-type: text/html content-length: 239 location: https://aliyun.com/ eagleeye-traceid: 0be3e0ac17555097903637743e684e timing-allow-origin: * x-envoy-upstream-service-time: 27
可以看到正常返回了301状态码。说明请求经由istio-egress命名空间的Waypoint转发出去,成功访问了外部服务。您可以使用以下命令查看Waypoint的对应日志:
kubectl -n istio-egress logs deployments/waypoint | tail -1 | jq
预期输出:
{ "authority_for": "aliyun.com", "bytes_received": 0, "bytes_sent": 239, "downstream_local_address": "240.240.0.7:80", "downstream_remote_address": "172.16.5.26:33356", "duration": 24, "istio_policy_status": null, "method": "GET", "path": "/", "protocol": "HTTP/1.1", "request_id": "234a2e8b-e170-42f6-b9db-693cd757974d", "requested_server_name": null, "response_code": 301, "response_flags": "-", "route_name": "default", "start_time": "2025-08-20T08:06:06.502Z", "trace_id": null, "upstream_cluster": "inbound-vip|80|http|aliyun.com;", "upstream_host": "140.205.135.3:80", "upstream_local_address": "172.16.5.23:34524", "upstream_response_time": "23", "upstream_service_time": "23", "upstream_transport_failure_reason": null, "user_agent": "curl/8.8.0", "x_forwarded_for": null }
步骤五:应用发起HTTP请求,由Waypoint升级为HTTPS
默认情况下,Waypoint使用同样的协议转发收到的请求,比如应用发起HTTP,Waypoint就通过HTTP访问外部服务;应用如果使用HTTPS,Waypoint就会直接转发HTTPS流量。
但是由于HTTPS流量是加密的,Waypoint无法看到其中的L7信息,只能执行一些TCP层面的鉴权和流量路由,无法使用7层高级能力。这种场景下,我们推荐应用发起HTTP,然后由Waypoint执行HTTPS升级,最终使用HTTPS访问外部服务。由于应用到Waypoint之间是mTLS,所以整个链路依然是加密的。
更新ServiceEntry,如果应用访问80端口,Waypoint会转发给外部服务的443端口。
kubectl apply -n istio-egress -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: external-svc-aliyun spec: hosts: - aliyun.com location: MESH_EXTERNAL ports: - number: 80 name: http protocol: HTTP targetPort: 443 - number: 443 name: https protocol: HTTPS resolution: DNS EOF
配置一个DestinationRule,让Waypoint对该服务的443端口执行HTTPS升级。
kubectl apply -n istio-egress -f - <<EOF apiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: aliyun-com spec: host: aliyun.com trafficPolicy: portLevelSettings: - port: number: 80 tls: mode: SIMPLE EOF
测试访问。
kubectl exec deployment/sleep -- curl aliyun.com -s -I
预期输出:
HTTP/1.1 301 Moved Permanently server: envoy date: Mon, 18 Aug 2025 09:36:30 GMT content-type: text/html content-length: 239 location: https://aliyun.com/ eagleeye-traceid: 0be3e0ac17555097903637743e684e timing-allow-origin: * x-envoy-upstream-service-time: 27
此时再次查看Waypoint的日志,可以看到请求已经转发到了443端口。