当网格内的应用需要与外部服务进行通信时,您可以使用出口网关作为统一的出口,集中管理所有的出站流量。通过配置出口网关,您可以实现对流量的安全控制和路由,提升网格内应用程序的安全性和可观测性。
阅读本文前,请确保您已经了解使用ASMEgressTrafficPolicy管理出口流量中的内容。本文使用服务网格资源实现了将访问集群外服务的请求透明劫持到出口网关,由出口网关执行安全策略,然后发送给集群外服务,配置相对复杂。如果使用ASMEgressTrafficPolicy管理出口流量中的内容无法满足您的需求,再参考本文。
前提条件
配置流程
步骤一:部署示例应用
部署sleep应用。
使用以下内容,创建sleep.yaml。
在ACK集群对应的KubeConfig环境下,执行以下命令,部署sleep应用。
关于如何使用kubectl管理集群,请参见获取集群KubeConfig并通过kubectl工具连接集群。
kubectl apply -f sleep.yaml
执行以下命令,进入sleep Pod,访问外部服务。
您可以通过
kubectl get pod -n default
命令,查看sleep Pod的名称。kubectl exec -it ${sleep Pod的名称} -- /bin/sh curl aliyun.com -I
示例输出:
HTTP/1.1 301 Moved Permanently server: envoy date: Thu, 14 Dec 2023 03:05:41 GMT content-type: text/html content-length: 239 location: https://aliyun.com/ eagleeye-traceid: 0b57ff8717025231418255220e**** timing-allow-origin: * x-envoy-upstream-service-time: 69
返回301,表示网格内应用可以正常访问外部服务。此处默认使用HTTP协议访问,网站会返回重定向响应。
说明ASM默认允许访问所有外部服务,采用此方式无法进行安全权限控制,也无法使用网格提供的各种可观测能力。建议您参照下文,开启REGISTRY_ONLY,限制可访问的服务,并使用出口网关作为流量统一出口。
(可选)步骤二:开启REGISTRY_ONLY
ASM的外部服务访问策略默认为ALLOW_ANY,建议您将其修改为REGISTRY_ONLY。Sidecar代理将阻止应用访问未在网格中定义服务条目的外部主机,保障网格内应用的安全。
若您已开启REGISTRY_ONLY,但未创建服务条目(ServiceEntry),外部服务访问会被拒绝。
若您未开启REGISTRY_ONLY,也未创建服务条目(ServiceEntry),可以正常访问服务,但是配置的出口网关不会生效。
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在Sidecar代理配置页面,单击全局页签,单击外部服务访问策略,配置对外部服务的访问策略OutboundTrafficPolicy为REGISTRY_ONLY,然后单击更新设置。
执行以下命令,进入sleep Pod,访问外部服务。
kubectl exec -it ${sleep Pod的名称} -- /bin/sh curl aliyun.com -I
示例输出:
HTTP/1.1 502 Bad Gateway date: Thu, 14 Dec 2023 03:08:46 GMT server: envoy transfer-encoding: chunked
返回502,表示网格内应用无法访问未经注册的外部服务。
步骤三:为外部服务创建服务条目(ServiceEntry)
对集群外的服务创建ServiceEntry,集群内应用才能使用出口网关访问对应的外部服务。
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 ,然后单击使用YAML创建。
在创建页面,选择sleep应用所在的命名空间,场景模板选择访问网格外部服务,配置如下YAML示例,然后单击创建。
apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-svc-http spec: hosts: - aliyun.com location: MESH_EXTERNAL ports: - number: 80 name: http protocol: HTTP resolution: DNS
执行以下命令,进入sleep Pod,访问外部服务。
kubectl exec -it ${sleep Pod的名称} -- /bin/sh curl aliyun.com -I
返回
301
,表示网格内应用可以正常访问外部服务。在网格内使用ServiceEntry注册了aliyun.com,所以允许应用访问该外部服务。此时外部流量直接从各个Pod发出,并没有从统一的出口网关发出。
步骤四:使用出口网关作为外部服务的统一出口
上文已为aliyun.com创建了ServiceEntry,因此可以使用虚拟服务、网关规则等功能来管理访问aliyun.com的流量。
创建出口网关,配置HTTP协议和80端口。具体操作,请参见创建出口网关。
按照以下内容,创建网关规则。具体操作,请参见管理网关规则。
使用以下YAML,创建虚拟服务。具体操作,请参见管理虚拟服务。
测试访问外部服务。
执行以下命令,进入sleep Pod,访问外部服务。
kubectl exec -it ${sleep Pod的名称} -- /bin/sh curl aliyun.com -I
返回301,表示网格内应用可以正常访问外部服务。此时网格内应用不是直接从Pod访问服务,而是通过上文创建的出口网关访问服务。
执行以下命令,在网关Pod中查看访问日志。
说明若您的出口网关Pod有多个副本,产生的访问日志会在某个Pod上。您需要依次在所有网关Pod上执行此命令,才能找到对应的访问日志。
如果您开启了出口网关的访问日志,也可以登录日志服务控制台查看访问记录。
kubectl -n istio-system logs ${出口网关Pod名称} -c istio-proxy | grep aliyun.com | tail -n 1
示例输出:
{"trace_id":null,"upstream_host":"106.11.XXX.XX:80","downstream_remote_address":"10.34.0.140:47942","requested_server_name":null,"response_code":301,"upstream_service_time":"24","user_agent":"curl/7.86.0-DEV","path":"/","route_name":null,"bytes_sent":0,"response_flags":"-","upstream_local_address":"10.34.0.141:60388","duration":24,"upstream_cluster":"outbound|80||aliyun.com","upstream_transport_failure_reason":null,"authority":"aliyun.com","request_id":"55789d59-9b81-4e39-b64a-66baf44e****","protocol":"HTTP/1.1","bytes_received":0,"method":"HEAD","downstream_local_address":"10.34.0.141:80","start_time":"2022-11-30T08:03:01.315Z","istio_policy_status":null,"x_forwarded_for":"10.34.0.140"}
downstream_remote_address
表示sleep Pod的IP地址。完成上述配置之后,相应的外部服务流量会通过出口网关向集群外发出,您可以在网关上使用ASM提供的可观测以及安全相关的能力,更加高效地管理出口流量。
相关文档
您可以在出口网关上使用ASM提供的可观测和安全相关的能力,更加高效地管理出口流量。具体操作,请参见可观测性能力和安全支持及证书动态加载。
您可以使用ASMEgressTrafficPolicy CRD,自定义如何通过出口网关来管理和访问外部流量。具体操作,请参见使用ASMEgressTrafficPolicy管理出口流量。
关于网关的更多功能介绍,请参见ASM网关概述。