ASM自1.16.4版本起,支持使用ASMEgressTrafficPolicy CRD。本文介绍如何使用ASMEgressTrafficPolicy管理出口流量。
前提条件
功能介绍
ASM提供了一种统一的方式来连接、管理和保护应用程序之间的通信。与基于网络IP的方法不同,ASM采用以应用程序为中心的方法,且无需修改现有的应用代码。ASMEgressTrafficPolicy定义了如何通过出口网关来管理和访问外部流量。通过结合ASM出口网关和AuthorizationPolicy,您可以更灵活地控制出口流量。
准备工作
一、设置外部服务访问策略
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在全局页签,单击外部服务访问策略,然后在对外部服务的访问策略OutboundTrafficPolicy右侧,单击REGISTRY_ONLY,然后单击更新设置。
二、创建命名空间
创建istio-egress命名空间。具体操作,请参见管理全局命名空间。
在全局命名空间页面,单击同步自动注入至Kubernetes集群,将该命名空间同步至ASM实例管理的ACK集群。
三、创建出口网关
在ASM中创建一个名为egressgateway-a的出口网关,端口映射配置为HTTP 80、HTTPS 443和HTTPS 444,并开启支持双向TLS认证。具体操作,请参见创建出口网关服务。
请确保在生成的YAML文件中,spec字段中包含以下内容。若不存在,请进行添加。
spec:
podLabels:
security.istio.io/tlsMode: istio
四、创建应用示例
在ASM实例中,创建名为mytest的命名空间并开启自动注入。具体操作,请参见管理全局命名空间。
在ACK集群中,在mytest命名空间中部署sleep-a服务,在default命名空间中部署nginx服务。
使用以下内容,创建test.yaml。
在ACK集群中,执行以下命令,部署sleep-a和nginx服务。
kubectl apply -f test.yaml
执行以下命令,通过sleep-a和nginx服务访问
http://www.httpbin.org
。kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org kubectl -n default exec deployment/nginx -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org
输出结果均返回
502
,表明访问失败。
场景一:仅mytest命名空间下的sleep-a服务可访问http://www.httpbin.org
使用以下内容,创建egress-by-egressgateway-a.yaml。
关于字段的相关说明,请参见ASMEgressTrafficPolicy CRD说明。
apiVersion: istio.alibabacloud.com/v1 kind: ASMEgressTrafficPolicy metadata: name: egress-by-egressgateway-a # 名称约定为egress-by-{出口网关名称},与出口网关对应。 namespace: istio-egress # 命名空间约定:固定到istio-egress命名空间。 spec: byEgressGateway: name: egressgateway-a egressRules: - from: - namespace: mytest workloadSelector: app: sleep-a to: - name: httpbin-service-http hosts: - www.httpbin.org # 要求多个域名对应DNS解析返回的地址保持一致。 - httpbin.org # 要求多个域名对应DNS解析返回的地址保持一致。 port: name: http number: 80 protocol: HTTP byEgressGateway: port: 80 # Sidecar → 80 Gateway → 80 Service (httpbin.org)
在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。
kubectl apply -f egress-by-egressgateway-a.yaml
验证ASMEgressTrafficPolicy配置是否生效。
执行以下命令,通过default命名空间下的nginx服务访问
http://www.httpbin.org
。kubectl -n default exec deployment/nginx -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org
输出结果返回
502
,表明nginx服务访问http://www.httpbin.org
失败。执行以下命令,通过mytest命名空间下的sleep-a服务访问
http://www.httpbin.org
。kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org
输出结果返回
200
,符合预期。执行以下命令,删除egress-by-egressgateway-a后,再次通过mytest命名空间下的sleep-a服务访问
http://www.httpbin.org
。kubectl -n istio-egress delete ASMEgressTrafficPolicy egress-by-egressgateway-a kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org
输出结果返回
502
,表明删除ASMEgressTrafficPolicy配置后,sleep-a服务http://www.httpbin.org
失败。
输出以上结果,表明ASMEgressTrafficPolicy配置生效。
场景二:将HTTP请求升级为HTTPS后,仅mytest命名空间下的sleep-a服务可直接访问http://www.httpbin.org和https://www.httpbin.org
使用以下内容,创建egress-by-egressgateway-a.yaml。
在spec字段下增加httpsUpgrade字段和直接访问
https://www.httpbin.org
的相关定义。关于字段的相关说明,请参见ASMEgressTrafficPolicy CRD说明。apiVersion: istio.alibabacloud.com/v1 kind: ASMEgressTrafficPolicy metadata: name: egress-by-egressgateway-a # 名称约定为egress-by-{出口网关名称},与出口网关对应。 namespace: istio-egress # 命名空间约定:固定到istio-egress命名空间。 spec: byEgressGateway: name: egressgateway-a egressRules: - from: - namespace: mytest workloadSelector: app: sleep-a to: - name: httpbin-service-http hosts: - www.httpbin.org # 要求多个域名对应DNS解析返回的地址一致。 - httpbin.org # 要求多个域名对应DNS解析返回的地址一致。 port: name: http number: 80 protocol: HTTP byEgressGateway: port: 80 # Sidecar → 80 Gateway → 80 Service (httpbin.org) httpsUpgrade: enabled: true # 若enabled配置为false,则httpsUpgrade对应的port不生效。 port: 443 # Sidecar → 80 Gateway → 443 Service (httpbin.org) - name: httpbin-service-https hosts: - www.httpbin.org - httpbin.org port: name: https number: 443 protocol: HTTPS byEgressGateway: port: 444 # 准备工作的第三步中,出口网关定义的HTTPS 444端口。
在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。
kubectl apply -f egress-by-egressgateway-a.yaml
验证ASMEgressTrafficPolicy配置是否生效。
验证mytest命名空间下的sleep-a服务。
执行以下命令,通过sleep-a服务访问
http://www.httpbin.org
。kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" http://httpbin.org
输出结果返回
200
,表明sleep-a服务访问http://www.httpbin.org
成功。执行以下命令,请求
httpbin.org
的anything
接口,验证出口网关是否将HTTP请求升级为HTTPS请求。kubectl -n mytest exec deployment/sleep-a -- sh -c "curl -s http://httpbin.org/anything |grep url"
预期输出:
"url": "https://httpbin.org/anything"
如果
url
字段信息以https
开头,表明出口网关将请求成功升级为https
,然后转发给httpbin.org
。执行以下命令,通过mytest命名空间下的sleep-a服务访问
https://www.httpbin.org
。kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" https://www.httpbin.org
输出结果返回
200
,表明sleep-a服务访问https://www.httpbin.org
成功。
验证default命名空间下的nginx服务。
执行以下命令,通过nginx服务访问
http://www.httpbin.org
。kubectl -n default exec deployment/nginx -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org
输出结果返回
502
,表明nginx服务访问http://www.httpbin.org
失败。执行以下命令,通过nginx服务访问
https://www.httpbin.org
。kubectl -n default exec deployment/nginx -- curl -s -o /dev/null -w "%{http_code}\n" https://www.httpbin.org
输出结果显示请求连接被拒绝,表明nginx服务访问
https://www.httpbin.org
失败。执行以下命令,查看nginx工作负载对应的Sidecar的accessLog,了解连接被拒绝的原因。
kubectl -n default logs -f deployment/nginx -c istio-proxy --tail=1
预期输出:
{"authority":"-","bytes_received":"0","bytes_sent":"0","downstream_local_address":"52.86.68.46:443","downstream_remote_address":"172.16.0.199:56748","duration":"0","istio_policy_status":"-","method":"-","path":"-","protocol":"-","request_id":"-","requested_server_name":"-","response_code":"0","response_flags":"UH","route_name":"-","start_time":"2023-04-11T02:00:07.409Z","trace_id":"-","upstream_cluster":"BlackHoleCluster","upstream_host":"-","upstream_local_address":"-","upstream_service_time":"-","upstream_transport_failure_reason":"-","user_agent":"-","x_forwarded_for":"-"}
预期输出表明,请求转发给
BlackHoleCluster
,因此导致连接被拒绝。
执行以下命令,删除egress-by-egressgateway-a后,再次通过mytest命名空间下的sleep-a服务访问
http://www.httpbin.org
和https://www.httpbin.org
。kubectl -n istio-egress delete ASMEgressTrafficPolicy egress-by-egressgateway-a kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" http://www.httpbin.org kubectl -n mytest exec deployment/sleep-a -- curl -s -o /dev/null -w "%{http_code}\n" https://www.httpbin.org
访问
http://www.httpbin.org
时,返回502
;访问https://www.httpbin.org
时,请求连接被拒绝。删除ASMEgressTrafficPolicy配置后,sleep-a服务无法访问http://www.httpbin.org
和https://www.httpbin.org
。
输出以上结果,表明ASMEgressTrafficPolicy配置生效。
相关操作
拒绝来自指定命名空间下的POST请求
通过ASM出口网关结合ASMEgressTrafficPolicy,您可以灵活地控制集群内向外的外部流量。结合AuthorizationPolicy,您还可以进行更细粒度的访问控制。例如,通过如下定义拒绝来自mytest命名空间下的POST请求。
kind: AuthorizationPolicy
apiVersion: security.istio.io/v1beta1
metadata:
name: sleep-a-egress-www-httpbin-org
namespace: istio-system
spec:
action: DENY
rules:
- to:
- operation:
hosts:
- www.httpbin.org
- httpbin.org
methods:
- POST
from:
- source:
namespaces: ["mytest"]
selector:
matchLabels:
istio: egressgateway-a
应用上述配置后,通过sleep-a服务采用POST方式的请求访问www.httpbin.org,将返回RBAC: access
,通过GET方式的请求访问www.httpbin.org则不受影响。