使用無 Proxy gRPC 設定服務安全性

本指南說明如何為無 Proxy gRPC 服務網格設定安全防護服務。

需求條件

為 gRPC 無 Proxy 服務網格設定服務安全防護前,請確認您符合下列需求。

設定身分與存取權管理

您必須具備使用 Google Kubernetes Engine 的必要權限。 您至少必須具備下列角色:

  • roles/container.clusterAdmin GKE 角色
  • roles/compute.instanceAdmin Compute Engine 角色
  • roles/iam.serviceAccountUser 角色

如要建立設定所需的資源,您必須具備 compute.NetworkAdmin 角色。這個角色具備所有必要權限,可建立、更新、刪除、列出及使用 (也就是在其他資源中參照) 必要資源。如果您是專案的擁有者兼編輯者,系統會自動指派這個角色。

請注意,在後端服務資源中參照這些資源時,系統不會強制執行 networksecurity.googleapis.com.clientTlsPolicies.usenetworksecurity.googleapis.com.serverTlsPolicies.use

如果日後強制執行這項檢查,且您使用 compute.NetworkAdmin角色,則不會遇到任何問題。

如果您使用自訂角色,且日後強制執行這項檢查,請務必加入相應的 .use 權限。否則,您可能會發現自訂角色沒有必要的權限,無法從後端服務參照 clientTlsPolicyserverTlsPolicy

準備設定

無 Proxy 服務網格 (PSM) 安全性會為服務網格新增安全性,並根據無 Proxy gRPC 服務文件設定負載平衡。在無代理程式的服務網格中,gRPC 用戶端會使用 URI 中的 xds: 配置存取服務,啟用 PSM 負載平衡和端點探索功能。

將 gRPC 用戶端和伺服器更新至正確版本

使用語言支援的最低 gRPC 版本,建構或重建應用程式。

更新啟動程序檔案

gRPC 應用程式會使用單一啟動程序檔案,該檔案必須包含 gRPC 用戶端和伺服器端程式碼所需的所有欄位。啟動程序產生器會自動產生啟動程序檔案,其中包含 PSM 安全性所需的旗標和值。詳情請參閱「啟動檔案」一節,其中包含啟動檔案範例。

設定總覽

這個設定程序是使用 GKE 和無 Proxy gRPC 服務設定 Cloud Service Mesh 的延伸程序。如果設定程序中現有的步驟未經修改,系統會在適用的地方參照這些步驟。

Cloud Service Mesh 設定的主要強化功能如下:

  1. 設定 CA 服務,在其中建立私人 CA 集區和必要的憑證授權單位。
  2. 建立 GKE 叢集,並使用 GKE 適用的 Workload Identity Federation for GKE 和網格憑證功能,以及 CA 服務整合。
  3. 在叢集上設定網格憑證核發。
  4. 建立用戶端和伺服器服務帳戶。
  5. 設定範例伺服器,該伺服器會使用 xDS API 和 xDS 伺服器憑證,從 Cloud Service Mesh 取得安全性設定。
  6. 設定使用 xDS 憑證的範例用戶端
  7. 更新 Cloud Service Mesh 設定,加入安全性設定。

如要查看使用 xDS 憑證的程式碼範例,請前往下列位置:

更新 Google Cloud CLI

如要更新 Google Cloud CLI,請執行下列指令:

gcloud components update

設定環境變數

在本指南中,您會使用 Cloud Shell 指令,而指令中重複的資訊會以各種環境變數表示。執行指令前,請在殼層環境中,將特定值設為下列環境變數。每行註解都代表相關聯的環境變數意義。

# Your project ID
PROJECT_ID=PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
ZONE=ZONE
gcloud config set compute/zone $ZONE

# GKE cluster URL derived from the above
GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${ZONE}/clusters/${CLUSTER_NAME}"

# Workload pool to be used with the GKE cluster
WORKLOAD_POOL="${PROJECT_ID}.svc.id.goog"

# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE='default'
DEMO_BACKEND_SERVICE_NAME='grpc-gke-helloworld-service'

# Compute other values
# Project number for your project
PROJNUM=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")

# VERSION is the GKE cluster version. Install and use the most recent version
# from the rapid release channel and substitute its version for
# CLUSTER_VERSION, for example:
# VERSION=latest available version
# Note that the minimum required cluster version is 1.21.4-gke.1801.
VERSION="CLUSTER_VERSION"
SA_GKE=service-${PROJNUM}@container-engine-robot.iam.gserviceaccount.com

啟用必要 API 的存取權

本節說明如何啟用必要 API 的存取權。

  1. 執行下列指令,啟用 Cloud Service Mesh 和無 Proxy gRPC 服務網格安全機制所需的其他 API。

    gcloud services enable \
        container.googleapis.com \
        cloudresourcemanager.googleapis.com \
        compute.googleapis.com \
        trafficdirector.googleapis.com \
        networkservices.googleapis.com \
        networksecurity.googleapis.com \
        privateca.googleapis.com \
        gkehub.googleapis.com
    
  2. 執行下列指令,允許預設服務帳戶存取 Cloud Service Mesh 安全性 API。

    GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
        --filter='displayName:Compute Engine default service account')
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member serviceAccount:${GSA_EMAIL} \
       --role roles/trafficdirector.client
    

建立或更新 GKE 叢集

Cloud Service Mesh 服務安全防護取決於憑證授權單位服務與 GKE 的整合。除了設定需求條件外,GKE 叢集也必須符合下列條件:

  • 使用最低叢集版本 1.21.4-gke.1801。如需後續版本的功能,可以透過快速發布管道取得該版本。
  • GKE 叢集必須啟用並設定網格憑證,如「建立憑證授權單位來核發憑證」一文所述。
  1. 建立使用 Workload Identity Federation for GKE 的新叢集。如要更新現有叢集,請跳至下一個步驟。您為 --tags 提供的值必須與使用 Cloud Load Balancing 元件設定 Cloud Service Mesh一節中,傳遞至 firewall-rules create 指令 --target-tags 標記的名稱相符。

    # Create a GKE cluster with GKE managed mesh certificates.
    gcloud container clusters create CLUSTER_NAME \
      --release-channel=rapid \
      --scopes=cloud-platform \
      --image-type=cos_containerd \
      --machine-type=e2-standard-2 \
      --zone=ZONE \
      --workload-pool=PROJECT_ID.svc.id.goog \
      --enable-mesh-certificates \
      --cluster-version=CLUSTER_VERSION \
      --enable-ip-alias \
      --tags=allow-health-checks \
      --workload-metadata=GKE_METADATA
    

    叢集建立作業可能需要幾分鐘才能完成。

  2. 如果您使用現有叢集,請開啟 GKE 適用的工作負載身分聯盟和 GKE 網格憑證。確認叢集是使用 --enable-ip-alias 旗標建立,這個旗標無法與 update 指令搭配使用。

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. 執行下列指令,將新叢集切換為 kubectl 指令的預設叢集:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --zone ZONE
    

向機群註冊叢集

在「建立 GKE 叢集」中建立或更新叢集後,請將該叢集註冊至機群。註冊叢集後,您就能更輕鬆地跨多個專案設定叢集。

請注意,每個步驟最多可能需要十分鐘才能完成。

  1. 將叢集註冊至機群:

    gcloud container fleet memberships register CLUSTER_NAME \
      --gke-cluster=ZONE/CLUSTER_NAME \
      --enable-workload-identity --install-connect-agent \
      --manifest-output-file=MANIFEST-FILE_NAME
    

    請依下列方式替換變數:

    • CLUSTER_NAME:叢集名稱。
    • ZONE:叢集所在的區域。
    • MANIFEST-FILE_NAME:這些指令產生註冊資訊清單的路徑。

    註冊程序完成後,您會看到類似以下的訊息:

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. 將產生的資訊清單檔案套用至叢集:

    kubectl apply -f MANIFEST-FILE_NAME
    

    申請程序成功後,您會看到類似以下的訊息:

    namespace/gke-connect created
    serviceaccount/connect-agent-sa created
    podsecuritypolicy.policy/gkeconnect-psp created
    role.rbac.authorization.k8s.io/gkeconnect-psp:role created
    rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created
    role.rbac.authorization.k8s.io/agent-updater created
    rolebinding.rbac.authorization.k8s.io/agent-updater created
    role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created
    rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    role.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    secret/http-proxy created
    deployment.apps/gke-connect-agent-20210416-01-00 created
    service/gke-connect-monitoring created
    secret/creds-gcp create
    
  3. 從叢集取得成員資格資源:

    kubectl get memberships membership -o yaml
    

    輸出內容應包含車隊指派的 Workload Identity Pool,其中 PROJECT_ID 是您的專案 ID:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    這表示叢集已成功註冊。

建立憑證授權單位來核發憑證

如要將憑證核發給 Pod,請建立 CA 服務集區和下列憑證授權單位 (CA):

  • 根 CA。這是所有核發網格憑證的信任根。如有現有的根層級 CA,可直接使用。在 enterprise 層級中建立根 CA,這個層級適用於長期、低用量的憑證核發作業。
  • 從屬 CA。這個 CA 會核發工作負載憑證。在叢集部署的區域中建立從屬 CA。在 devops 層級中建立從屬 CA,這適用於短期大量核發憑證。

建立從屬 CA 是選用步驟,但我們強烈建議您建立從屬 CA,而非使用根 CA 核發 GKE Mesh 憑證。如果您決定使用根 CA 核發網格憑證,請確保預設的以設定為準的核發模式仍可使用。

下層 CA 可以與叢集位於不同區域,但強烈建議您在與叢集相同的區域中建立下層 CA,以提升效能。不過,您可以在不同區域建立根 CA 和從屬 CA,不會影響效能或可用性。

CA 服務支援下列區域:

地區名稱 地區說明
asia-east1 台灣
asia-east2 香港
asia-northeast1 東京
asia-northeast2 大阪
asia-northeast3 首爾
asia-south1 孟買
asia-south2 德里
asia-southeast1 新加坡
asia-southeast2 雅加達
australia-southeast1 雪梨
australia-southeast2 墨爾本
europe-central2 華沙
europe-north1 芬蘭
europe-southwest1 馬德里
europe-west1 比利時
europe-west2 倫敦
europe-west3 法蘭克福
europe-west4 荷蘭
europe-west6 蘇黎世
europe-west8 米蘭
europe-west9 巴黎
europe-west10 柏林
europe-west12 杜林
me-central1 杜哈
me-central2 達曼
me-west1 特拉維夫市
northamerica-northeast1 蒙特婁
northamerica-northeast2 多倫多
southamerica-east1 聖保羅
southamerica-west1 聖地亞哥
us-central1 愛荷華州
us-east1 南卡羅來納州
us-east4 北維吉尼亞州
us-east5 哥倫布
us-south1 達拉斯
us-west1 奧勒岡州
us-west2 洛杉磯
us-west3 鹽湖城
us-west4 拉斯維加斯

您也可以執行下列指令,查看支援的地點清單:

gcloud privateca locations list
  1. 將 IAM roles/privateca.caManager 授予建立 CA 集區和 CA 的個人。請注意,MEMBER 的正確格式為 user:userid@example.com。如果該使用者是目前的使用者,您可以使用 $(gcloud auth list --filter=status:ACTIVE --format="value(account)") 殼層指令取得目前的使用者 ID。

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.caManager
    
  2. 將 CA 服務的 role/privateca.admin 角色授予需要修改 IAM 政策的個人,其中 MEMBER 是需要這項存取權的個人,具體來說,就是執行下列步驟以授予 privateca.auditorprivateca.certificateManager 角色的任何個人:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. 建立根 CA 服務集區。

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. 建立根 CA。

    gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \
      --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \
      --key-algorithm="ec-p256-sha256" \
      --max-chain-length=1 \
      --location ROOT_CA_POOL_LOCATION
    

    在本示範設定中,請為變數使用下列值:

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. 建立從屬集區和從屬 CA。確認系統仍允許預設的以設定為準的核發模式

    gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --tier devops
    
    gcloud privateca subordinates create SUBORDINATE_CA_NAME \
      --pool SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --issuer-pool ROOT_CA_POOL_NAME \
      --issuer-location ROOT_CA_POOL_LOCATION \
      --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \
      --key-algorithm "ec-p256-sha256" \
      --use-preset-profile subordinate_mtls_pathlen_0
    

    在本示範設定中,請為變數使用下列值:

    • SUBORDINATE_CA_POOL_NAME="td-ca-pool"
    • SUBORDINATE_CA_POOL_LOCATION=us-east1
    • SUBORDINATE_CA_NAME="td-ca"
    • SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_POOL_LOCATION=us-east1
  6. 授予根 CA 集區的 IAM privateca.auditor 角色,允許 GKE 服務帳戶存取:

    gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \
     --location ROOT_CA_POOL_LOCATION \
     --role roles/privateca.auditor \
     --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  7. 授予從屬 CA 集區的 IAM privateca.certificateManager 角色,允許 GKE 服務帳戶存取:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --role roles/privateca.certificateManager \
      --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  8. 儲存下列 WorkloadCertificateConfig YAML 設定,告知叢集如何核發網格憑證:

    apiVersion: security.cloud.google.com/v1
    kind: WorkloadCertificateConfig
    metadata:
      name: default
    spec:
      # Required. The CA service that issues your certificates.
      certificateAuthorityConfig:
        certificateAuthorityServiceConfig:
          endpointURI: ISSUING_CA_POOL_URI
    
      # Required. The key algorithm to use. Choice of RSA or ECDSA.
      #
      # To maximize compatibility with various TLS stacks, your workloads
      # should use keys of the same family as your root and subordinate CAs.
      #
      # To use RSA, specify configuration such as:
      #   keyAlgorithm:
      #     rsa:
      #       modulusSize: 4096
      #
      # Currently, the only supported ECDSA curves are "P256" and "P384", and the only
      # supported RSA modulus sizes are 2048, 3072 and 4096.
      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
      # Optional. Validity duration of issued certificates, in seconds.
      #
      # Defaults to 86400 (1 day) if not specified.
      validityDurationSeconds: 86400
    
      # Optional. Try to start rotating the certificate once this
      # percentage of validityDurationSeconds is remaining.
      #
      # Defaults to 50 if not specified.
      rotationWindowPercentage: 50
    
    

    更改下列內容:

    • 叢集執行的專案 ID:
      PROJECT_ID
    • 核發網格憑證的 CA 的完整 URI (ISSUING_CA_POOL_URI)。這可以是從屬 CA (建議) 或根 CA。格式如下:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. 儲存下列 TrustConfig YAML 設定,告知叢集如何信任核發的憑證:

    apiVersion: security.cloud.google.com/v1
    kind: TrustConfig
    metadata:
      name: default
    spec:
      # You must include a trustStores entry for the trust domain that
      # your cluster is enrolled in.
      trustStores:
      - trustDomain: PROJECT_ID.svc.id.goog
        # Trust identities in this trustDomain if they appear in a certificate
        # that chains up to this root CA.
        trustAnchors:
        - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
    

    更改下列內容:

    • 叢集執行的專案 ID:
      PROJECT_ID
    • 根 CA 集區的完整 URI (ROOT_CA_POOL_URI)。 格式如下:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. 將設定套用至叢集:

    kubectl apply -f WorkloadCertificateConfig.yaml
    kubectl apply -f TrustConfig.yaml
    

使用 NEG 建立無 Proxy gRPC 服務

如要確保 PSM 安全,您需要無 Proxy gRPC 伺服器,能夠使用 xDS 從 Cloud Service Mesh 取得安全設定。這個步驟與 PSM 負載平衡設定指南中的「使用 NEG 設定 GKE 服務」類似,但您使用的是 grpc-java 存放區中 xDS 範例的 xDS 啟用 helloworld 伺服器,而不是 java-example-hostname 映像檔。

您會在以 openjdk:8-jdk 映像檔建構的容器中,建構及執行這個伺服器。您也可以使用具名 NEG 功能,指定 NEG 的名稱。這樣可簡化後續步驟,因為部署作業會知道 NEG 的名稱,不必再進行查詢。

以下是 gRPC 伺服器 Kubernetes 規格的完整範例。請注意下列事項:

  • 規格會建立 gRPC 伺服器 Pod 使用的 Kubernetes 服務帳戶 example-grpc-server
  • 規格會使用服務 cloud.google.com/neg 註解中的 name 欄位,指定 NEG 名稱 example-grpc-server
  • 變數 ${PROJNUM} 代表專案的專案編號。
  • 規格會使用 initContainers 區段執行啟動產生器,以填入無 Proxy gRPC 程式庫所需的啟動檔案。這個啟動程序檔案位於 gRPC 伺服器容器 (名為 example-grpc-server) 的 /tmp/grpc-xds/td-grpc-bootstrap.json 中。

在 Pod 規格中新增下列註解:

 annotations:
   security.cloud.google.com/use-workload-certificates: ""

如要查看正確的放置位置,請參閱下方的完整規格。

建立時,每個 Pod 都會在 /var/run/secrets/workload-spiffe-credentials 取得磁碟區。 這個卷冊包含下列內容:

  • private_key.pem 是自動產生的私密金鑰。
  • certificates.pem 是 PEM 格式的憑證組合,可做為用戶端憑證鏈提供給其他 Pod,或做為伺服器憑證鏈使用。
  • ca_certificates.pem 是 PEM 格式的憑證組合,可用於驗證其他 Pod 提供的用戶端憑證鏈,或連線至其他 Pod 時收到的伺服器憑證鏈,做為信任錨點。

請注意,ca_certificates.pem 包含工作負載的本機信任網域憑證,也就是叢集的工作負載集區。

certificates.pem 中的葉子憑證包含下列純文字 SPIFFE 身分主張:

spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT

在這個判斷中:

  • WORKLOAD_POOL 是叢集工作負載集區的名稱。
  • NAMESPACE 是 Kubernetes 服務帳戶的命名空間。
  • KUBERNETES_SERVICE_ACCOUNT 是 Kubernetes 服務帳戶的名稱。

下列語言的指令會建立本範例中使用的規格。

Java

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立規格:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: openjdk:8-jdk
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 800m
               memory: 512Mi
             requests:
               cpu: 100m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

C++

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立規格:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: phusion/baseimage:18.04-1.0.0
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

Python

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立規格:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: phusion/baseimage:18.04-1.0.0
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

Go

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立規格:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: golang:1.16-alpine
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --config-mesh-experimental
           - "grpc-mesh"
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

    請按照下列步驟完成程序。

  1. 套用規格:

    kubectl apply -f example-grpc-server.yaml
    
  2. 將必要角色指派給服務帳戶:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \
      ${PROJNUM}-compute@developer.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \
      --role roles/trafficdirector.client
    
  3. 執行下列指令,確認服務和 Pod 已正確建立:

    kubectl get deploy/example-grpc-server
    kubectl get svc/example-grpc-server
    
  4. 確認 NEG 名稱正確無誤:

    gcloud compute network-endpoint-groups list \
        --filter "name=example-grpc-server" --format "value(name)"
    

    指令應會傳回 NEG 名稱 example-grpc-server

使用 Google Cloud 負載平衡元件設定 Cloud Service Mesh

本節中的步驟與「使用負載平衡元件設定 Cloud Service Mesh」中的步驟類似,但有些變更,詳情請參閱下列各節。

建立健康狀態檢查、防火牆規則和後端服務

如果 gRPC 伺服器設定為使用 mTLS,gRPC 健康狀態檢查就無法運作,因為健康狀態檢查用戶端無法向伺服器出示有效用戶端憑證。您可以透過下列兩種方式解決這個問題:

第一種方法是讓伺服器建立額外的服務通訊埠,並將其指定為健康狀態檢查通訊埠。這會附加至特殊的健康狀態檢查服務,以純文字或 TLS 傳輸至該通訊埠。

xDS helloworld 範例伺服器會使用 PORT_NUMBER + 1 做為純文字健康狀態檢查通訊埠。這個範例使用 50052 做為健康狀態檢查通訊埠,因為 50051 是 gRPC 應用程式伺服器通訊埠。

第二種方法是設定健康狀態檢查,只檢查與應用程式服務通訊埠的 TCP 連線。這項檢查只會確認連線狀態,而且在 TLS 交握失敗時,也會產生不必要的伺服器流量。因此,我們建議您採用第一種做法。

  1. 建立健康狀態檢查。請注意,您必須建立並啟動伺服器,健康狀態檢查才會開始。

    • 如果您要建立健康狀態檢查專用的服務通訊埠 (建議採用這種做法),請使用下列指令:

      gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
       --enable-logging --port 50052
      
    • 如果您要建立 TCP 健康狀態檢查 (不建議),請使用下列指令:

      gcloud compute health-checks create tcp grpc-gke-helloworld-hc \
      --use-serving-port
      
  2. 建立防火牆。確認 --target-tags 的值與「建立或更新 GKE 叢集」一節中為 --tags 提供的值相符。

    gcloud compute firewall-rules create grpc-gke-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051-50052
    
  3. 建立後端服務:

    gcloud compute backend-services create grpc-gke-helloworld-service \
       --global \
       --load-balancing-scheme=INTERNAL_SELF_MANAGED \
       --protocol=GRPC \
       --health-checks grpc-gke-helloworld-hc
    
  4. 將 NEG 附加至後端服務:

    gcloud compute backend-services add-backend grpc-gke-helloworld-service \
       --global \
       --network-endpoint-group example-grpc-server \
       --network-endpoint-group-zone ${ZONE} \
       --balancing-mode RATE \
       --max-rate-per-endpoint 5
    

建立 MeshGRPCRoute 資源

這與您在「設定無 Proxy gRPC 服務」中設定 MeshGRPCRoute 資源的方式類似。

  1. 建立 Mesh 規格,並儲存至名為 mesh.yaml 的檔案。

    name: grpc-mesh
    
  2. 從規格匯入 Mesh 資源。

    gcloud network-services meshes import grpc-mesh \
      --source=mesh.yaml \
      --location=global
    
  3. 建立 GRPCRoute 規格,並儲存至名為 grpc_route.yaml 的檔案。

    name: helloworld-grpc-route
    hostnames:
    - helloworld-gke:8000
    meshes:
    - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
    
  4. grpc_route.yaml 規格匯入 GRPCRoute 資源。

    gcloud network-services grpc-routes import helloworld-grpc-route \
      --source=grpc_route.yaml \
      --location=global
    

設定 Cloud Service Mesh,啟用無 Proxy gRPC 安全性

這個範例說明如何在用戶端和伺服器端設定 mTLS。

政策相關資訊格式

請注意,參照伺服器 TLS 和用戶端 TLS 政策時,必須使用下列格式:

projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies]/[server-tls-policy|client-mtls-policy]

例如:

projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy

在伺服器端設定 mTLS

首先,請建立伺服器 TLS 政策。這項政策會要求 gRPC 伺服器端使用名稱為 google_cloud_private_spiffecertificateProvicerInstance 外掛程式設定,做為身分識別憑證 (屬於 serverCertificate 的一部分)。「mtlsPolicy」部分表示 mTLS 安全性,並使用與 clientValidationCa 外掛程式設定相同的 google_cloud_private_spiffe,也就是根 (驗證) 憑證規格。

接著,請建立端點政策。這表示使用通訊埠 50051 的後端 (例如 gRPC 伺服器) 會收到名為 server-mtls-policy 的附加伺服器 TLS 政策,無論是否使用任何中繼資料標籤都適用。您可以使用 MATCH_ALL 或支援的值指定中繼資料標籤。支援的中繼資料標籤位於 NetworkServicesEndpointPolicy 文件endpointMatcher.metadataLabelMatcher.metadataLabelMatchCriteria 欄位。您可以使用已定義的政策,透過包含端點政策資源值的暫時性檔案 ep-mtls-psms.yaml 建立端點政策。

  1. 在目前目錄中建立臨時檔案 server-mtls-policy.yaml,並填入伺服器 TLS 政策資源的值:

    name: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. 匯入暫時檔案 server-mtls-policy.yaml,建立名為 server-mtls-policy 的伺服器 TLS 政策資源:

    gcloud network-security server-tls-policies import server-mtls-policy \
      --source=server-mtls-policy.yaml --location=global
    
  3. 建立臨時檔案 ep-mtls-psms.yaml,藉此建立端點政策:

    name: "ep-mtls-psms"
    type: "GRPC_SERVER"
    serverTlsPolicy: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy"
    trafficPortSelector:
      ports:
      - "50051"
    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: "MATCH_ALL"
        metadataLabels:
        - labelName: app
          labelValue: helloworld
    
  4. 匯入 ep-mtls-psms.yaml 檔案,建立端點政策資源:

    gcloud beta network-services endpoint-policies import ep-mtls-psms \
      --source=ep-mtls-psms.yaml --location=global
    

在用戶端設定 mTLS

用戶端安全政策會附加至後端服務。當用戶端透過後端服務存取後端 (gRPC 伺服器) 時,系統會將附加的用戶端安全性政策傳送給用戶端。

  1. 在目前目錄中,於名為 client-mtls-policy.yaml 的暫存檔案中建立用戶端 TLS 政策資源內容:

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. 匯入暫時檔案 client-mtls-policy.yaml,建立名為 client-mtls-policy 的用戶端 TLS 政策資源:

    gcloud network-security client-tls-policies import client-mtls-policy \
      --source=client-mtls-policy.yaml --location=global
    
  3. 在暫存檔案中建立程式碼片段,參照這項政策,並在 SecuritySettings 訊息中新增 subjectAltNames 的詳細資料,如下列範例所示。將 ${PROJECT_ID} 替換為專案 ID 值,也就是先前所述 ${PROJECT_ID} 環境變數的值。請注意,subjectAltNames 中的 example-grpc-server 是 Kubernetes 服務帳戶名稱,用於部署規格中的 gRPC 伺服器 Pod。

    if [ -z "$PROJECT_ID" ] ; then echo Please make sure PROJECT_ID is set. ; fi
    cat << EOF > client-security-settings.yaml
    securitySettings:
      clientTlsPolicy: projects/${PROJECT_ID}/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://${PROJECT_ID}.svc.id.goog/ns/default/sa/example-grpc-server"
    EOF
    
  4. securitySettings 訊息新增至您已建立的後端服務。這些步驟會匯出目前的後端服務內容、新增用戶端 securitySetting 訊息,然後重新匯入新內容,以更新後端服務。

    gcloud compute backend-services export grpc-gke-helloworld-service --global \
      --destination=/tmp/grpc-gke-helloworld-service.yaml
    
    cat /tmp/grpc-gke-helloworld-service.yaml client-security-settings.yaml \
      >/tmp/grpc-gke-helloworld-service1.yaml
    
    gcloud compute backend-services import grpc-gke-helloworld-service --global \
      --source=/tmp/grpc-gke-helloworld-service1.yaml -q
    

驗證設定

Cloud Service Mesh 設定現已完成,包括伺服器端和用戶端安全防護。接著,請準備並執行伺服器和用戶端工作負載。 這樣就完成範例了。

建立無 Proxy gRPC 用戶端

這個步驟與上一個步驟「建立無 Proxy gRPC 服務」類似。 您會使用 grpc-java 存放區中 xDS 範例目錄的 xDS 啟用 helloworld 用戶端。您可以在從 openjdk:8-jdk 映像檔建構的容器中建構及執行用戶端。gRPC 用戶端 Kubernetes 規格會執行下列動作。

  • 這會建立 Kubernetes 服務帳戶 example-grpc-client,供 gRPC 用戶端 Pod 使用。
  • ${PROJNUM} 代表專案的專案編號,必須替換為實際編號。

在 Pod 規格中新增下列註解:

  annotations:
    security.cloud.google.com/use-workload-certificates: ""

建立時,每個 Pod 都會在 /var/run/secrets/workload-spiffe-credentials 取得磁碟區。 這個卷冊包含下列內容:

  • private_key.pem 是自動產生的私密金鑰。
  • certificates.pem 是 PEM 格式的憑證組合,可做為用戶端憑證鏈提供給其他 Pod,或做為伺服器憑證鏈使用。
  • ca_certificates.pem 是 PEM 格式的憑證組合,可用於驗證其他 Pod 提供的用戶端憑證鏈,或連線至其他 Pod 時收到的伺服器憑證鏈,做為信任錨點。

請注意,ca_certificates.pem 包含工作負載本機信任網域的根憑證,也就是叢集的工作負載集區。

certificates.pem 中的葉子憑證包含下列純文字 SPIFFE 身分主張:

spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT

在這個判斷中:

  • WORKLOAD_POOL 是叢集工作負載集區的名稱。
  • NAMESPACE 是 Kubernetes 服務帳戶的名稱。
  • KUBERNETES_SERVICE_ACCOUNT 是 Kubernetes 服務帳戶的命名空間。

下列語言的指令會建立本範例中使用的規格。

Java

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立下列規格:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: openjdk:8-jdk
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 800m
                memory: 512Mi
              requests:
                cpu: 100m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

C++

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立下列規格:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: phusion/baseimage:18.04-1.0.0
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Python

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立下列規格:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: phusion/baseimage:18.04-1.0.0
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Go

  1. 執行下列指令,確保專案編號設定正確:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. 建立下列規格:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: golang:1.16-alpine
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --config-mesh-experimental
            - "grpc-mesh"
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

請按照下列步驟完成程序。

  1. 套用規格:

    kubectl apply -f example-grpc-client.yaml
    
  2. 將必要角色指派給服務帳戶:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \
      ${PROJNUM}-compute@developer.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \
      --role roles/trafficdirector.client
    
  3. 確認用戶端 Pod 正在執行:

    kubectl get pods
    

    指令會傳回類似下列內容的文字:

    NAMESPACE   NAME                                    READY   STATUS    RESTARTS   AGE
    default     example-grpc-client-7c969bb997-9fzjv    1/1     Running   0          104s
    [..skip..]
    

執行伺服器

在先前建立的伺服器 Pod 中,建構並執行啟用 xDS 的 helloworld 伺服器。

Java

  1. 取得為 example-grpc-server 服務建立的 Pod 名稱:

    kubectl get pods | grep example-grpc-server
    

    您會看到類似下列的意見回饋:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. 開啟伺服器 Pod 的殼層:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. 在殼層中,確認 /tmp/grpc-xds/td-grpc-bootstrap.json 的啟動檔案符合「啟動檔案」一節所述的結構定義。

  4. 下載 gRPC Java 1.42.1 版,並建構 xds-hello-world 伺服器應用程式。

    curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz
    
    cd grpc-java-1.42.1/examples/example-xds
    
    ../gradlew --no-daemon installDist
    
  5. 使用 --xds-creds 標記執行伺服器,指出啟用 xDS 的安全性,並使用 50051 做為接聽通訊埠,以及 xds-server 做為伺服器識別名稱:

    ./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
    
  6. 伺服器從 Cloud Service Mesh 取得必要設定後,您會看到下列輸出內容:

    Listening on port 50051
    plain text health service listening on port 50052
    

C++

  1. 取得為 example-grpc-server 服務建立的 Pod 名稱:

    kubectl get pods | grep example-grpc-server
    

    您會看到類似下列的意見回饋:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. 開啟伺服器 Pod 的殼層:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. 在殼層中,確認 /tmp/grpc-xds/td-grpc-bootstrap.json 的啟動檔案符合「啟動檔案」一節所述的結構定義。

  4. 下載 gRPC C++,並建構 xds-hello-world 伺服器應用程式。

    apt-get update -y && \
            apt-get install -y \
                build-essential \
                clang \
                python3 \
                python3-dev
    
    curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
    
    cd grpc-master
    
    tools/bazel build examples/cpp/helloworld:xds_greeter_server
    
  5. 使用 50051 做為接聽埠,並以 xds_greeter_server 做為伺服器識別名稱,執行伺服器:

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --port=50051 --maintenance_port=50052 --secure
    

    如要在沒有憑證的情況下執行伺服器,可以指定下列項目:

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
    
  6. 伺服器從 Cloud Service Mesh 取得必要設定後,您會看到下列輸出內容:

    Listening on port 50051
    plain text health service listening on port 50052
    

Python

  1. 取得為 example-grpc-server 服務建立的 Pod 名稱:

    kubectl get pods | grep example-grpc-server
    

    您會看到類似下列的意見回饋:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. 開啟伺服器 Pod 的殼層:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. 在殼層中,確認 /tmp/grpc-xds/td-grpc-bootstrap.json 的啟動檔案符合「啟動檔案」一節所述的結構定義。

  4. 下載 gRPC Python 1.41.0 版,並建構範例應用程式。

    apt-get update -y
    
    apt-get install -y python3 python3-pip
    
    curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
    
    cd grpc-1.41.x/examples/python/xds/
    
    python3 -m virtualenv venv
    
    source venv/bin/activate
    
    python3 -m pip install -r requirements.txt
    

  5. 使用 --xds-creds 標記執行伺服器,指出已啟用 xDS 的安全性,並使用 50051 做為接聽通訊埠。

    python3 server.py 50051 --xds-creds
    
  6. 伺服器從 Cloud Service Mesh 取得必要設定後,您會看到下列輸出內容:

    2021-05-06 16:10:34,042: INFO     Running with xDS Server credentials
    2021-05-06 16:10:34,043: INFO     Greeter server listening on port 50051
    2021-05-06 16:10:34,046: INFO     Maintenance server listening on port 50052
    

Go

  1. 取得為 example-grpc-server 服務建立的 Pod 名稱:

    kubectl get pods | grep example-grpc-server
    

    您會看到類似下列的意見回饋:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. 開啟伺服器 Pod 的殼層:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
    
  3. 在殼層中,確認 /tmp/grpc-xds/td-grpc-bootstrap.json 的啟動檔案符合「啟動檔案」一節所述的結構定義。

  4. 下載 gRPC Go 1.41.0 版,然後前往包含 xds-hello-world 伺服器應用程式的目錄。

    apk add curl
    
    curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz
    
    cd grpc-go-1.42.0/examples/features/xds/server
    
    
  5. 使用 --xds_creds 標記建構及執行伺服器,指出已啟用 xDS 的安全性,並使用 50051 做為接聽埠:

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -port 50051
    
  6. 伺服器從 Cloud Service Mesh 取得必要設定後,您會看到下列輸出內容:

    Using xDS credentials...
    Serving GreeterService on 0.0.0.0:50051 and HealthService on 0.0.0.0:50052
    

伺服器啟動後,健康狀態檢查程序需要 3 到 5 分鐘,才會顯示服務健康狀態良好。

執行用戶端並驗證設定

在您先前建立的用戶端 Pod 中,建構及執行啟用 xDS 的 helloworld 用戶端。

Java

  1. 取得用戶端 Pod 的名稱:

    kubectl get pods | grep example-grpc-client
    

    你會看到類似以下的意見回饋:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. 開啟用戶端 Pod 的殼層:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. 在指令殼層中,下載 gRPC Java 1.42.1 版,並建構 xds-hello-world 用戶端應用程式。

    curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz
    
    cd grpc-java-1.42.1/examples/example-xds
    
    ../gradlew --no-daemon installDist
    
  4. 使用 --xds-creds 標記執行用戶端,指出啟用 xDS 的安全性、用戶端名稱和目標連線字串:

    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke:8000
    

    畫面會顯示類似以下的輸出:

    Greeting: Hello xds-client, from xds-server
    

C++

  1. 取得用戶端 Pod 的名稱:

    kubectl get pods | grep example-grpc-client
    

    你會看到類似以下的意見回饋:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. 開啟用戶端 Pod 的殼層:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. 進入殼層後,請下載 gRPC C++ 並建構 xds-hello-world 用戶端應用程式。

    apt-get update -y && \
            apt-get install -y \
                build-essential \
                clang \
                python3 \
                python3-dev
    
    curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
    
    cd grpc-master
    
    tools/bazel build examples/cpp/helloworld:xds_greeter_client
    
  4. 使用 --xds-creds 標記執行用戶端,指出啟用 xDS 的安全性、用戶端名稱和目標連線字串:

    bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000
    

    如要在沒有憑證的情況下執行用戶端,請使用下列指令:

    bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000 --nosecure
    

    畫面會顯示類似以下的輸出:

    Greeter received: Hello world
    

Python

  1. 取得用戶端 Pod 的名稱:

    kubectl get pods | grep example-grpc-client
    

    你會看到類似以下的意見回饋:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. 開啟用戶端 Pod 的殼層:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. 進入殼層後,請下載 gRPC Python 1.41.0 版,並建構範例用戶端應用程式。

    apt-get update -y
    apt-get install -y python3 python3-pip
    python3 -m pip install virtualenv
    curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
    cd grpc-1.41.x/examples/python/xds/
    python3 -m virtualenv venv
    source venv/bin/activate
    python3 -m pip install -r requirements.txt
    
  4. 使用 --xds-creds 標記執行用戶端,指出啟用 xDS 的安全性、用戶端名稱和目標連線字串:

    python3 client.py xds:///helloworld-gke:8000 --xds-creds
    

    畫面會顯示類似以下的輸出:

    Greeter client received: Hello you from example-host!
    

Go

  1. 取得用戶端 Pod 的名稱:

    kubectl get pods | grep example-grpc-client
    

    你會看到類似以下的意見回饋:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. 開啟用戶端 Pod 的殼層:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
    
  3. 進入殼層後,請下載 gRPC Go 1.42.0 版,然後前往包含 xds-hello-world 用戶端應用程式的目錄。

    apk add curl
    
    curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz
    
    cd grpc-go-1.42.0/examples/features/xds/client
    
  4. 使用 --xds_creds 標記建構及執行用戶端,指出啟用 xDS 的安全性、用戶端名稱和目標連線字串:

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke:8000
    

    畫面會顯示類似以下的輸出:

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    

透過授權政策設定服務層級存取權

授權政策支援功能需要 gRFC A41 支援。您可以在 github 找到所需語言版本

請按照這些操作說明,透過授權政策設定服務層級存取權。建立授權政策前,請先詳閱「使用授權限制存取權」一文中的注意事項。

為方便驗證設定,請建立額外的主機名稱,供用戶端參照 helloworld-gke 服務。

  1. 更新先前儲存在 grpc_route.yaml 中的 GRPCRoute 規格

    name: helloworld-grpc-route
    hostnames:
    - helloworld-gke:8000
    - helloworld-gke-noaccess:8000
    meshes:
    - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
    
  2. grpc_route.yaml 規格再次匯入 GRPCRoute 資源。

    gcloud network-services grpc-routes import helloworld-grpc-route \
      --source=grpc_route.yaml \
      --location=global
    

下列操作說明會建立授權政策,允許由主機名稱為 helloworld-gke:8000、通訊埠為 50051example-grpc-client 帳戶傳送要求。

gcloud

  1. 建立名為 helloworld-gke-authz-policy.yaml 的檔案,藉此建立授權政策。

    action: ALLOW
    name: helloworld-gke-authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/default/sa/example-grpc-client
      destinations:
      - hosts:
        - helloworld-gke:8000
        ports:
        - 50051
    
  2. 匯入政策。

    gcloud network-security authorization-policies import \
      helloworld-gke-authz-policy \
      --source=helloworld-gke-authz-policy.yaml \
      --location=global
    
  3. 將下列內容附加至 ep-mtls-psms.yaml 檔案,藉此更新端點政策,參照新的授權政策。

    authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policy
    

    端點政策現在指定,對於 gRPC 啟動程序檔案包含 app:helloworld 標籤的 Pod,必須對傳入要求強制執行 mTLS 和授權政策。

  4. 匯入政策:

    gcloud network-services endpoint-policies import ep-mtls-psms \
      --source=ep-mtls-psms.yaml --location=global
    

驗證授權政策

請按照這些操作說明,確認授權政策是否正常運作。

Java

  1. 開啟先前使用的用戶端 Pod 的殼層。

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. 在命令殼層中執行下列指令,驗證設定。

    cd grpc-java-1.42.1/examples/example-xds
    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke:8000
    

    畫面會顯示類似以下的輸出:

    Greeting: Hello xds-client, from xds-server
    
  3. 使用替代伺服器名稱再次執行用戶端。請注意,這是失敗案例。授權政策只允許存取 helloworld-gke:8000 主機名稱,因此要求無效。

    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke-noaccess:8000
    

    畫面會顯示類似以下的輸出:

    WARNING: RPC failed: Status{code=PERMISSION_DENIED}
    

    如果沒有看到這項輸出內容,表示授權政策可能尚未啟用。請稍候片刻,然後再次嘗試完成整個驗證程序。

Go

  1. 開啟先前使用的用戶端 Pod 的殼層。

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. 在命令殼層中執行下列指令,驗證設定。

    cd grpc-go-1.42.0/examples/features/xds/client
    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke:8000
    

    畫面會顯示類似以下的輸出:

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    
  3. 使用替代伺服器名稱再次執行用戶端。請注意,這是失敗案例。授權政策只允許存取 helloworld-gke:8000 主機名稱,因此要求無效。

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke-noaccess:8000
    

    畫面會顯示類似以下的輸出:

    could not greet: rpc error: code = PermissionDenied desc = Incoming RPC is not allowed: rpc error: code = PermissionDenied desc = incoming RPC did not match an allow policy
    exit status 1
    

    如果沒有看到這項輸出內容,表示授權政策可能尚未啟用。請稍候片刻,然後再次嘗試完成整個驗證程序。

使用 TLS 而非 mTLS

在這個範例中,使用 TLS 只需進行小幅變更。

  1. ServerTlsPolicy 中,放置 mtlsPolicy

    cat << EOF > server-tls-policy.yaml
    name: "server-tls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    
  2. 請改用 EndpointPolicy 中的這項政策:

    cat << EOF > ep-tls-psms.yaml
    name: "ep-mtls-psms"
    type: "GRPC_SERVER"
    serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-tls-policy"
    trafficPortSelector:
      ports:
      - "50051"
    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: "MATCH_ALL"
        metadataLabels: []
    EOF
    
  3. mTLS 的 ClientTlsPolicy 也適用於 TLS,但可以捨棄政策的 clientCertificate 部分,因為 TLS 不需要這項設定:

    cat << EOF > client-tls-policy.yaml
    name: "client-tls-policy"
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    

在 Google 錢包範例中使用服務安全性

本節將概略說明如何為 Java、C++ 和 Go 啟用錢包範例的服務安全性。

Java

您可以在 github 找到 Java 的範例原始碼。 設定無 Proxy 安全性時,程式碼已使用 XdsChannelXdsServer 憑證。

這些操作說明介紹如何使用 Go 設定錢包範例。Java 的程序類似。這些操作說明會使用從Google Cloud 容器存放區取得的現有 Docker 映像檔。

如要建立範例,請按照下列操作說明操作:

  1. 複製存放區,並取得 gRPC 範例目錄中的檔案。
  2. 編輯 00-common-env.sh 檔案。註解掉現有行,將 WALLET_DOCKER_IMAGE 的值設為 Go Docker 映像檔,並取消註解將 WALLET_DOCKER_IMAGE 的值設為 Java Docker 映像檔的行。
  3. 按照「建立及設定 Cloud Router 執行個體」一文中的操作說明,或使用指令碼 10.apis.sh 中的 create_cloud_router_instances 函式,建立及設定 Cloud Router 執行個體。
  4. 使用hello world 範例的指示建立叢集,或使用指令碼 20-cluster.sh 中的 create_cluster 函式。
  5. 按照憑證授權單位服務的操作說明建立私有憑證授權單位,或使用 30-private-ca-setup.sh 指令碼。
  6. 建立 Kubernetes 資源,包括服務帳戶、命名空間、Kubernetes 服務、NEG 和所有服務的伺服器端部署作業:accountstatsstats_premiumwallet_v1wallet_v2,使用指令碼 40-k8s-resources.sh
  7. 針對您建立的每項服務,使用指令碼 50-td-components.sh 中的 create_health_checkcreate_backend_service,建立健康狀態檢查和後端服務。
  8. 使用指令碼 60-routing-components.sh 中的 create_routing_components 建立 Cloud Service Mesh 路由元件。
  9. 使用指令碼 70-security-components.sh 中的 create_security_components,為每個後端服務建立 Cloud Service Mesh 安全性元件。
  10. 使用指令碼 75-client-deployment.sh 中的 create_client_deployment 建立 Wallet 用戶端部署作業。
  11. 如要驗證設定,請按照「使用 grpc-wallet 用戶端驗證」一文所述啟動用戶端。

C++

您可以在 github 找到 C++ 的範例原始碼。設定無 Proxy 安全性時,程式碼已使用 XdsChannelXdsServer 憑證。

這些操作說明說明如何使用 Go 設定 Wallet 範例。C++ 的程序類似。這些操作說明使用從Google Cloud 容器存放區取得的現有 Docker 映像檔。

如要建立範例,請按照下列操作說明操作:

  1. 複製存放區,並取得 gRPC 範例目錄中的檔案。
  2. 編輯 00-common-env.sh 檔案。註解排除現有程式碼行,將 WALLET_DOCKER_IMAGE 的值設為 Go Docker 映像檔,並取消註解將 WALLET_DOCKER_IMAGE 的值設為 C++ Docker 映像檔的程式碼行。
  3. 按照「建立及設定 Cloud Router 執行個體」一文中的操作說明,或使用指令碼 10.apis.sh 中的 create_cloud_router_instances 函式,建立及設定 Cloud Router 執行個體。
  4. 使用hello world 範例的指示建立叢集,或使用指令碼 20-cluster.sh 中的 create_cluster 函式。
  5. 按照 CA 服務的操作說明,或使用 30-private-ca-setup.sh 指令碼,建立私有憑證授權單位。
  6. 建立 Kubernetes 資源,包括服務帳戶、命名空間、Kubernetes 服務、NEG 和所有服務的伺服器端部署作業:accountstatsstats_premiumwallet_v1wallet_v2,使用指令碼 40-k8s-resources.sh
  7. 針對您建立的每項服務,使用指令碼 50-td-components.sh 中的 create_health_checkcreate_backend_service,建立健康狀態檢查和後端服務。
  8. 使用指令碼 60-routing-components.sh 中的 create_routing_components 建立 Cloud Service Mesh 路由元件。
  9. 使用指令碼 70-security-components.sh 中的 create_security_components,為每個後端服務建立 Cloud Service Mesh 安全性元件。
  10. 使用指令碼 75-client-deployment.sh 中的 create_client_deployment 建立 Wallet 用戶端部署作業。
  11. 如要驗證設定,請按照「使用 grpc-wallet 用戶端驗證」一文所述啟動用戶端。

Go

您可以在 github 找到 Go 的原始碼範例。設定無 Proxy 安全性時,程式碼已使用 XdsChannelXdsServer 憑證。

這些操作說明會使用您從Google Cloud 容器存放區取得的現有 Docker 映像檔。

如要建立範例,請按照下列操作說明操作:

  1. 複製存放區,並取得 gRPC 範例目錄中的檔案。
  2. 編輯 00-common-env.sh 檔案,為環境變數設定正確的值。
  3. 按照「建立及設定 Cloud Router 執行個體」一文中的操作說明,或使用指令碼 10.apis.sh 中的 create_cloud_router_instances 函式,建立及設定 Cloud Router 執行個體。
  4. 使用hello world 範例的指示建立叢集,或使用指令碼 20-cluster.sh 中的 create_cluster 函式。
  5. 按照憑證授權單位服務的操作說明建立私有憑證授權單位,或使用 30-private-ca-setup.sh 指令碼。
  6. 建立 Kubernetes 資源,包括服務帳戶、命名空間、Kubernetes 服務、NEG 和所有服務的伺服器端部署作業:accountstatsstats_premiumwallet_v1wallet_v2,使用指令碼 40-k8s-resources.sh
  7. 針對您建立的每項服務,使用指令碼 50-td-components.sh 中的 create_health_checkcreate_backend_service,建立健康狀態檢查和後端服務。
  8. 使用指令碼 60-routing-components.sh 中的 create_routing_components 建立 Cloud Service Mesh 路由元件。
  9. 使用指令碼 70-security-components.sh 中的 create_security_components,為每個後端服務建立 Cloud Service Mesh 安全性元件。
  10. 使用指令碼 75-client-deployment.sh 中的 create_client_deployment 建立 Wallet 用戶端部署作業。
  11. 如要驗證設定,請按照「使用 grpc-wallet 用戶端驗證」一文所述啟動用戶端。

啟動檔案

本指南中的設定程序會使用啟動產生器建立必要的啟動檔案。本節提供有關啟動檔案本身的參考資訊。

啟動程序檔案包含無代理程式 gRPC 程式碼所需的設定資訊,包括 xDS 伺服器的連線資訊。啟動程序檔案包含無 Proxy gRPC 安全性功能所需的安全性設定。gRPC 伺服器需要一個額外欄位。範例啟動程序檔案如下所示:

{
  "xds_servers": [
    {
      "server_uri": "trafficdirector.googleapis.com:443",
      "channel_creds": [
        {
          "type": "google_default"
        }
      ],
      "server_features": [
        "xds_v3"
      ]
    }
  ],
  "authorities": {
    "traffic-director-c2p.xds.googleapis.com": {
      "xds_servers": [
        {
          "server_uri": "dns:///directpath-pa.googleapis.com",
          "channel_creds": [
            {
              "type": "google_default"
            }
          ],
          "server_features": [
            "xds_v3",
            "ignore_resource_deletion"
          ]
        }
      ],
      "client_listener_resource_name_template": "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.listener.v3.Listener/%s"
    }
  },
  "node": {
    "id": "projects/9876012345/networks/mesh:grpc-mesh/nodes/b59f49cc-d95a-4462-9126-112f794d5dd3",
    "cluster": "cluster",
    "metadata": {
      "INSTANCE_IP": "10.28.2.8",
      "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE": true,
      "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "223606568246",
      "TRAFFICDIRECTOR_NETWORK_NAME": "default",
      "app": "helloworld"
    },
    "locality": {
      "zone": "us-central1-c"
    }
  },
  "certificate_providers": {
    "google_cloud_private_spiffe": {
      "plugin_name": "file_watcher",
      "config": {
        "certificate_file": "/var/run/secrets/workload-spiffe-credentials/certificates.pem",
        "private_key_file": "/var/run/secrets/workload-spiffe-credentials/private_key.pem",
        "ca_certificate_file": "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem",
        "refresh_interval": "600s"
      }
    }
  },
  "server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s"
}

更新安全服務的啟動程序檔案

下列欄位反映與安全性和 xDS v3 用法相關的修改內容:

node 內的 id 欄位會為 gRPC 用戶端提供 Cloud Service Mesh 的專屬身分。您必須使用節點 ID,以以下格式提供 Google Cloud 專案編號和網路名稱:

projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]

以專案編號 1234 和預設網路為例:

projects/1234/networks/default/nodes/client1

INSTANCE_IP 欄位是 Pod 的 IP 位址,或 0.0.0.0 表示 INADDR_ANY。gRPC 伺服器會使用這個欄位,從 Cloud Service Mesh 擷取 Listener 資源,確保伺服器端安全。

啟動檔案中的安全性設定欄位

JSON 金鑰 類型 附註
server_listener_resource_name_template 字串 grpc/server?xds.resource.listening_address=%s gRPC 伺服器必須提供此值。gRPC 會使用這個值組成資源名稱,以便從 Cloud Service Mesh 擷取 `Listener` 資源,用於伺服器端安全性和其他設定。gRPC 會使用這個值組成資源名稱字串
certificate_providers JSON 結構 google_cloud_private_spiffe 這是必要旗標,這個值是 JSON 結構體,代表名稱對應至憑證供應商執行個體的地圖。憑證提供者執行個體用於擷取身分和根憑證。範例啟動程序檔案包含一個名稱:google_cloud_private_spiffe,值為憑證提供者執行個體 JSON 結構體。每個憑證供應商執行個體 JSON 結構體都有兩個欄位:
  • plugin_name。必要值,用於識別要使用的憑證提供者外掛程式,這是 gRPC 憑證提供者外掛程式架構的規定。gRPC 內建支援檔案監控外掛程式,這個設定會使用該外掛程式。plugin_name 為 file_watcher
  • config。必要值,用於識別 file_watcher 外掛程式的 JSON 設定網誌。結構定義和內容取決於外掛程式。

file_watcher 外掛程式的 config JSON 結構內容如下:

  • certificate_file:必要字串。這個值是身分識別憑證的位置。
  • private_key_file:必要字串。這個值是私密金鑰檔案的位置,應與身分識別憑證相符。
  • ca_certificate_file:必要字串。此值是根憑證的位置,也稱為信任組合。
  • refresh_interval:選用字串。這個值表示重新整理間隔,並以 Duration 的 JSON 對應字串表示法指定。預設值為「600 秒」,也就是 10 分鐘。

啟動產生器

您可以在 gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 找到啟動程序產生器容器映像檔。原始碼位於 https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap。最常用的指令列選項如下:

  • --output:使用這個選項指定輸出自我啟動檔案的寫入位置,例如,指令 --output /tmp/bootstrap/td-grpc-bootstrap.json 會在 Pod 的檔案系統中,將自我啟動檔案產生至 /tmp/bootstrap/td-grpc-bootstrap.json
  • --config-mesh-experimental:使用這個選項指定網格名稱,與 Mesh 資源相符。
  • --node-metadata:使用這個標記在自我啟動檔案中填入節點中繼資料。在 EndpointPolicy 中使用中繼資料標籤比對器時,必須設定這個項目,因為 Cloud Service Mesh 會使用啟動程序檔案節點中繼資料部分提供的標籤資料。引數以 key=value 的形式提供,例如:--node-metadata version=prod --node-metadata type=grpc

上述資訊會在啟動程序檔案的節點中繼資料部分新增下列內容:

{
  "node": {
...
    "metadata": {
      "version": "prod",
      "type": "grpc",
...
    },
...
  },
...
}

刪除部署作業

您可以選擇執行這些指令,刪除使用本指南建立的部署項目。

如要刪除叢集,請執行下列指令:

gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet

如要刪除您建立的資源,請執行下列指令:

gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet
gcloud compute network-endpoint-groups delete example-grpc-server --zone ZONE --quiet
gcloud compute firewall-rules delete grpc-gke-allow-health-checks --quiet
gcloud compute health-checks delete grpc-gke-helloworld-hc --quiet
gcloud network-services endpoint-policies delete ep-mtls-psms \
    --location=global --quiet
gcloud network-security authorization-policies delete helloworld-gke-authz-policy \
   --location=global --quiet
gcloud network-security client-tls-policies delete client-mtls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-tls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-mtls-policy \
    --location=global --quiet

疑難排解

請按照這些操作說明排解安全性部署問題。

工作負載無法從 Cloud Service Mesh 取得設定

如果看到類似以下的錯誤訊息:

PERMISSION_DENIED: Request had insufficient authentication scopes.

請確認您做到了以下各項:

  • 您已使用 --scopes=cloud-platform 引數建立 GKE 叢集。
  • 您已將 roles/trafficdirector.client 指派給 Kubernetes 服務帳戶。
  • 您已將 roles/trafficdirector.client 指派給預設 Google Cloud 服務帳戶 (上方的 ${GSA_EMAIL})。
  • 您已啟用 trafficdirector.googleapis.com 服務 (API)。

即使 Cloud Service Mesh 設定正確,gRPC 伺服器也不會使用 TLS/mTLS

請務必在端點政策設定中指定 GRPC_SERVER。如果您指定 SIDECAR_PROXY,gRPC 會忽略設定。

您無法使用要求的叢集版本建立 GKE 叢集

GKE 叢集建立指令可能會失敗,並顯示類似下列的錯誤:

Node version "1.20.5-gke.2000" is unsupported.

請確認叢集建立指令中是否使用 --release-channel rapid 引數。您必須使用快速發布管道,才能取得這個版本的正確版本。

畫面顯示 No usable endpoint 錯誤

如果用戶端因No usable endpoint錯誤而無法與伺服器通訊,健康狀態檢查程式可能會將伺服器後端標示為不健康。如要檢查後端的健康狀態,請執行這個 gcloud 指令:

gcloud compute backend-services get-health grpc-gke-helloworld-service --global

如果指令傳回的後端狀態為「不正常」,可能是因為下列其中一個原因:

  • 防火牆未建立或未包含正確的來源 IP 範圍。
  • 防火牆上的目標標記與您建立的叢集標記不符。

工作負載無法在安全性設定中通訊

為無 Proxy 服務網格設定安全性後,如果工作負載無法通訊,請按照下列操作說明找出原因。

  1. 停用無 Proxy 安全性,並解決無 Proxy 服務網格負載平衡使用案例中的問題。如要停用網狀網路的安全防護功能,請採取下列任一做法:
    1. 在用戶端和伺服器端使用純文字憑證,或
    2. 請勿在 Cloud Service Mesh 設定中,為後端服務和端點政策設定安全性。

請按照「排解無 Proxy 的 Cloud Service Mesh 部署作業問題」一文中的步驟操作,因為您的部署作業沒有任何安全性設定。

  1. 修改工作負載,使用 xDS 憑證搭配純文字或不安全的憑證做為備用憑證。如先前所述,請保留停用安全性的 Cloud Service Mesh 設定。在這種情況下,雖然 gRPC 允許 Cloud Service Mesh 設定安全性,但 Cloud Service Mesh 不會傳送安全性資訊,因此 gRPC 應會改用純文字 (或不安全) 憑證,運作方式與先前的第一種情況類似。如果這個方法無效,請按照下列步驟操作:

    1. 提高用戶端和伺服器端的記錄層級,即可查看 gRPC 和 Cloud Service Mesh 之間交換的 xDS 訊息。
    2. 確認傳送至工作負載的 CDS 和 LDS 回應中,Cloud Service Mesh 未啟用安全性。
    3. 確認工作負載的管道未使用 TLS 或 mTLS 模式。如果看到任何與 TLS 交握相關的記錄訊息,請檢查應用程式原始碼,確認您是否使用不安全的憑證或純文字做為備用憑證。如果應用程式原始碼正確,這可能是 gRPC 程式庫中的錯誤
  2. 請按照該使用者指南中的疑難排解步驟,確認 CA 服務與 GKE 的整合功能是否正常運作。請確認該功能提供的憑證和金鑰位於指定目錄 /var/run/secrets/workload-spiffe-credentials/ 中。

  3. 如先前所述,在網格中啟用 TLS (而非 mTLS),然後重新啟動用戶端和伺服器工作負載。

    1. 提高用戶端和伺服器端的記錄層級,即可查看 gRPC 和 Cloud Service Mesh 之間交換的 xDS 訊息。
    2. 確認 Cloud Service Mesh 已在傳送至工作負載的 CDS 和 LDS 回應中啟用安全性。

用戶端失敗,並顯示 CertificateException 和訊息 Peer certificate SAN check failed

這表示 SecuritySettings 訊息中的 subjectAltNames 值有問題。請注意,這些值是根據您為後端服務建立的 Kubernetes 服務而定。您建立的每個 Kubernetes 服務都有相關聯的 SPIFFE ID,格式如下:

spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}

這些值包括:

  • WORKLOAD_POOL:叢集的工作負載集區,為 ${PROJECT_ID}.svc.id.goog
  • K8S_NAMESPACE:部署服務時使用的 Kubernetes 命名空間
  • SERVICE_ACCOUNT:部署服務時使用的 Kubernetes 服務帳戶

針對您以網路端點群組形式附加至後端服務的每個 Kubernetes 服務,請務必正確計算 SPIFFE ID,並將該 SPIFFE ID 新增至 SecuritySettings 訊息的 subjectAltNames 欄位。

應用程式無法搭配 gRPC 程式庫使用 mTLS 憑證

如果應用程式無法搭配 gRPC 程式庫使用 mTLS 憑證,請執行下列操作:

  1. 確認 Pod 規格包含使用 NEG 建立無 Proxy gRPC 服務一文所述的 security.cloud.google.com/use-workload-certificates 註解。

  2. 確認包含憑證鏈結、葉節點憑證、私密金鑰和信任的 CA 憑證的檔案,可從 Pod 內的下列路徑存取:

    1. 憑證鏈結和分葉憑證:「/var/run/secrets/workload-spiffe-credentials/certificates.pem」
    2. 私密金鑰:「/var/run/secrets/workload-spiffe-credentials/private_key.pem」
    3. CA 組合包:「/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem」
  3. 如果上一個步驟中的憑證無法使用,請按照下列步驟操作:

      gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME 
    --location=LOCATION

    1. 確認 GKE 的控制平面具有正確的 IAM 角色繫結,可授予 CA 服務存取權:

      # Get the IAM policy for the CA
      gcloud privateca roots get-iam-policy ROOT_CA_POOL_NAME
      
      # Verify that there is an IAM binding granting access in the following format
      - members:
      - serviceAccount:service-projnumber@container-engine-robot.iam.gserviceaccount.com
      role: roles/privateca.certificateManager
      
      # Where projnumber is the project number (e.g. 2915810291) for the GKE cluster.
      
    2. 確認憑證未過期。這是憑證鏈結和分葉憑證,位於 /var/run/secrets/workload-spiffe-credentials/certificates.pem。如要檢查,請執行下列指令:

      cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
      

    3. 執行下列指令,確認應用程式支援金鑰類型:

      cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
      

    4. 確認 gRPC Java 應用程式的 WorkloadCertificateConfig YAML 檔案中包含下列 keyAlgorithm

      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
  4. 確認 CA 使用的金鑰系列與憑證金鑰相同。

應用程式的憑證遭到用戶端、伺服器或對等互連裝置拒絕

  1. 確認對等應用程式使用相同的信任套件來驗證憑證。
  2. 確認使用的憑證未過期 (憑證鏈結和分葉憑證:「/var/run/secrets/workload-spiffe-credentials/certificates.pem」)。

Pod 仍處於待處理狀態

如果在設定過程中,Pod 仍處於待處理狀態,請在部署規格中增加 Pod 的 CPU 和記憶體資源。

無法使用 --enable-mesh-certificates 標記建立叢集

確認您使用的是最新版 gcloud CLI:

gcloud components update

請注意,--enable-mesh-certificates 標記僅適用於 gcloud beta

Pod 無法啟動

如果憑證佈建失敗,使用 GKE Mesh 憑證的 Pod 可能無法啟動。可能發生這種情況的情境如下:

  • WorkloadCertificateConfigTrustConfig 設定有誤或缺少。
  • CSR 未獲核准。

您可以檢查 Pod 事件,確認憑證佈建是否失敗。

  1. 檢查 Pod 的狀態:

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

    更改下列內容:

    • POD_NAMESPACE:Pod 的命名空間。
    • POD_NAME:Pod 的名稱。
  2. 查看 Pod 的近期事件:

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. 如果憑證佈建失敗,您會看到含有 Type=WarningReason=FailedMountFrom=kubeletMessage 欄位的事件,且 Message 欄位開頭為 MountVolume.SetUp failed for volume "gke-workload-certificates"Message 欄位包含疑難排解資訊。

    Events:
      Type     Reason       Age                From       Message
      ----     ------       ----               ----       -------
      Warning  FailedMount  13s (x7 over 46s)  kubelet    MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
    
  4. 如果 Pod 無法啟動的原因是物件設定有誤或 CSR 遭拒,請參閱下列疑難排解步驟。

WorkloadCertificateConfigTrustConfig 設定有誤

請確認您已正確建立 WorkloadCertificateConfigTrustConfig 物件。您可以使用 kubectl 診斷這兩個物件的設定錯誤。

  1. 擷取目前狀態。

    針對 WorkloadCertificateConfig

    kubectl get WorkloadCertificateConfig default -o yaml
    

    針對 TrustConfig

    kubectl get TrustConfig default -o yaml
    
  2. 檢查狀態輸出內容。有效物件的條件會包含 type: Readystatus: "True"

    status:
      conditions:
      - lastTransitionTime: "2021-03-04T22:24:11Z"
        message: WorkloadCertificateConfig is ready
        observedGeneration: 1
        reason: ConfigReady
        status: "True"
        type: Ready
    

    如果是無效物件,則會改為顯示 status: "False"reasonmessage欄位包含其他疑難排解詳細資料。

CSR 未獲核准

如果 CSR 核准程序發生錯誤,您可以查看 CSR 的 type: Approvedtype: Issued 條件,瞭解錯誤詳細資料。

  1. 使用 kubectl 列出相關 CSR:

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. 選擇 Approved 且不是 Issued 的 CSR,或選擇不是 Approved 的 CSR。

  3. 使用 kubectl 取得所選 CSR 的詳細資料:

    kubectl get csr CSR_NAME -o yaml
    

    CSR_NAME 替換為您選擇的 CSR 名稱。

有效的 CSR 具有 type: Approvedstatus: "True" 的條件,以及 status.certificate 欄位中的有效憑證:

status:
  certificate: <base64-encoded data>
  conditions:
  - lastTransitionTime: "2021-03-04T21:58:46Z"
    lastUpdateTime: "2021-03-04T21:58:46Z"
    message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
    reason: AutoApproved
    status: "True"
    type: Approved

無效 CSR 的疑難排解資訊會顯示在 messagereason 欄位中。

Pod 缺少憑證

  1. 取得 Pod 的 Pod 規格:

    kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
    

    更改下列內容:

    • POD_NAMESPACE:Pod 的命名空間。
    • POD_NAME:Pod 的名稱。
  2. 確認 Pod 規格包含security.cloud.google.com/use-workload-certificates設定 Pod 以接收 mTLS 憑證」一文所述的註解。

  3. 確認 GKE Mesh 憑證准入控制器是否已將 workloadcertificates.security.cloud.google.com 類型的 CSI 驅動程式磁碟區成功注入 Pod 規格:

    volumes:
    ...
    -csi:
      driver: workloadcertificates.security.cloud.google.com
      name: gke-workload-certificates
    ...
    
  4. 檢查每個容器中是否有磁碟區掛接:

    containers:
    - name: ...
      ...
      volumeMounts:
      - mountPath: /var/run/secrets/workload-spiffe-credentials
        name: gke-workload-certificates
        readOnly: true
      ...
    
  5. 確認下列憑證套件和私密金鑰位於 Pod 中的下列位置:

    • 憑證鏈結套裝組合:/var/run/secrets/workload-spiffe-credentials/certificates.pem
    • 私密金鑰:/var/run/secrets/workload-spiffe-credentials/private_key.pem
    • CA 信任錨點套裝組合:/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
  6. 如果沒有這些檔案,請按照下列步驟操作:

    1. 為叢集擷取 CA 服務 (預先發布版) 執行個體:

      kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
      
    2. 擷取 CA 服務 (預覽版) 執行個體的狀態:

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      更改下列內容:

      • ISSUING_CA_TYPE:核發 CA 類型,必須是 subordinatesroots
      • ISSUING_CA_NAME:核發 CA 的名稱。
      • ISSUING_CA_LOCATION:核發 CA 的區域。
    3. 取得根 CA 的 IAM 政策:

      gcloud privateca roots get-iam-policy ROOT_CA_NAME
      

      ROOT_CA_NAME 替換成根 CA 的名稱。

    4. 在 IAM 政策中,確認政策繫結是否存在:privateca.auditor

      ...
      - members:
        - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
        role: roles/privateca.auditor
      ...
      

      在本例中,PROJECT_NUMBER 是叢集的專案編號。

    5. 取得從屬 CA 的 IAM 政策:

      gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
      

      SUBORDINATE_CA_NAME 替換為下層 CA 名稱。

    6. 在 IAM 政策中,確認 privateca.certificateManager 政策繫結是否存在:

      ...
      - members:
        - serviceAccount: service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
        role: roles/privateca.certificateManager
      ...
      

      在本例中,PROJECT_NUMBER 是叢集的專案編號。

應用程式無法使用核發的 mTLS 憑證

  1. 確認憑證未過期:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. 確認應用程式支援您使用的金鑰類型。

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. 確認核發 CA 使用的金鑰系列與憑證金鑰相同。

    1. 取得 CA 服務 (預覽版) 執行個體的狀態:

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      更改下列內容:

      • ISSUING_CA_TYPE:核發 CA 類型,必須是 subordinatesroots
      • ISSUING_CA_NAME:核發 CA 的名稱。
      • ISSUING_CA_LOCATION:核發 CA 的區域。
    2. 檢查輸出內容中的 keySpec.algorithm 是否與您在 WorkloadCertificateConfig YAML 資訊清單中定義的金鑰演算法相同。輸出如下所示:

      config:
        ...
        subjectConfig:
          commonName: td-sub-ca
          subject:
            organization: TestOrgLLC
          subjectAltName: {}
      createTime: '2021-05-04T05:37:58.329293525Z'
      issuingOptions:
        includeCaCertUrl: true
      keySpec:
        algorithm: RSA_PKCS1_2048_SHA256
       ...
      

認證遭拒

  1. 確認對等應用程式使用相同的信任套件來驗證憑證。
  2. 確認憑證未過期:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. 如果未使用 gRPC Go 憑證重新載入 API,請確認用戶端程式碼會定期從檔案系統重新整理憑證。

  4. 確認工作負載與 CA 位於相同的信任網域。GKE 網格憑證支援單一信任網域中的工作負載通訊。

限制

只有 GKE 支援 Cloud Service Mesh 服務安全。您無法使用 Compute Engine 部署服務安全性。

如果兩個以上的端點政策資源與端點完全相符 (例如兩個政策具有相同的標籤和連接埠,或兩個以上的政策具有不同的標籤,但與端點的標籤完全相符),Cloud Service Mesh 就不支援這類情境。如要進一步瞭解端點政策如何與端點標籤相符,請參閱「APIs for EndpointPolicy.EndpointMatcher.MetadataLabelMatcher」。在這種情況下,Cloud Service Mesh 不會從任何衝突的政策產生安全性設定。