ASM网关不仅可以作为Ingress网关,还可以作为Egress出口网关,为网格内应用提供统一的出口,帮助您更便捷地使用网格提供的可观测及安全能力,提升运维效率。本文介绍如何为网格内流量配置统一的出口网关。

前提条件

配置流程

配置流程

步骤一:部署示例应用

  1. 部署sleep应用。
    1. 使用以下内容,创建sleep.yaml
      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: 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
      ---
    2. 执行以下命令,部署sleep应用。
      kubectl apply -f sleep.yaml
  2. 执行以下命令,进入sleep Pod,访问外部服务。
    kubectl exec -it ${sleep Pod的名称} -- /bin/sh
    curl aliyun.com -I
    示例输出:
    HTTP/1.1 301 Moved Permanently
    server: envoy
    date: Wed, 30 Nov 2022 06:31:49 GMT
    content-type: text/html
    content-length: 239
    location: https://aliyun.com/
    eagleeye-traceid: 0be3e0ca16697899092851326e****
    timing-allow-origin: *
    x-envoy-upstream-service-time: 28
    返回301,表示网格内应用可以正常访问外部服务。此处默认使用HTTP协议访问,网站会返回重定向响应。
    说明 ASM默认允许访问所有外部服务,采用此方式无法进行安全权限控制,也无法使用网格提供的各种可观测能力。建议您参照下文,开启REGISTRY_ONLY,限制可访问的服务,并使用出口网关作为流量统一出口。

(可选)步骤二:开启REGISTRY_ONLY

ASM的外部服务访问策略默认为ALLOW_ANY,建议您将其修改为REGISTRY_ONLY。Sidecar代理将阻止未在网格中定义HTTP服务或服务条目的主机,保障网格内应用的安全。

说明

展开查看开启REGISTRY_ONLY的操作步骤。

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理
  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择Sidecar管理(数据面) > Sidecar代理配置
  3. Sidecar代理配置页面,单击全局页签,单击外部服务访问策略,配置对外部服务的访问策略OutboundTrafficPolicyREGISTEY_ONLY,然后单击更新设置
  4. 执行以下命令,进入sleep Pod,访问外部服务。
    kubectl exec -it ${sleep Pod的名称} -- /bin/sh
    curl aliyun.com -I
    示例输出:
    HTTP/1.1 502 Bad Gateway
    date: Wed, 30 Nov 2022 06:57:16 GMT
    server: envoy
    transfer-encoding: chunked
    返回502,表示网格内应用无法访问未经注册的外部服务。

步骤三:为外部服务创建服务条目(ServiceEntry)

对集群外的服务创建ServiceEntry,集群内应用才能使用出口网关访问对应的外部服务。

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理
  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择集群与工作负载管理 > 集群外服务(ServiceEntry),然后单击使用YAML创建
  3. 创建页面,选择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
  4. 执行以下命令,进入sleep Pod,访问外部服务。
    kubectl exec -it ${sleep Pod的名称} -- /bin/sh
    curl aliyun.com -I
    返回301,表示网格内应用可以正常访问外部服务。在网格内使用ServiceEntry注册了aliyun.com,所以允许应用访问该外部服务。此时外部流量直接从各个Pod发出,并没有从统一的出口网关发出。

步骤四:使用出口网关作为外部服务的统一出口

下文使用出口网关作为网格访问外部服务的唯一出口,Istio的各种能力也可以应用于出口网关,方便您统一管理。

(可选)创建出口网关

若您已创建出口网关(开启80端口),可跳过此步骤。

展开查看创建出口网关的操作步骤。

  1. 在网格详情页面左侧导航栏,选择ASM网关 > 出口网关
  2. 出口网关页面,单击创建,配置名称部署集群网关类型选择南北向-出口,其他配置项保持默认,然后单击创建创建出口网关

使用出口网关作为外部流量出口

上文已为aliyun.com创建了ServiceEntry,因此可以使用虚拟服务、网关规则等功能来管理访问aliyun.com的流量。

  1. 在网格详情页面左侧导航栏,单击ASM网关 > 网关规则
  2. 网关规则页面,单击创建,进行相关配置,然后单击创建
    请选择目标命名空间,其他配置项可按照下图示例进行配置。创建网关规则

创建虚拟服务

  1. 在网格详情页面左侧导航栏,选择流量管理中心 > 虚拟服务,然后在右侧页面,单击使用YAML创建
  2. 创建页面,选择目标命名空间和任意场景模板,配置以下YAML示例,然后单击创建
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: egressgateway-vs
    spec:
      hosts:
      - aliyun.com
      gateways:
      - egress-gw  # 上一步创建的网关规则名称。
      - mesh
      http:
      - match:
        - gateways:
          - mesh
          port: 80
        route:
        - destination:
            host: istio-egressgateway.istio-system.svc.cluster.local
            port:
              number: 80
          weight: 100
      - match:
        - gateways:
          - istio-egressgateway
          port: 80
        route:
        - destination:
            host: aliyun.com
            port:
              number: 80
          weight: 100

测试访问外部服务

  1. 执行以下命令,进入sleep Pod,访问外部服务。
    kubectl exec -it ${sleep Pod的名称} -- /bin/sh
    curl aliyun.com -I
    返回301,表示网格内应用可以正常访问外部服务。此时网格内应用不是直接从Pod访问服务,而是通过上文创建的出口网关访问服务。
  2. 执行以下命令,在网关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提供的可观测以及安全相关的能力,更加高效地管理出口流量。