將 Cloud Service Mesh 工作負載的流量轉送至 Cloud Run 服務

本頁面說明如何安全地將 GKE 上 Cloud Service Mesh 工作負載的網路流量,路由至 Cloud Run 服務。

請注意,從 GKE 將流量轉送至 Cloud Run 時,Cloud Run 服務不一定要加入 Cloud Service Mesh。不過,Cloud Run 服務必須與 Cloud Service Mesh GKE 叢集位於同一專案。這項功能為公開預先發布版,因此有這項限制。

事前準備

以下各節假設您已具備下列條件:

  1. 已啟用 Cloud Service Mesh 的 GKE 叢集
  2. 已部署 Cloud Run 服務

或者,您也可以執行下列指令,部署範例 Cloud Run 服務。

  1. 為叢集產生 kubeconfig 內容:

    gcloud container clusters get-credentials CLUSTER_NAME --project=PROJECT_ID  --location=CLUSTER_LOCATION
    

    其中:

    • CLUSTER_NAME 是叢集名稱。
    • PROJECT_ID 是專案的專案 ID。
    • CLUSTER_LOCATION 是叢集的區域或可用區。
  2. 部署範例 Cloud Run 服務:

    gcloud run deploy hello-world \
      --image=us-docker.pkg.dev/cloudrun/container/hello \
      --no-allow-unauthenticated \
      --port=8080 \
      --service-account=PROJECT_NUMBER[email protected] \
      --region=us-central1 \
      --project=PROJECT_ID
    

    其中:

    • PROJECT_NUMBER 是專案的專案號碼。
    • PROJECT_ID 是專案的專案 ID。

設定身分與存取權管理

如要叫用 Cloud Run 服務,必須通過 Cloud Run Identity and Access Management (IAM) 檢查。您必須將 Cloud Run 叫用者角色授予 Google 服務帳戶。您也必須設定 GKE Kubernetes 服務帳戶 (KSA),模擬 Google 服務帳戶。

請按照下列步驟,允許 Kubernetes 服務帳戶模擬 Google 服務帳戶。

  1. 將 IAM 政策繫結新增至 IAM 服務帳戶:

    gcloud iam service-accounts add-iam-policy-binding PROJECT_NUMBER[email protected] \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA]"
    

    其中:

    • NAMESPACE 是命名空間名稱。在本指南中,您可以使用 default 命名空間。
    • KSA 是 Kubernetes 服務帳戶的名稱。在本指南中,您可以使用 KSA default
  2. 為服務帳戶加上註解:

    kubectl annotate serviceaccount KSA \
      --namespace NAMESPACE \
      iam.gke.io/gcp-service-account=PROJECT_NUMBER[email protected]
    
  3. 將 Cloud Run 叫用者角色授予 Google 服務帳戶:

    gcloud run services add-iam-policy-binding hello-world \
      --region=us-central1 \
      --member="serviceAccount:PROJECT_NUMBER[email protected]" \
      --role="roles/run.invoker"
    

將 Cloud Run 服務設定為 GCPBackend

在本節中,您會使用 GCPBackend 將 Cloud Run 服務公開給 GKE 工作負載。GCPBackend 包含:

  1. 前端資訊,具體來說,就是 GKE 工作負載用來呼叫這個 GCPBackend 的主機名稱和通訊埠。
  2. 後端資訊 - Cloud Run 服務詳細資料,例如服務名稱、位置和專案編號。

GCPBackend 包含主機名稱和連接埠詳細資料,以及 Cloud Service 詳細資料 (服務名稱、位置和專案編號)。GKE 工作負載應在 HTTP 要求中使用 GCPBackend 主機名稱和連接埠,存取 Cloud Run 服務。

如要在叢集內解析主機名稱的 DNS (預設無法解析),您必須設定 Google Cloud DNS,將所選主機名稱下的所有主機解析為任意 IP 位址。您必須先設定這個 DNS 項目,要求才會成功。 Google Cloud DNS 設定是每個自訂網域的一次性設定。

  1. 建立代管區域:

    gcloud dns managed-zones create prod \
        --description="zone for gcpbackend" \
        --dns-name=gcpbackend \
        --visibility=private \
        --networks=default
    

    在本範例中,DNS 名稱為 gcpbackend,虛擬私有雲網路為 default

  2. 設定記錄,讓網域可解析:

    gcloud beta dns record-sets create *.gcpbackend \
      --ttl=3600 --type=A --zone=prod \
      --rrdatas=10.0.0.1
    
  3. 使用先前網域下的主機名稱建立 GCPBackend:

    cat <<EOF > gcp-backend.yaml
    apiVersion: networking.gke.io/v1
    kind: GCPBackend
    metadata:
      name: cr-gcp-backend
      namespace: NAMESPACE
    spec:
      hostname: hello-world.gcpbackend
      type: CloudRun
      cloudrun:
        service: hello-world
        regions: [us-central1]
    EOF
    kubectl apply -f gcp-backend.yaml
    

    在本例中,GCP_BACKEND_NAMEcr-gcp-backend

  4. 建立測試 Pod,確認 GKE 與 Cloud Run 的連線:

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: testcurl
      namespace: default
    spec:
      containers:
      - name: curl
        image: curlimages/curl
        command: ["sleep", "3000"]
    EOF
    
    kubectl exec testcurl -c curl -- curl http://hello-world.gcpbackend/hello
    

    現在,GKE 工作負載可以將 HTTP 要求傳送至 hello-world.gcpbackend/hello,存取 Cloud Run 服務。

您應為 GCPBackend 使用不同的名稱,以免與現有的 Kubernetes 服務或 Istio 服務項目發生衝突。如果發生衝突,優先順序 (由高至低) 依序為 Kubernetes Service、istio ServiceEntry 和 GCPBackend。

請注意,虛擬服務和 GCPBackend 必須位於相同命名空間,且 Cloud Run 服務必須與 Cloud Service Mesh GKE 叢集位於相同專案。

(選用) 使用 Cloud Run 的主機名稱,而非 Cloud DNS

每個 Cloud Run 服務都會獲派主機名稱 (例如 hello-world.us-central1.run.app),且 DNS 可在全球解析。您可以直接在 GCPBackend 主機名稱中使用這個主機名稱,並略過 Cloud DNS 設定。

cat <<EOF | kubectl apply -f -
apiVersion: networking.gke.io/v1
kind: GCPBackend
metadata:
  name: cr-gcp-backend
  namespace: NAMESPACE
spec:
  hostname: hello-world.us-central1.run.app
  type: CloudRun
  cloudrun:
    service: hello-world
    region: [us-central1]
EOF

現在,您的 GKE 工作負載可以將 HTTP 要求傳送至 hello-world.us-central1.run.app,藉此存取 Cloud Run 服務。

(選用) 設定 Istio 虛擬服務和/或目的地規則

您可以為 GCPBackend 主機名稱設定 Istio 虛擬服務或 Istio 目的地規則,為傳送至 GCPBackend 的要求設定消費者或用戶端政策。

以下範例會對 50% 的要求注入 5 秒的延遲時間,並對傳送至 GCPBackend 的 10% 要求中止 (503 http 狀態)。

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cr-virtual-service
  namespace: NAMESPACE
spec:
  hosts:
  - hello-world.us-central1.run.app
  gateways:
  - mesh
  http:
  - fault:
      delay:
        percentage:
          value: 50  # Delay 50% of requests
        fixedDelay: 5s
      abort:
        percentage:
          value: 10  # Abort 10% of requests
        httpStatus: 503
  - route:
    - destination:
        host: hello-world.us-central1.run.app
EOF

在本例中,VIRTUAL_SERVICE_NAMEcr-virtual-service

疑難排解

本節說明如何排解 Cloud Service Mesh 和 Cloud Run 的常見錯誤。

Cloud Run Sidecar 記錄

Envoy 錯誤會記錄在 Cloud Logging 中。

舉例來說,如果未在網格專案中授予 Cloud Run 服務帳戶 trafficdirector 用戶端角色,系統就會記錄下列錯誤:

StreamAggregatedResources gRPC config stream to trafficdirector.googleapis.com:443 closed: 7, Permission 'trafficdirector.networks.getConfigs' denied on resource '//trafficdirector.googleapis.com/projects/525300120045/networks/mesh:test-mesh/nodes/003fb3e0c8927482de85f052444d5e1cd4b3956e82b00f255fbea1e114e1c0208dbd6a19cc41694d2a271d1ab04b63ce7439492672de4499a92bb979853935b03d0ad0' (or it may not exist).

CSDS

您可以使用 CSDS 擷取 trafficdirector 用戶端狀態:

gcloud alpha container fleet mesh debug proxy-status --membership=<CLUSTER_MEMBERSHIP> --location=<CLUSTER_LOCATION>
External Clients:
....

後續步驟