为代管式 Anthos Service Mesh 配置外部 HTTP(S) 负载均衡

概览

Cloud Load Balancing 提供许多云管理的边缘功能,包括全球任播负载均衡、Google 管理的证书、身份和访问权限管理以及云防火墙或 IDS。Anthos Service Mesh 可以在以下网格入站流量模型中无缝集成这些边缘功能。服务网格云网关提供了一种统一的方法,可以通过 Kubernetes Gateway API 同时配置具有 Cloud Load Balancing 的 Anthos Service Mesh 入站流量网关。

展示使用 Anthos Service Mesh 的 Cloud 负载均衡器的图表

与之前的用户指南从边缘到网格:通过 GKE Ingress 公开服务网格应用(搭配使用服务网格云网关)相比,该模型现在可以通过一个 Kubernetes 网关资源进行部署,从而简化了同时部署云和集群托管的负载均衡的过程。

预览限制

此功能的预览版存在以下限制:

  • 不支持多集群网关。
  • 不支持 Autopilot 集群。
  • 仅支持经典版应用负载均衡器。高级负载均衡器和内部 HTTP(S) 负载均衡器不受支持。
  • 外部 HTTP(S) 负载平衡器与 Anthos Service Mesh 入站流量网关之间的流量使用 TLS 进行加密。但是,外部 HTTP(S) 负载平衡器将无法验证 Anthos Service Mesh 入站流量网关提供的证书。此限制适用于 Google Cloud HTTP(S) 负载均衡器的所有用户。
  • 如果从集群中删除 Anthos Service Mesh GatewayClasses,系统不会自动重新安装这些节点。不过,这不会影响该功能的易用性。
  • 路由匹配逻辑不遵循 Gateway API 规范,而是按照 HTTPRoute 的顺序进行匹配。在未来版本中,将会改为遵循 Gateway API 规范。

使用要求

  • 安装在运行 1.24 或更高版本的 Google Kubernetes Engine (GKE) 集群上的代管式 Anthos Service Mesh。不支持其他 GKE Enterprise 集群。
  • 仅限 Kubernetes Gateway API v1beta1 版本。

前提条件

  • 在项目中启用以下 API:

    • compute.googleapis.com
    • container.googleapis.com
    • certificatemanager.googleapis.com
    • serviceusage.googleapis.com
    gcloud services enable \
       compute.googleapis.com \
       container.googleapis.com \
       certificatemanager.googleapis.com \
       serviceusage.googleapis.com
    

为单集群网格部署服务网格云网关

本部分介绍如何部署 Kubernetes Gateway 资源,该资源用于部署全球外部 HTTP(S) 负载均衡器(经典版)和 Anthos Service Mesh 入站流量网关。

使用代管式 Anthos Service Mesh 启用 Gateway API

  1. 在集群中启用 Gateway API。GKE 集群必须为 1.24 版或更高版本。

  2. 安装代管式 Anthos Service Mesh,并使用 rapidregular 作为其发布渠道。

部署 Gateway 资源

部署服务网格云网关时,Kubernetes Gateway 资源用于一步部署 Cloud Load Balancing 和 Anthos Service Mesh 入站流量网关。请注意,Kubernetes Gateway 资源与 Istio Gateway 资源不同。

如需详细了解差异,请参阅 Kubernetes Gateway 和 Istio Gateway。每个 Kubernetes Gateway 都有一个 GatewayClass,用于指示其类型和固有功能。服务网格云网关有一个 GatewayClass,它能够部署 Cloud Load Balancing 和 Anthos Service Mesh 入站流量网关。

  1. 将以下 GatewayClass 清单保存到名为 l7-gateway-class.yaml 的文件中:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: GatewayClass
    metadata:
      name: asm-l7-gxlb
    spec:
      controllerName: mesh.cloud.google.com/gateway
    
  2. 在您的集群中部署 GatewayClass:

    kubectl apply -f l7-gateway-class.yaml
    
  3. 安装后验证 GatewayClass 是否存在:

    kubectl get gatewayclasses.gateway.networking.k8s.io
    

    输出类似于以下内容:

    NAME          CONTROLLER
    asm-l7-gxlb   mesh.cloud.google.com/gateway
    gke-l7-rilb   networking.gke.io/gateway
    gke-l7-gxlb   networking.gke.io/gateway
    

    部署所有资源可能需要几分钟时间。如果您没有看到预期输出,请确认您已正确满足前提条件

    您还会看到以下 GatewayClass:

    gke-l7-gxlb   networking.gke.io/gateway
    

    这用于部署底层 Google Cloud 全局外部 HTTP(S) 负载均衡器。

  4. 为服务网格云网关创建专用命名空间:

    kubectl create namespace istio-ingress
    
  5. 将以下网关清单保存到名为 gateway.yaml 的文件中:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
    
  6. 在集群的 istio-ingress 命名空间中部署网关:

    kubectl apply -f gateway.yaml
    
  7. 验证是否已创建 Kubernetes Gateway API 对象:

    kubectl get gateways.gateway.networking.k8s.io -n istio-ingress
    

    输出类似于以下内容:

    NAME                                CLASS         ADDRESS         READY   AGE
    asm-gw-gke-servicemesh-cloud-gw     gke-l7-gxlb   34.111.114.64   True    9m40s
    asm-gw-istio-servicemesh-cloud-gw   istio                                 9m44s
    servicemesh-cloud-gw                asm-l7-gxlb                           9m44s
    

部署此 Kubernetes Gateway API 对象时,将出现以下情况:

  • 系统会部署并配置外部 HTTP(S) 负载均衡器。完成该操作可能需要几分钟时间,但是完成后,网关将指示 IP 地址,并会使用创建的 Compute Engine 负载均衡器资源的名称进行注释。
  • Anthos Service Mesh 入站流量网关部署在 istio-ingress 命名空间中创建。这将创建 Envoy 代理实例,用于接收来自 Cloud 负载均衡器的流量。
  • Cloud 负载均衡器将加密所有流量并路由到 Anthos Service Mesh 入站流量网关。

现在,您已经拥有接受互联网流量进入网格所需的完整基础架构。请注意,这是最简单的网关部署。在以下部分中,您将添加额外的政策和功能,以使其可直接用于生产环境。

应用和路由部署

如需完全演示这些功能,您需要将应用部署到 Anthos Service Mesh,并通过网关接收互联网流量(用于示例目的)。

  1. default 命名空间添加标签以启用 Sidecar 注入功能。

    kubectl label namespace default istio-injection=enabled istio.io/rev- --overwrite
    
  2. 将以下网关清单保存到名为 whereami.yaml 的文件中:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v1
      template:
        metadata:
          labels:
            app: whereami-v1
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v1"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v1
    spec:
      selector:
        app: whereami-v1
      ports:
      - port: 8080
        targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v2
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v2
      template:
        metadata:
          labels:
            app: whereami-v2
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v2"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v2
    spec:
      selector:
        app: whereami-v2
      ports:
      - port: 8080
        targetPort: 8080
    

    此清单为 whereami(一个输出 JSON 以指示其身份和位置的简单应用)创建 Service/whereami-v1Service/whereami-v2Deployment/whereami-v1Deployment/whereami-v2。您将部署它的两个不同版本。

  3. 创建 Service 和 Deployment:

    kubectl apply -f whereami.yaml
    

    该应用启动并运行后,您将在集群中运行四个 whereami Pod。

  4. 验证四个 Pod 是否正都在运行:

    kubectl get pods
    

    输出类似于以下内容:

    whereami-v1-7c76d89d55-qg6vs       2/2     Running   0          28s
    whereami-v1-7c76d89d55-vx9nm       2/2     Running   0          28s
    whereami-v2-67f6b9c987-p9kqm       2/2     Running   0          27s
    whereami-v2-67f6b9c987-qhj76       2/2     Running   0          27s
    
  5. 将以下 HTTPRoute 清单保存到名为 http-route.yaml 的文件中:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: where-route
    spec:
     parentRefs:
     - kind: Gateway
       name: servicemesh-cloud-gw
       namespace: istio-ingress
     hostnames:
     - "where.example.com"
     rules:
     - matches:
       - headers:
         - name: version
           value: v2
       backendRefs:
       - name: whereami-v2
         port: 8080
     - backendRefs:
       - name: whereami-v1
         port: 8080
    
  6. http-route.yaml 部署到您的集群:

    kubectl apply -f http-route.yaml
    

    此 HTTPRoute 引用 servicemesh-cloud-gw,这意味着它将配置服务网格云网关,以便使用以下路由规则配置底层 Anthos Service Mesh 入站流量网关。HTTPRoute 的执行方式与 Istio VirtualService 相同,但使用 Kubernetes Gateway API 来执行此操作。由于 Gateway API 是具有许多底层实现的 OSS 规范,因此它是最适合跨不同负载均衡器(例如 Anthos Service Mesh 代理和 Cloud 负载均衡器)组合定义路由的 API。

  7. 从网关检索 IP 地址,以便将流量发送到您的应用:

    VIP=$(kubectl get gateways.gateway.networking.k8s.io asm-gw-gke-servicemesh-cloud-gw -o=jsonpath="{.status.addresses[0].value}" -n istio-ingress)
    

    输出为一个 IP 地址。

    echo $VIP
    
    34.111.61.135
    
  8. 将流量发送到网关 IP 地址以验证此设置是否正常工作。发送一个带有 version: v2 标头的请求和另一个不带有该标头的请求,以确定两个应用版本之间的路由是否正确。

    curl ${VIP} -H "host: where.example.com"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v1",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v1-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    
    curl ${VIP} -H "host: where.example.com" -H "version: v2"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v2",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v2-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    

生产环境网关部署

上一部分展示了服务网格云网关的一个非常简单的示例。以下步骤基于一个简单的示例构建来显示一个可直接用于生产环境的设置,该设置用于展示将某些入站流量路由功能委托给 Cloud 负载均衡器的优势。

在以下示例中,您将采用上一部分中的 servicemesh-cloud-gw,并添加以下功能,以创建更安全且更易于管理的网关:

  • 使用静态 IP 地址部署网关,即使底层基础架构发生更改,仍将保留该 IP。
  • 转换网关,以使用自签名证书接收 HTTPS 流量。
  1. 创建静态外部 IP 地址。静态 IP 非常有用,因为底层基础架构将来可能会发生变化,但 IP 地址可以保留。

    gcloud compute addresses create whereami-ip \
        --global \
        --project PROJECT_ID
    
  2. where-example-com 网域创建自签名证书:

    openssl genrsa -out key.pem 2048
    cat <<EOF >ca.conf
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    [dn_requirements]
    0.organizationName        = example
    commonName                = where.example.com
    [sans_list]
    DNS.1                     = where.example.com
    EOF
    
    openssl req -new -key key.pem \
        -out csr.pem \
        -config ca.conf
    
    openssl x509 -req \
        -signkey key.pem \
        -in csr.pem \
        -out cert.pem \
        -extfile ca.conf \
        -extensions extension_requirements \
        -days 365
    
    gcloud compute ssl-certificates create where-example-com \
        --certificate=cert.pem \
        --private-key=key.pem \
        --global \
        --project PROJECT_ID
    

    您可以通过多种方式生成 TLS 证书。可以在命令行中手动生成,使用 Google 管理的证书生成,也可以由您的公司的公钥基础架构 (PKI) 系统内部生成。在此示例中,您手动生成自签名证书。虽然自签名证书通常不用于公共服务,但更容易演示这些概念。

    如需详细了解如何通过 Kubernetes Secret 创建自签名证书,请参阅保护网关

  3. 使用以下清单更新 gateway.yaml

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
      - name: https
        protocol: HTTPS
        port: 443
        allowedRoutes:
          namespaces:
            from: All
        tls:
          mode: Terminate
          options:
            networking.gke.io/pre-shared-certs: where-example-com
      addresses:
      - type: NamedAddress
        value: whereami-ip
    
  4. 在您的集群中重新部署网关:

    kubectl apply -f gateway.yaml
    
  5. 获取静态 IP 的 IP 地址:

    VIP=$(gcloud compute addresses describe whereami-ip --global --format="value(address)")
    
  6. 使用 curl 访问网关的网域。由于未为此网域配置 DNS,因此请使用 --resolve 选项指示 curl 将域名解析为网关的 IP 地址:

    curl https://where.example.com --resolve where.example.com:443:${VIP} --cacert cert.pem -v
    

    完成后,输出类似于以下内容:

    ...
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=where.example.com
    *  start date: Apr 19 15:54:50 2021 GMT
    *  expire date: Apr 19 15:54:50 2022 GMT
    *  common name: where.example.com (matched)
    *  issuer: O=example; CN=where.example.com
    *  SSL certificate verify ok.
    ...
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "where-v1",
      "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
      "pod_name": "where-v1-84b47c7f58-tj5mn",
      "pod_name_emoji": "😍",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-04-19T16:30:08",
      "zone": "us-west1-a"
    }
    

详细输出包括成功 TLS 握手,后面是来自应用的响应,如以下输出所示。这表明 TLS 在网关上正常终止,并且应用安全地响应客户端。

您已成功部署以下架构:

ASM 架构

servicemesh-cloud-gw 及其 asm-l7-gxlb GatewayClass 已经抽象化了一些内部基础架构组件,以简化用户体验。Cloud Load Balancing 将使用内部证书终止 TLS 流量,并且还会检查 Anthos Service Mesh 入站流量网关代理层的运行状况。应用和路由部署中部署的 whereami-route 会配置 Anthos Service Mesh 入站流量网关代理以将流量路由到正确的网格托管的 Service。

后续步骤