使用 GKE 身分識別服務,從 Cloud Build 私人集區存取私人 Google Kubernetes Engine 叢集


本教學課程說明如何使用 Cloud Build 私人集區,存取私人 Google Kubernetes Engine (GKE) 叢集的控制層。有了這項存取權,您就能使用 Cloud Build 在私人 GKE 叢集上部署應用程式及管理資源。本教學課程適用於平台管理員、叢集管理員和開發人員。本文假設您已熟悉 GKE、Cloud Build、OpenID Connectgcloud 指令列工具。

Cloud Build 私人集區和 GKE 叢集控制層都會在 Google 擁有的虛擬私有雲 (VPC) 網路中執行。這些 VPC 網路會對等互連至 Google Cloud上的 VPC 網路。不過,虛擬私有雲網路對等互連「不支援遞移對等互連」,因此使用 Cloud Build 私人集區時可能會受到限制。本教學課程介紹的解決方案會使用 GKE 適用的 Identity Service,讓 Cloud Build 私人集區中的工作站存取私人 GKE 叢集的控制層。

架構總覽

GKE 適用的 Identity Service 是 GKE 叢集控制層的驗證 Proxy。這項服務會將要求代理至 API 伺服器,並驗證 OpenID Connect (OIDC) 身分識別提供者核發的 ID 權杖。Proxy 成功驗證 ID 權杖後,會將使用者模擬 HTTP 標頭新增至原始要求,並轉送至 API 伺服器。Proxy 會以 Kubernetes 服務帳戶的形式執行,並具備模擬使用者和群組的權限。

GKE 專用 Identity Service 代理程式會在叢集節點上以 Pod 形式執行。類型為 LoadBalancer 的 Kubernetes 服務會將 Proxy 公開至叢集外部。如果私有叢集已啟用 GKE 適用的 Identity Service,安裝程式會在 Kubernetes 服務中新增註解,以佈建內部直通網路負載平衡器。由於 Proxy 會在虛擬私有雲網路的叢集節點上執行,因此可透過虛擬私有雲網路對等互連連線 (例如 Cloud Build 私人集區) 透過負載平衡器存取 Proxy。

您可以在 GKE 適用的 Identity Service 中,將 Google 設定為 OpenID Connect 識別資訊提供者,因為 Google 的 OAuth 2.0 驗證系統符合 OpenID Connect 規格。如要取得 Google 服務帳戶的 ID 權杖,可以使用 Service Account Credentials API APIgenerateIdToken 方法。ID 權杖是由 Google 核發及簽署。

綜合上述做法,這個解決方案可透過 GKE 適用的 Identity 服務 Proxy,存取私人 GKE 叢集控制層。在 Cloud Build 私人集區執行的建構作業,會透過虛擬私有雲網路對等互連連線連至 Proxy。在 Cloud Build 私人集區中執行的建構作業會以 Google 服務帳戶身分執行。這個 Google 服務帳戶可透過 Service Account Credentials API 取得 ID 權杖,向 Proxy 進行驗證。

下圖顯示上文所述的架構:

使用 GKE 適用的 Identity Service 存取私人 GKE 叢集

這個解決方案中的所有通訊都會透過內部 IP 位址空間進行。私人集區中的工作站不需要公開網際網路連線。

透過 GKE 適用的 Identity Service 進行驗證時,系統不會套用授予使用者帳戶和 Google 服務帳戶的 Identity and Access Management (IAM) 權限。而是使用 Kubernetes 角色型存取控制 (RBAC) 管理這些帳戶的叢集權限。

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  4. To initialize the gcloud CLI, run the following command:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Cloud Build, GKE, Identity-Aware Proxy (IAP), and Service Networking APIs APIs:

    gcloud services enable cloudbuild.googleapis.com container.googleapis.com iap.googleapis.com servicenetworking.googleapis.com
  8. Install the Google Cloud CLI.

  9. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  10. To initialize the gcloud CLI, run the following command:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Make sure that billing is enabled for your Google Cloud project.

  13. Enable the Cloud Build, GKE, Identity-Aware Proxy (IAP), and Service Networking APIs APIs:

    gcloud services enable cloudbuild.googleapis.com container.googleapis.com iap.googleapis.com servicenetworking.googleapis.com

建立私人 GKE 叢集

  1. 在 Cloud Shell 中建立 GKE 叢集,該叢集不得有用戶端存取控制層公開端點的權限,且已安裝 GKE 適用的 Identity Service:

    gcloud container clusters create CLUSTER  \
      --enable-identity-service \
      --enable-ip-alias \
      --enable-master-authorized-networks \
      --enable-private-endpoint \
      --enable-private-nodes \
      --master-ipv4-cidr CONTROL_PLANE_CIDR \
      --network NETWORK\
      --release-channel regular \
      --scopes cloud-platform \
      --subnetwork SUBNET \
      --tags NODE_TAGS \
      --workload-pool PROJECT_ID.svc.id.goog \
      --zone ZONE
    

    更改下列內容:

    • CLUSTER:叢集名稱。在本教學課程中,請使用 private-cluster
    • CONTROL_PLANE_CIDR:控制層的 IP 位址範圍。必須加上 /28 前置字串,在本教學課程中,您可以使用 172.16.0.32/28
    • NETWORK:控制層連線的虛擬私有雲網路。在本教學課程中,請使用 default
    • SUBNET:GKE 叢集控制層連線的子網路。子網路必須屬於 NETWORK 指定的 VPC 網路。在本教學課程中,請使用 default
    • NODE_TAGS:以半形逗號分隔的網路標記清單,用於套用至節點。在本教學課程中,請使用 private-cluster-node
    • PROJECT_ID:您的 Google Cloud 專案 ID。
    • ZONE:GKE 叢集的區域。在本教學課程中,請使用 us-central1-f

    請注意下列指令的相關事項:

    • --enable-identity-service 標記會在叢集上啟用 GKE 適用的 Identity 服務。在自有環境中,您可以為現有叢集啟用 GKE 適用的 Identity Service

    • --enable-private-endpoint 標記會將控制層設為只能使用內部 IP 位址存取。

    • --enable-private-nodes 旗標會將叢集節點設為僅具備內部 IP 位址。

    • --enable-master-authorized-networks--enable-private-nodes 旗標只允許從 --network 旗標指定的私人網路存取 API 伺服器。

    • 選用的 --workload-pool 標記可啟用 Workload Identity Federation for GKE。本教學課程不需要這項工具。

  2. 新增防火牆規則,允許 GKE 叢集控制平面連線至 ClientConfig 資源的驗證准入 Webhook:

    gcloud compute firewall-rules create allow-control-plane-clientconfig-webhook \
      --allow tcp:15000 \
      --network NETWORK\
      --source-ranges CONTROL_PLANE_CIDR\
      --target-tags NODE_TAGS
    

    ClientConfig 是 Kubernetes 自訂資源類型 (CRD),GKE 適用的 Identity Service 會使用這項資源類型,設定與身分識別提供者互動的方式。

將 GKE 適用的 Identity 服務註冊為 OAuth 2.0 用戶端應用程式

在本節中,您將使用 Google 的 OAuth 2.0 驗證系統,將 GKE 適用的 Identity Service 註冊為用戶端應用程式。

  1. 在 Google Cloud 控制台中開啟「憑證」頁面。

    開啟「憑證」頁面

  2. 按一下「建立憑證」

  3. 選取「OAuth 用戶端 ID」

    如果尚未為 Google Cloud 專案設定同意畫面,請按一下「設定同意畫面」。請參閱設定同意畫面的說明文件。在本教學課程中,請設定下列值:

    • 「使用者類型」可以是「內部」或「外部」。在本教學課程中,您可以選取「內部」。
    • 應用程式名稱使用者支援電子郵件地址開發人員聯絡資訊的值為必填,且可為任何值。
    • 本教學課程不需要新增任何範圍。

    設定完同意畫面後,按一下「返回資訊主頁」,然後從目前程序的步驟 1 重新開始。

  4. 在「應用程式類型」清單中,選取「網頁應用程式」

  5. 在「Name」(名稱) 欄位中,輸入用戶端 ID 的名稱。在本教學課程中,請使用 Identity Service for GKE

  6. 點選「建立」

    系統隨即會顯示對話方塊。複製「您的用戶端 ID」的值,稍後會用到。

  7. 按一下「確定」關閉對話方塊。

  8. 在主目錄下方建立名為 cloud-build-private-pools-gke-tutorial 的目錄,然後前往該目錄:

    mkdir -p ~/cloud-build-private-pools-gke-tutorial cd ~/cloud-build-private-pools-gke-tutorial

  9. 在新目錄中,建立名為 client-config-patch.yaml 的 YAML 檔案,其中包含稍後修補 Identity Service for GKE ClientConfig 資源時需要的值:

    cat << EOF > client-config-patch.yaml
    spec:
      authentication:
      - name: google-oidc
        oidc:
          clientID: CLIENT_ID
          cloudConsoleRedirectURI: https://console.cloud.google.com/kubernetes/oidc
          extraParams: prompt=consent,access_type=offline
          issuerURI: https://accounts.google.com
          kubectlRedirectURI: http://localhost:10000/callback
          scopes: email
          userClaim: email
          userPrefix: '-'
    EOF
    

    CLIENT_ID 替換為先前步驟中的 OAuth 用戶端 ID。

    請注意修補程式的下列事項:

    • Google OAuth 2.0 驗證系統核發的 ID 憑證,會在 sub (主體) 聲明中包含專屬的數字 ID。在角色繫結中使用這個不透明的 ID,會難以識別角色繫結的主體。因此,這個修補程式會設定 GKE 適用的 Identity Service,使用 ID 權杖中的電子郵件聲明來識別使用者,而非使用預設的子聲明。

    • 新增電子郵件範圍,確保核發的 ID 權杖包含電子郵件聲明。

    • 開發人員使用 GKE 身分識別服務向叢集進行驗證時,系統會使用 cloudConsoleRedirectURIextraParamskubectlRedirectURI 和範圍欄位。當 Google 服務帳戶向叢集進行驗證時,不會使用這些金鑰。kubectlRedirectURI 欄位為必填欄位。

    • userPrefix 欄位是使用已設定識別資訊提供者驗證的使用者前置字元。值為 '-' 表示沒有前置字元。

    • spec.authentication 欄位是陣列。您可以搭配使用多個 OpenID Connect 識別資訊提供者與 GKE 適用的 Identity 服務。舉例來說,您可以將 Google 設為身分提供者,驗證 Google 服務帳戶,並使用其他身分提供者驗證開發人員。

    如要進一步瞭解這項設定中的欄位,請參閱「使用外部識別資訊提供者向 GKE 進行驗證」。

建立 Google 服務帳戶,設定 GKE 適用的 Identity Service

  1. 在 Cloud Shell 中建立 Google 服務帳戶:

    gcloud iam service-accounts create ISG_GSA \
      --display-name "Configure Identity Service for GKE"
    

    ISG_GSA 替換為您要用於 Google 服務帳戶的名稱。在本教學課程中,請使用 identity-service-for-gke

    您會將這個 Google 服務帳戶指派給 Compute Engine VM 執行個體,以便在叢集上設定 GKE 適用的 Identity Service 和 Kubernetes 角色式存取控管。

  2. 將專案的 Kubernetes Engine 管理員角色授予 Google 服務帳戶:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/container.admin
    

    這個角色提供在本教學課程中執行下列工作所需的權限:

    • 在專案中的叢集上,設定 GKE 適用的 Identity Service。
    • 在叢集中建立角色繫結和叢集角色繫結。

設定 GKE 適用的 Identity Service

如要設定 GKE 適用的 Identity Service,您必須有權存取叢集控制層。在本教學課程中,您將建立 Compute Engine VM 執行個體,以便存取控制平面。

您需要 VM 執行個體的 SSH 存取權。如要從 VPC 網路外部,對 VM 執行個體啟用已驗證及授權的 SSH 存取權,請搭配使用 TCP 轉送和 Identity-Aware Proxy (IAP)。這項功能可讓您存取 SSH,不必為 VM 執行個體設定公開 IP 位址。

  1. 在 Cloud Shell 中,建立防火牆規則,允許使用 IAP TCP 轉送功能,透過 SSH 存取具有 ssh-iap 網路標記的任何 VM 執行個體:

    gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
      --allow tcp:22 \
      --description "Allow SSH tunneling using Identity-Aware Proxy" \
      --network NETWORK \
      --source-ranges 35.235.240.0/20 \
      --target-tags ssh-iap
    

    來源範圍包含 IAP 用於 TCP 轉送的 IP 位址。

  2. 在與 GKE 叢集相同的 VPC 網路中建立 Compute Engine VM 執行個體:

    gcloud compute instances create VM \
      --metadata enable-oslogin=TRUE \
      --network NETWORK \
      --no-address \
      --scopes cloud-platform,userinfo-email \
      --service-account ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --subnet SUBNET  \
      --tags ssh-iap \
      --zone ZONE
    

    VM 替換為您要使用的 VM 執行個體名稱。在本教學課程中,請使用 identity-service-for-gke-configuration

    請注意上述指令的下列事項:

    • --service-account 旗標會將 Google 服務帳戶附加至 VM 執行個體。

    • 如要存取 Service Account Credentials API,必須使用 cloud-platform 範圍。

    • userinfo-email 範圍有助於建立 VM 執行個體,以管理 Kubernetes 角色型存取權控管。本教學課程可略過此步驟。

    • --no-address 旗標表示建立的 VM 執行個體沒有外部 IP 位址。

    • 選用的 enable-oslogin 執行個體中繼資料值可啟用 VM 執行個體上的 OS 登入。OS 登入功能可讓您使用 IAM 管理 VM 執行個體的 SSH 存取權。

  3. 將 ClientConfig 修補程式檔案複製到 VM 執行個體:

    gcloud compute scp client-config-patch.yaml VM:~ --tunnel-through-iap --zone ZONE
    

    --tunnel-through-iap 旗標會指示 gcloud 透過 IAP 建立連線通道。

  4. 使用 SSH 連線至 VM 執行個體:

    gcloud compute ssh VM --tunnel-through-iap --zone ZONE
    

    您將透過 SSH 工作階段執行本節的其餘指令。

  5. 在 VM 執行個體中安裝 kubectl 指令列工具和 gke-gcloud-auth-plugin 二進位檔

    sudo apt-get install -y kubectl google-cloud-sdk-gke-gcloud-auth-plugin
    
  6. 擷取 GKE 叢集的憑證:

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    gcloud container clusters get-credentials CLUSTER --zone ZONE
    
  7. 修補預設的 ClientConfig 資源:

    kubectl patch clientconfig default \
        --namespace kube-public \
        --patch-file client-config-patch.yaml \
        --type merge
    
  8. 從修補的預設 ClientConfig 資源中擷取 certificateAuthorityData 欄位,並儲存在名為 certificateAuthorityData.pem 的檔案中:

    kubectl get clientconfig default \
         --namespace kube-public \
         --output jsonpath='{.spec.certificateAuthorityData}' \
         | base64 --decode > certificateAuthorityData.pem
    
  9. 從修補的預設 ClientConfig 資源中擷取伺服器欄位,並儲存在名為 server.txt 的檔案中:

    kubectl get clientconfig default \
         --namespace kube-public \
         --output jsonpath='{.spec.server}' > server.txt
    
  10. 離開 SSH 工作階段:

    exit
    

(選用) 驗證叢集設定

繼續操作前,請先確認叢集上的 GKE 專用身分識別服務設定正確無誤。您可以使用附加至 VM 執行個體的 Google 服務帳戶,透過 GKE 適用的 Identity 服務向叢集驗證,藉此驗證設定。

  1. 在 Cloud Shell 中,將 Google 服務帳戶的「服務帳戶 OpenID Connect 身分識別權杖建立者」授予服務帳戶本身:

    gcloud iam service-accounts add-iam-policy-binding \
      ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/iam.serviceAccountOpenIdTokenCreator
    

    這個角色提供 iam.serviceAccounts.getOpenIdToken 權限,可透過 Service Account Credentials API 為服務帳戶要求 ID 權杖。

  2. 使用 SSH 連線至 VM 執行個體:

    gcloud compute ssh VM --tunnel-through-iap --zone ZONE
    

    您將透過 SSH 工作階段執行本節的其餘指令。

  3. 中繼資料伺服器要求 OAuth 2.0 存取權杖,以取得附加至 VM 執行個體的 Google 服務帳戶,並使用 OAuth 用戶端 ID 做為要求的 aud (對象) 聲明:

    ACCESS_TOKEN=$(curl --silent --header "Metadata-Flavor: Google" \
    http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token \
           | python3 -c 'import json, sys; print(json.load(sys.stdin).get("access_token"))')
    

    中繼資料伺服器的回應內文是 JSON 文件。這個指令使用內嵌 Python 指令碼,從回應本文中擷取 access_token 欄位。

  4. 向 Service Account Credentials API 要求附加至 VM 執行個體的 Google 服務帳戶的 ID 權杖

    ID_TOKEN=$(curl --silent --request POST \
        --data '{"audience": "CLIENT_ID", "includeEmail": true}' \
        --header "Authorization: Bearer $ACCESS_TOKEN" \
        --header "Content-Type: application/json; charset=utf-8" \
    "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/ISG_GSA@PROJECT_ID.iam.gserviceaccount.com:generateIdToken" \
           | python3 -c 'import json, sys; print(json.load(sys.stdin).get("token"))')
    

    請注意上述指令的下列事項:

    • 要求主體 JSON 中的 audience 欄位,會指定 ID 權杖要求的 aud (目標對象) 聲明。
    • 上一個步驟中的存取權杖會用於向 API 進行驗證。
  5. 查看 ID 權杖中的聲明:

    echo $ID_TOKEN \
        | cut -d. -f2 \
        | base64 --decode --ignore-garbage 2> /dev/null \
        | python3 -m json.tool
    

    確認 email 聲明包含 Google 服務帳戶的電子郵件地址。

  6. 使用 ID 權杖,透過 GKE 適用的 Identity 服務向控制層進行驗證:

    kubectl get namespaces \
        --certificate-authority certificateAuthorityData.pem \
        --server $(cat server.txt) \
        --token $ID_TOKEN
    

    輸出結果會與下列內容相似:

      Error from server (Forbidden): namespaces is forbidden: User "ISG_GSA@PROJECT_ID.iam.gserviceaccount.com" cannot list resource "namespaces" in API group "" at the cluster scope
    

    這是預期中的錯誤。雖然 Google 服務帳戶已在專案的 GKE 叢集上獲得 IAM 權限,但使用 GKE 適用的 Identity Service 進行驗證時,IAM 權限不會生效。而是使用 Kubernetes 角色型存取控制 (RBAC) 設定存取權。

  7. 建立叢集角色繫結,在服務帳戶使用 Google 的 OpenID Connect 供應商向叢集進行驗證時,將 view 叢集角色授予 Google 服務帳戶:

    kubectl create clusterrolebinding ISG_GSA-cluster-view \
        --clusterrole view \
        --user ISG_GSA@PROJECT_ID.iam.gserviceaccount.com
    

    如果您在自己環境的 ClientConfig 中設定 userPrefix 值 (而非 -),請將前置字元新增至這個指令中 --user 旗標的值。

  8. 使用 GKE 適用的 Identity Service 存取 GKE 叢集:

    kubectl get namespaces \
        --certificate-authority certificateAuthorityData.pem \
        --server $(cat server.txt) \
        --token $ID_TOKEN
    

    輸出結果會與下列內容相似:

    NAME                      STATUS   AGE
    anthos-identity-service   Active   1h
    default                   Active   1h
    kube-node-lease           Active   1h
    kube-public               Active   1h
    kube-system               Active   1h
    
  9. 離開 SSH 工作階段:

    exit
    

kubectl 工具建立內容

kubectl 指令可使用 kubeconfig 檔案設定叢集存取權。kubeconfig 檔案包含一或多個環境。每個內容都有名稱,並可視需要包含叢集連線資訊、用於向叢集驗證的憑證,以及預設命名空間。

在本節中,您將建立含有內容的 kubeconfig 檔案。內容包括叢集的 GKE Identity Service Proxy 連線詳細資料。您不會在 kubeconfig 檔案中新增任何使用者憑證。

  1. 在 Cloud Shell 中,將含有憑證授權單位資料和伺服器網址的檔案從 VM 執行個體複製到目前目錄:

    gcloud compute scp VM:~/certificateAuthorityData.pem VM:~/server.txt . \
        --tunnel-through-iap --zone ZONE
    
  2. 建立內容和叢集設定,稍後將用於從 Cloud Build 連線至 GKE 叢集:

    kubectl config set-context private-cluster \
        --cluster private-cluster \
        --kubeconfig kubeconfig
    

    --kubeconfig 旗標會在目前目錄中,建立名為 kubeconfig 的新檔案,並在其中建立內容和叢集設定。

    這個指令會使用 GKE 叢集名稱做為環境的叢集設定名稱。在您自己的環境中,您可以在內容中使用不同的叢集設定名稱。

  3. 在叢集設定中設定 certificateAuthorityData 欄位:

    kubectl config set-cluster private-cluster \
        --certificate-authority certificateAuthorityData.pem \
        --embed-certs \
        --kubeconfig kubeconfig
    
  4. 在叢集設定中設定 server 欄位:

    kubectl config set-cluster private-cluster \
        --kubeconfig kubeconfig \
        --server $(cat server.txt)
    

為 Cloud Build 建立 Google 服務帳戶

  1. 在 Cloud Shell 中建立 Google 服務帳戶,以便在 Cloud Build 私人集區中執行建構作業:

    gcloud iam service-accounts create CB_GSA \
      --description "Runs builds on Cloud Build private pools" \
      --display-name "Cloud Build private pool"
    

    CB_GSA 替換為您要用於 Google 服務帳戶的名稱。在本教學課程中,請使用 cloud-build-private-pool

  2. 將專案的 Cloud Build 服務帳戶角色授予 Google 服務帳戶:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudbuild.builds.builder
    

    這個角色提供 Google 代管 Cloud Build 服務帳戶的預設權限

  3. 將 Google 服務帳戶的「服務帳戶 OpenID Connect 身分識別權杖建立者」授予服務帳戶本身:

    gcloud iam service-accounts add-iam-policy-binding \
        CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.serviceAccountOpenIdTokenCreator
    

    這個角色提供 iam.serviceAccounts.getOpenIdToken 權限,可透過 Service Account Credentials API 為服務帳戶要求 ID 權杖。

  4. 使用 SSH 連線至 VM 執行個體:

    gcloud compute ssh VM --tunnel-through-iap --zone ZONE
    

    您將透過 SSH 工作階段執行本節的其餘指令。

  5. 在 SSH 工作階段中,建立 Kubernetes 叢集角色繫結,在服務帳戶使用 Google 的 OpenID Connect 提供者向叢集驗證時,將 cluster-admin 叢集角色授予 Google 服務帳戶:

    kubectl create clusterrolebinding CB_GSA-cluster-admin \
        --clusterrole cluster-admin \
        --user CB_GSA@PROJECT_ID.iam.gserviceaccount.com
    

    cluster-admin 叢集角色會授予廣泛的叢集層級權限。在您自己的環境中,可以使用叢集角色,只提供 Cloud Build 執行工作所需的權限。您也可以使用角色繫結,只授予特定命名空間的權限。

    如果您在自家環境的 ClientConfig 中設定 userPrefix,就必須將該前置字串新增至這個指令中 --user 標記的值。

  6. 離開 SSH 工作階段:

    exit
    

建立 Cloud Build 私人集區

  1. 在 Cloud Shell 中,為與私人集區的連線,在 VPC 網路中分配 IP 位址範圍:

    gcloud compute addresses create RESERVED_RANGE_NAME \
    --addresses RESERVED_RANGE_START_IP\
        --description "Cloud Build private pool reserved range" \
        --global \
        --network NETWORK \
        --prefix-length RESERVED_RANGE_PREFIX_LENGTH \
        --purpose VPC_PEERING
    

    更改下列內容:

    • RESERVED_RANGE_NAME:用於代管 Cloud Build 私人集區的已分配 IP 位址範圍名稱。在本教學課程中,請使用 cloud-build-private-pool
    • RESERVED_RANGE_START_IP:分配 IP 位址範圍的第一個 IP 位址。在本教學課程中,請使用 192.168.12.0
    • RESERVED_RANGE_PREFIX_LENGTH:已分配 IP 位址範圍的前置長度 (子網路遮罩)。前置字串長度必須為 /23 或更小的數字,例如 /22/21。數字越小,位址範圍越大。在本教學課程中,請使用 23,且不要輸入開頭的 / (斜線)。
  2. 建立防火牆規則,允許來自保留 IP 位址範圍的傳入流量,傳向虛擬私有雲網路中的其他資源:

    gcloud compute firewall-rules create allow-private-pools-ingress \
        --allow all \
        --network NETWORK \
        --source-ranges RESERVED_RANGE_START_IP/RESERVED_RANGE_PREFIX_LENGTH
    
  3. 建立私人服務連線,將虛擬私有雲網路連線至 Service Networking 服務:

    gcloud services vpc-peerings connect \
        --network NETWORK \
        --ranges RESERVED_RANGE_NAME \
        --service servicenetworking.googleapis.com
    

    Cloud Build 私人集區會使用服務聯網執行工作站。透過虛擬私有雲網路對等互連連線,虛擬私有雲網路可使用已分配的內部 IP 位址範圍,與私人集區通訊。

    建立私人服務連線可能需要幾分鐘的時間。

    如果您在自己的環境中使用共用虛擬私有雲,如要瞭解建立私有服務連線的其他步驟,請參閱「設定環境」。

  4. 在與虛擬私有雲網路對等互連的 Google 擁有虛擬私有雲網路中,建立 Cloud Build 私人集區:

    gcloud builds worker-pools create PRIVATE_POOL_NAME \
       --no-public-egress \
       --peered-network projects/PROJECT_ID/global/networks/NETWORK \
       --region REGION
    

    更改下列內容:

    • PRIVATE_POOL_NAME:私人集區的名稱。在本教學課程中,請使用 private-pool
    • REGION:私人集區使用的區域。在本教學課程中,請使用 us-central1

    --no-public-egress 旗標表示私人集區中的工作站沒有公開 IP 位址。在您自己的環境中,如果希望私人集區中的工作站使用公開 IP 位址連線至網際網路,可以移除這個旗標。

    如要瞭解其他設定選項,例如私人集區中工作站的機器類型和磁碟大小,請參閱「建立及管理私人集區」。

檢查問題是否已經順利解決

在本節中,您將在 Cloud Build 私人集區中執行建構作業,驗證解決方案。建構作業會存取私人 GKE 叢集。

  1. 在 Cloud Shell 中,建立 Cloud Storage bucket 來儲存 Cloud Build 的建構作業記錄:

    gcloud storage buckets create gs://PROJECT_ID-build-logs --location=REGION
    
  2. 為 Cloud Build 建立建構設定檔

    cat << "EOF" > cloudbuild.yaml
    steps:
    - id: list-services
      name: gcr.io/google.com/cloudsdktool/google-cloud-cli
      entrypoint: bash
      args:
      - -eEuo
      - pipefail
      - -c
      - |-
        kubectl config use-context $_KUBECTL_CONTEXT
    
        ACCESS_TOKEN=$$(curl --silent \
            --header "Metadata-Flavor: Google" \
            http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token \
            | python3 -c 'import json, sys; print(json.load(sys.stdin).get("access_token"))')
    
        ID_TOKEN=$$(curl --silent --request POST \
            --data '{"audience": "CLIENT_ID", "includeEmail": true}' \
            --header "Authorization: Bearer $$ACCESS_TOKEN" \
            --header "Content-Type: application/json; charset=utf-8" \
            "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$_SERVICE_ACCOUNT:generateIdToken" \
            | python3 -c 'import json, sys; print(json.load(sys.stdin).get("token"))')
    
        kubectl get services --namespace $_NAMESPACE --token $$ID_TOKEN
    
    logsBucket: gs://PROJECT_ID-build-logs
    
    options:
      env:
      - KUBECONFIG=/workspace/$_KUBECONFIG
    
    substitutions:
      _KUBECONFIG: kubeconfig
      _KUBECTL_CONTEXT: private-cluster
      _NAMESPACE: default
    
    serviceAccount: projects/$PROJECT_ID/serviceAccounts/$_SERVICE_ACCOUNT
    EOF
    

    建構設定檔中的步驟會執行下列動作:

    1. 切換至 _KUBECTL_CONTEXT 替代項目指定的 kubectl 環境。預設替代值為 private-cluster

    2. 從中繼資料伺服器擷取存取權杖。存取權杖會核發給執行建構作業的 Google 服務帳戶。

    3. 使用 Service Account Credentials API 產生 ID 權杖。系統會使用存取權杖驗證產生 ID 權杖的要求。ID 權杖要求的 aud (對象) 聲明是 _CLIENT_ID 替代項目指定的 OAuth 2.0 用戶端 ID。

    4. 列出 _NAMESPACE 替代項目所指定命名空間中的 Kubernetes 服務。預設替代值為 default。系統會使用上一個指令產生的 ID 權杖驗證要求。

    請注意建構設定檔的下列事項:

    • $ 字元是替代的前置字元。$$ 用於 bash 參數擴充和指令替代。

    • 您可以在執行建構作業時,透過 _KUBECONFIG_KUBECTL_CONTEXT 替換項目指定不同的 kubeconfig 檔案和環境。透過這些替代項目,您可以使用含有多個環境的單一 kubeconfig 檔案,或使用多個 kubeconfig 檔案,管理多個叢集設定。

    • 替代 _SERVICE_ACCOUNT 沒有預設值。執行建構時,您必須提供這個替代項的值。

    • options 區塊會為建構中的所有步驟設定 KUBECONFIG 環境變數。

    • 建構步驟會使用 gcr.io/google.com/cloudsdktool/google-cloud-cli 建構工具映像檔。這個容器映像檔很大,從登錄檔提取至私人集區工作站需要一些時間。如要縮短提取建構工具映像檔的時間,可以建立自訂建構工具映像檔,其中只包含建構步驟所需的工具,例如 curlkubectl 和 Python。

    如要進一步瞭解建構設定檔中的內嵌 Shell 指令碼,請參閱「執行 Bash 指令碼」。

  3. 使用建構設定檔和目前目錄中的檔案執行建構作業:

    gcloud builds submit \
        --config cloudbuild.yaml \
        --region REGION \
        --substitutions _SERVICE_ACCOUNT=CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --worker-pool projects/PROJECT_ID/locations/REGION/workerPools/PRIVATE_POOL_NAME
    

    這項指令會將目前目錄中的所有檔案上傳至 Cloud Storage,供 Cloud Build 使用。建構步驟會使用 kubeconfig 檔案連線至 GKE 叢集。

    在輸出內容的結尾附近,您會看到類似下列內容的幾行:

    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   2h
    

    這項輸出內容顯示,私人集區工作站已透過 GKE 適用的 Identity 服務驗證 Proxy 連線至叢集控制層。

疑難排解

如果無法使用 SSH 連線至 VM 執行個體,請新增 --troubleshoot 旗標,找出連線問題的原因:

gcloud compute ssh VM --tunnel-through-iap --zone ZONE --troubleshoot

如果在修補 GKE 叢集上的預設 ClientConfig 時收到 Error from server (NotFound): clientconfigs.authentication.gke.io "default" not found 訊息,請確認您已按照「建立私人 GKE 叢集」一節所述建立防火牆規則。確認防火牆規則是否存在:

gcloud compute firewall-rules describe allow-control-plane-clientconfig-webhook

如果無法向 GKE 適用的 Identity 服務 Proxy 進行驗證,請在 gke-oidc-service 部署作業的 Pod 記錄中尋找錯誤:

gcloud compute ssh VM --tunnel-through-iap --zone ZONE --command \
    'kubectl logs deployment/gke-oidc-service \
         --namespace anthos-identity-service --all-containers'

如果您在本教學課程中遇到其他問題,建議查看下列文件:

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。

刪除專案

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

刪除資源

如要保留您在本教學課程中使用的專案,請刪除個別的資源:

  1. 在 Cloud Shell 中刪除 Cloud Build 私人集區:

    gcloud builds worker-pools delete PRIVATE_POOL_NAME --region REGION --quiet
    
  2. 刪除 Service Networking 的私人服務連線:

    gcloud services vpc-peerings delete --network NETWORK \
      --service servicenetworking.googleapis.com --quiet --async
    
  3. 刪除分配給 Cloud Build 私人集區的 IP 位址範圍:

    gcloud compute addresses delete RESERVED_RANGE_NAME --global --quiet
    
  4. 刪除 Cloud Storage bucket 和所有內容:

    gcloud storage rm gs://PROJECT_ID-build-logs --recursive
    
  5. 刪除 GKE 叢集:

    gcloud container clusters delete CLUSTER --zone ZONE --quiet --async
    
  6. 刪除 Compute Engine VM 執行個體:

    gcloud compute instances delete VM --zone ZONE --quiet
    
  7. 刪除防火牆規則:

    gcloud compute firewall-rules delete allow-private-pools-ingress --quiet
    
    gcloud compute firewall-rules delete allow-ssh-ingress-from-iap --quiet
    
    gcloud compute firewall-rules delete allow-control-plane-clientconfig-webhook --quiet
    
  8. 移除 IAM 角色繫結:

    gcloud projects remove-iam-policy-binding PROJECT_ID \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudbuild.builds.builder
    
    gcloud projects remove-iam-policy-binding PROJECT_ID \
        --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/container.admin
    
    gcloud iam service-accounts remove-iam-policy-binding \
        CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.serviceAccountOpenIdTokenCreator
    
    gcloud iam service-accounts remove-iam-policy-binding \
        ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.serviceAccountOpenIdTokenCreator
    
  9. 刪除 Google 服務帳戶:

    gcloud iam service-accounts delete CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
       --quiet
    
    gcloud iam service-accounts delete ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
       --quiet
    

刪除 OAuth 2.0 用戶端 ID

  1. 前往 Google Cloud 控制台的「憑證」頁面:

    開啟「憑證」頁面

  2. 從專案選取器清單中選取專案。

  3. 在「OAuth 2.0 用戶端 ID」表格中,找到「Identity Service for GKE」的資料列,然後點選「刪除 OAuth 用戶端」圖示。

  4. 在對話方塊中按一下「刪除」

後續步驟