文档

使用ASMEgressTrafficPolicy管理出口流量

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

前提条件

功能介绍

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

准备工作

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

  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: curlimages/curl
              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: nginx
              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,表明访问失败。

场景一:仅mytest命名空间下的sleep-a服务可访问http://www.httpbin.org

  1. 使用以下内容,创建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)
  2. 在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。

    kubectl apply -f egress-by-egressgateway-a.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,符合预期。

    3. 执行以下命令,删除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

  1. 使用以下内容,创建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端口。
    
  2. 在ACK集群中,执行以下命令,创建ASMEgressTrafficPolicy资源。

    kubectl apply -f egress-by-egressgateway-a.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.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,因此导致连接被拒绝。

    3. 执行以下命令,删除egress-by-egressgateway-a后,再次通过mytest命名空间下的sleep-a服务访问http://www.httpbin.orghttps://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.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则不受影响。

  • 本页导读 (1)
文档反馈