為 Cloud Service Mesh 設定傳統版應用程式負載平衡器

總覽

如果您是現有的 Cloud Service Mesh 使用者,且擁有 Istiod 代管控制層,並想將傳統型應用程式負載平衡器設定為 Ingress 閘道,請參閱本文。傳統版應用程式負載平衡器也稱為傳統版外部應用程式負載平衡器。

如果您是 Cloud Service Mesh 新手,請勿使用這份文件。新使用者會自動設定為使用 Cloud Service Mesh 代管控制層。您無法將本文所述設定用於 Cloud Service Mesh 代管控制層

Cloud Load Balancing 提供許多雲端管理的邊緣功能,包括全域任播負載平衡、Google 管理的憑證、Identity and Access Management、Cloud Next Generation Firewall 和 Cloud Intrusion Detection System。Cloud Service Mesh 可在下列網格進入模型中,順暢整合這些邊緣功能。服務網格雲端閘道提供統一方式,可透過 Kubernetes Gateway API 同時設定 Cloud Service Mesh Ingress 閘道和 Cloud Load Balancing

顯示使用 Cloud Service Mesh 的負載平衡器圖表

相較於先前的使用者指南「從邊緣到網格:透過 GKE Ingress 開放服務網格應用程式」,使用服務網格雲端閘道時,現在只要透過一個 Kubernetes Gateway 資源即可部署此模型,簡化雲端和叢集代管負載平衡的部署程序。

試閱限制

這項功能的預覽版有下列限制:

  • 不支援多叢集閘道。
  • 不支援 Autopilot 叢集。
  • 系統僅支援傳統版應用程式負載平衡器。全域外部應用程式負載平衡器 (有時稱為進階負載平衡器) 和內部應用程式負載平衡器不支援這項功能。
  • 傳統應用程式負載平衡器與 Cloud Service Mesh 進入閘道之間的流量會使用 TLS 加密。不過,傳統版應用程式負載平衡器不會驗證 Cloud Service Mesh 進入閘道提供的憑證。這項限制適用於 Google Cloud HTTP(S) 負載平衡器的所有使用者。
  • 如果從叢集中刪除 Cloud Service Mesh GatewayClasses,系統不會自動重新安裝。不過,這不會影響功能的使用性。
  • 路徑比對邏輯不符合 Gateway API 規格,而是按照 HTTPRoute 的順序比對。日後版本會根據 Gateway API 規格進行變更。

需求條件

  • 代管式 Cloud Service Mesh 安裝在執行 1.24 以上版本的 Google Kubernetes Engine (GKE) 叢集上。不支援其他 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 資源,該資源會部署傳統型應用程式負載平衡器和 Cloud Service Mesh Ingress 閘道。

透過代管 Cloud Service Mesh 啟用 Gateway API

  1. 在叢集中啟用 Gateway API。GKE 叢集必須為 1.24 以上版本。

  2. rapidregular 做為發布管道,安裝受管理 Cloud Service Mesh

部署閘道資源

部署服務網格雲端閘道時,Kubernetes Gateway 資源會用於部署 Cloud Load Balancing 和 Cloud Service Mesh 進入閘道,只需一個步驟即可完成。請注意,Kubernetes Gateway 資源與 Istio Gateway 資源不同。

如要進一步瞭解兩者的差異,請參閱「Kubernetes Gateways 和 Istio Gateways」。每個 Kubernetes Gateway 都有一個 GatewayClass,可指出其類型和固有功能。服務網格雲端閘道具有 GatewayClass,可部署 Cloud Load Balancing 和 Cloud 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 傳統版應用程式負載平衡器。

  4. 為服務網格雲端閘道建立專屬命名空間:

    kubectl create namespace istio-ingress
    
  5. 將下列 Gateway 資訊清單儲存至名為 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 命名空間中部署 Gateway:

    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 負載平衡器資源名稱。
  • 系統會在 istio-ingress 命名空間中建立 Cloud Service Mesh Ingress 閘道 Deployment。這會建立 Envoy Proxy 執行個體,接收來自負載平衡器的流量。
  • 負載平衡器會加密所有流量,並將流量轉送至 Cloud Service Mesh Ingress 閘道。

您現在已具備完整基礎架構,可接受網格中的網際網路流量。請注意,這是最簡單的閘道部署方式。在接下來的幾節中,您會新增其他政策和功能,讓應用程式準備好投入正式環境。

應用程式和路由部署

為充分展示功能,您將應用程式部署至 Cloud Service Mesh,並透過閘道接收網際網路流量,以供範例用途。

  1. default 命名空間加上標籤,啟用補充資訊植入功能。

    kubectl label namespace default istio-injection=enabled istio.io/rev- --overwrite
    
  2. 將下列 Gateway 資訊清單儲存至名為 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
            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
            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 建立 Service/whereami-v1Service/whereami-v2Deployment/whereami-v1Deployment/whereami-v2,這是一個簡單的應用程式,會輸出 JSON 來指出自己的身分和位置。您將部署兩個不同版本。

  3. 建立服務和部署作業:

    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,也就是說,它會設定服務網格雲端閘道,以便使用這些路由規則設定基礎 Cloud Service Mesh 輸入閘道。HTTPRoute 的功能與 Istio VirtualService 相同,但會使用 Kubernetes Gateway API 執行這項功能。由於 Gateway API 是 OSS 規格,且有許多基礎實作項目,因此最適合用來定義不同負載平衡器 (例如 Cloud Service Mesh 代理程式和負載平衡器) 的路由。

  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"
    }
    

部署正式版閘道

上一節介紹了服務網格雲端閘道的簡單範例。以下步驟會以簡單的範例為基礎,說明如何設定適用於正式環境的設定,並展示將部分 Ingress 路由功能委派給負載平衡器的優點。

在下列範例中,您將採用上一節的 servicemesh-cloud-gw,並新增下列功能,建立更安全且易於管理的閘道:

  • 部署閘道時使用靜態 IP 位址,即使基礎架構變更,該位址也會保留。
  • 轉換 Gateway,透過自行簽署的憑證接收 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. 在叢集中重新部署 Gateway:

    kubectl apply -f gateway.yaml
    
  5. 取得靜態 IP 的 IP 位址:

    VIP=$(gcloud compute addresses describe whereami-ip --global --format="value(address)")
    
  6. 使用 curl 存取閘道的網域。由於未設定這個網域的 DNS,請使用 --resolve 選項,告知 curl 將網域名稱解析為 Gateway 的 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 流量,並檢查 Cloud Service Mesh Ingress 閘道 Proxy 層的健康狀態。whereami-route 部署在「應用程式和轉送部署」中的設定,會設定 Cloud Service Mesh Ingress 閘道 Proxy,將流量轉送至正確的網格代管服務。

在下列範例中,您將採用上一節的 servicemesh-cloud-gw,並新增下列功能,建立更安全且易於管理的閘道:

  • 部署閘道時使用靜態 IP 位址,即使基礎架構變更,該位址也會保留。
  • 轉換 Gateway,透過自行簽署的憑證接收 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. 在叢集中重新部署 Gateway:

    kubectl apply -f gateway.yaml
    
  5. 取得靜態 IP 的 IP 位址:

    VIP=$(gcloud compute addresses describe whereami-ip --global --format="value(address)")
    
  6. 使用 curl 存取閘道的網域。由於未設定這個網域的 DNS,請使用 --resolve 選項,告知 curl 將網域名稱解析為 Gateway 的 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 流量,並檢查 Cloud Service Mesh Ingress 閘道 Proxy 層的健康狀態。whereami-route 部署在「應用程式和轉送部署」中的設定,會設定 Cloud Service Mesh Ingress 閘道 Proxy,將流量轉送至正確的網格代管服務。

後續步驟