使用ASMEgressTrafficPolicy管理出口流量

ASM自1.16.4版本起,支持使用ASMEgressTrafficPolicy CRD。本文介绍如何使用ASMEgressTrafficPolicy管理出口流量。

背景信息

实现原理

服务网格支持出口流量管理,通过创建ServiceEntry、VirtualService、Gateway以及Destination等多个资源,并且确保这些资源之间相互关联,配置完成后即可实现将流量透明劫持到出口网关,并由出口网关转发给外部服务。

这些配置比较复杂,需要您对相关字段的含义有较为深入的理解,而且容易配置出错。为了降低出口流量配置门槛,ASM推出了ASMEgressTrafficPolicy资源。

ASMEgressTrafficPolicy将出口流量配置进行了抽象和简化,您无需手动配置ServiceEntry、VirtualService、Gateway以及Destination等资源,只需要填写一些必要配置,即可实现将流量透明劫持到出口网关,并且通过HTTP/HTTPS协议发送给外部服务。

由于ASMEgressTrafficPolicy对服务网格原生资源进行了简化,可能并不能满足您的一些高级需求(比如出口流量按比例路由、出口网关发起mTLS等)。如果您需要使用一些高级功能,例如添加自定义配置,请参见为网格内流量配置统一的出口网关

功能介绍

ASM提供了一种统一的方式来连接、管理和保护应用程序之间的通信。与基于网络IP的方法不同,ASM采用以应用程序为中心的方法,且无需修改现有的应用代码。ASMEgressTrafficPolicy定义了如何通过出口网关来管理和访问外部流量。通过结合ASM出口网关和AuthorizationPolicy,您可以更灵活地控制出口流量。Dingtalk_20230411112608

本文示例的流量链路可以分为两大类:

1. 网格代理之间以及网格代理和网关之间的通信:通信默认开启mTLS,证书完全由ASM管理。

2. 应用与网格代理之间以及网关和集群外服务之间:

a. 为了网格7层高级能力可以正常运行,应用与网格代理之间尽量采用明文通信。这样网格代理可以获取流量的L7信息,支持更多的高级功能。如果由于某些特殊原因,应用必须直接发起HTTPS,这时只能使用网格的L4能力。

b. 出口网关和外部服务之间的通信协议用户可以自行配置,明文或者HTTPS都可以。

前提条件

  • 已创建ASM商业版实例(企业版或旗舰版),且版本为1.16.4及以上。关于创建实例的具体操作,请参见创建ASM实例;关于升级实例的具体操作,请参见升级ASM实例

  • 已为default命名空间开启自动注入。具体操作,请参见启用自动注入

准备工作

一、设置外部服务访问策略

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择数据面组件管理 > Sidecar代理配置

  3. 全局页签,单击外部服务访问策略,然后在对外部服务的访问策略OutboundTrafficPolicy右侧,单击REGISTRY_ONLY,然后单击更新设置

二、创建命名空间

  1. 创建istio-egress命名空间。具体操作,请参见管理全局命名空间

  2. 全局命名空间页面,单击同步自动注入至Kubernetes集群,将该命名空间同步至ASM实例管理的ACK集群。

三、创建出口网关

在ASM中创建一个名为egressgateway-a的出口网关,端口映射配置为HTTP 80、HTTPS 443和HTTPS 444,并开启支持双向TLS认证。具体操作,请参见创建出口网关服务

请确保在生成的YAML文件中,spec字段中包含以下内容。若不存在,请进行添加。

spec:
  podLabels:
    security.istio.io/tlsMode: istio

四、创建应用示例

  1. 在ASM实例中,创建名为mytest的命名空间并开启自动注入。具体操作,请参见管理全局命名空间

  2. 在ACK集群中,在mytest命名空间中部署sleep-a服务,在default命名空间中部署nginx服务。

    1. 使用以下内容,创建test.yaml

      展开查看YAML文件

      apiVersion: v1
      kind: Service
      metadata:
        name: sleep-a
        namespace: mytest
        labels:
          app: sleep-a
          service: sleep-a
      spec:
        ports:
        - port: 80
          name: http
        selector:
          app: sleep-a
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: sleep-a
        namespace: mytest
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: sleep-a
        template:
          metadata:
            labels:
              app: sleep-a
          spec:
            terminationGracePeriodSeconds: 0
            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
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app: nginx
        name: nginx
        namespace: default
      spec:
        progressDeadlineSeconds: 600
        replicas: 1
        revisionHistoryLimit: 10
        selector:
          matchLabels:
            app: nginx
        strategy:
          rollingUpdate:
            maxSurge: 25%
            maxUnavailable: 25%
          type: RollingUpdate
        template:
          metadata:
            creationTimestamp: null
            labels:
              app: nginx
          spec:
            containers:
            - image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/nginx:1.27.0
              imagePullPolicy: Always
              name: nginx
              resources: {}
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
            dnsPolicy: ClusterFirst
            restartPolicy: Always
            schedulerName: default-scheduler
            securityContext: {}
            terminationGracePeriodSeconds: 30
    2. 在ACK集群中,执行以下命令,部署sleep-a和nginx服务。

      kubectl apply -f test.yaml
  3. 执行以下命令,通过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,表明访问失败。

sleep-a服务访问HTTP外部服务

方案一:sidecar到出口网关之间使用HTTP明文

image

此方案在实际环境中并不合理,目前ASMEgressTrafficPolicy并不支持使用HTTP明文访问出口网关。

  • 流量管理主要在客户端sidecar实施,并不需要出口网关。

  • 可观测不依赖出口网关。

  • 安全能力依赖出口网关,但是如果没有mTLS,基于客户端身份的所有授权能力将不可用。出口网关只能无差别地拒绝所有请求。

方案二:sidecar到出口网关之间使用mTLS(推荐方案)

image

通过控制台界面配置

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 出口网关

  3. 单击网关名称,进入网关概览页。单击左侧出口流量策略。参照下图进行配置。

    image

  4. 验证ASMEgressTrafficPolicy配置是否生效。

    1. 执行以下命令,通过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失败。

    2. 执行以下命令,通过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,符合预期。

      说明

      由于http://www.httpbin.org属于海外站点,如果您在实际验证过程中出现响应时间长的情况,可以考虑将ASMEgressTrafficPolicy和测试命令中的hosts更换为其他地址,例如aliyun.com。如果您使用aliyun.com作为实际验证的host,由于aliyun站点默认强制使用HTTPS协议,此处的预期返回应为301重定向。

    3. 网关出口流量策略页面右侧单击清空规则,删除ASMEgressTrafficPolicy配置。再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.org

      kubectl -n istio-egress delete ASMEgressTrafficPolicy  egress-by-egressgateway
      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配置生效。

通过kubectl配置

  1. 使用以下内容,创建egress-by-egressgateway.yaml。

    关于字段的相关说明,请参见ASMEgressTrafficPolicy CRD说明

    apiVersion: istio.alibabacloud.com/v1
    kind: ASMEgressTrafficPolicy
    metadata:
      name: egress-by-egressgateway  # 名称约定为egress-by-{出口网关名称},与出口网关对应。
      namespace: istio-egress         # 命名空间约定:固定到istio-egress命名空间。
    spec:
      byEgressGateway:
        name: egressgateway
      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)
  2. 在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。

    kubectl apply -f egress-by-egressgateway.yaml
  3. 验证ASMEgressTrafficPolicy配置是否生效。

    1. 执行以下命令,通过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失败。

    2. 执行以下命令,通过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,符合预期。

      说明

      由于http://www.httpbin.org属于海外站点,如果您在实际验证过程中出现响应时间长的情况,可以考虑将ASMEgressTrafficPolicy和测试命令中的hosts更换为其他地址,例如aliyun.com。如果您使用aliyun.com作为实际验证的host,由于aliyun站点默认强制使用HTTPS协议,此处的预期返回应为301重定向。

    3. 执行以下命令,删除egress-by-egressgateway后,再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.org

      kubectl -n istio-egress delete ASMEgressTrafficPolicy  egress-by-egressgateway
      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配置生效。

sleep-a服务访问HTTPS外部服务

方案一:sidecar到出口网关之间使用mTLS(推荐方案)

image

通过控制台界面配置

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 出口网关

  3. 单击网关名称,进入网关概览页。单击左侧出口流量策略。参照下图进行配置。

    image

  4. 验证ASMEgressTrafficPolicy配置是否生效。

    1. 验证mytest命名空间下的sleep-a服务。

      1. 执行以下命令,通过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成功。

      2. 执行以下命令,请求httpbin.organything接口,验证出口网关是否将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

      3. 执行以下命令,通过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成功。

    2. 验证default命名空间下的Nginx服务。

      1. 执行以下命令,通过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失败。

      2. 执行以下命令,通过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失败。

      3. 执行以下命令,查看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.XX.XX: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,因此导致连接被拒绝。

    3. 网关出口流量策略页面右侧单击清空规则,再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.orghttps://www.httpbin.org

      kubectl -n istio-egress delete ASMEgressTrafficPolicy  egress-by-egressgateway
      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.orghttps://www.httpbin.org

      输出以上结果,表明ASMEgressTrafficPolicy配置生效。

通过kubectl配置

  1. 使用以下内容,更新egress-by-egressgateway.yaml。

    spec字段下增加了httpsUpgrade字段和直接访问https://www.httpbin.org的相关定义。关于字段的相关说明,请参见ASMEgressTrafficPolicy CRD说明

    apiVersion: istio.alibabacloud.com/v1
    kind: ASMEgressTrafficPolicy
    metadata:
      name: egress-by-egressgateway  # 名称约定为egress-by-{出口网关名称},与出口网关对应。
      namespace: istio-egress          # 命名空间约定:固定到istio-egress命名空间。
    spec:
      byEgressGateway:
        name: egressgateway
      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)
  2. 在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。

    kubectl apply -f egress-by-egressgateway.yaml
  3. 验证ASMEgressTrafficPolicy配置是否生效。

    1. 验证mytest命名空间下的sleep-a服务。

      1. 执行以下命令,通过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成功。

      2. 执行以下命令,请求httpbin.organything接口,验证出口网关是否将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

      3. 执行以下命令,通过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成功。

    2. 验证default命名空间下的Nginx服务。

      1. 执行以下命令,通过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失败。

      2. 执行以下命令,通过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失败。

      3. 执行以下命令,查看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.XX.XX: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,因此导致连接被拒绝。

    3. 执行以下命令,删除egress-by-egressgateway后,再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.orghttps://www.httpbin.org

      kubectl -n istio-egress delete ASMEgressTrafficPolicy  egress-by-egressgateway
      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.orghttps://www.httpbin.org

    输出以上结果,表明ASMEgressTrafficPolicy配置生效。

方案二:sidecar到出口网关之间使用HTTPS

image

通过控制台界面配置

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 出口网关

  3. 单击网关名称,进入网关概览页。单击左侧出口流量策略。参照下图进行配置。

    image

  4. 验证ASMEgressTrafficPolicy配置是否生效。

    1. 验证mytest命名空间下的sleep-a服务。

      1. 执行以下命令,通过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

        输出结果返回502,表明sleep-a服务访问http://www.httpbin.org失败。

      2. 执行以下命令,通过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成功。

    2. 验证default命名空间下的Nginx服务。

      1. 执行以下命令,通过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失败。

      2. 执行以下命令,通过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失败。

      3. 执行以下命令,查看Nginx工作负载对应的Sidecar的access log,了解连接被拒绝的原因。

         kubectl -n default  logs -f deployment/nginx -c istio-proxy   --tail=1 

        预期输出:

        {"authority":"-","bytes_received":"0","bytes_sent":"0","downstream_local_address":"52.86.XX.XX: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,因此导致连接被拒绝。

    3. 网关出口流量策略页面右侧单击清空规则,再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.orghttps://www.httpbin.org

      kubectl -n istio-egress delete ASMEgressTrafficPolicy  egress-by-egressgateway
      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.orghttps://www.httpbin.org

      输出以上结果,表明ASMEgressTrafficPolicy配置生效。

通过kubectl配置

  1. 使用以下内容,更新egress-by-egressgateway.yaml。

    spec字段下增加了httpsUpgrade字段和直接访问https://www.httpbin.org的相关定义。关于字段的相关说明,请参见ASMEgressTrafficPolicy CRD说明

    apiVersion: istio.alibabacloud.com/v1
    kind: ASMEgressTrafficPolicy
    metadata:
      name: egress-by-egressgateway  # 名称约定为egress-by-{出口网关名称},与出口网关对应。
      namespace: istio-egress          # 命名空间约定:固定到istio-egress命名空间。
    spec:
      byEgressGateway:
        name: egressgateway
      egressRules:
      - from:
         - namespace: mytest
           workloadSelector:
              app: sleep-a
        to:
        - name: httpbin-service-https
          hosts:
          - www.httpbin.org
          - httpbin.org
          port:
            name: https
            number: 443
            protocol: HTTPS
          byEgressGateway:
            port: 444   # 准备工作的第三步中,出口网关定义的HTTPS 444端口。
  2. 在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。

    kubectl apply -f egress-by-egressgateway.yaml
  3. 验证ASMEgressTrafficPolicy配置是否生效。

    1. 验证mytest命名空间下的sleep-a服务。

      1. 执行以下命令,通过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

        输出结果返回502,表明sleep-a服务访问http://www.httpbin.org失败。

      2. 执行以下命令,通过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成功。

    2. 验证default命名空间下的Nginx服务。

      1. 执行以下命令,通过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失败。

      2. 执行以下命令,通过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失败。

      3. 执行以下命令,查看Nginx工作负载对应的Sidecar的access log,了解连接被拒绝的原因。

         kubectl -n default  logs -f deployment/nginx -c istio-proxy   --tail=1 

        预期输出:

        {"authority":"-","bytes_received":"0","bytes_sent":"0","downstream_local_address":"52.86.XX.XX: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,因此导致连接被拒绝。

    3. 执行以下命令,删除egress-by-egressgateway后,再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.orghttps://www.httpbin.org

      kubectl -n istio-egress delete ASMEgressTrafficPolicy  egress-by-egressgateway
      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.orghttps://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则不受影响。