使用 Identity Service for 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 网络对等互连。但是,VPC 网络对等互连不支持传递性对等互连,这可能会在使用 Cloud Build 专用池时受到限制。本教程介绍了一个解决方案,该解决方案使用 Identity Service for GKE 来允许 Cloud Build 专用池中的工作器访问专用 GKE 集群的控制平面。

架构概览

Identity Service for GKE 是 GKE 集群控制平面的身份验证代理。它会将请求代理到 API 服务器,并验证由 OpenID Connect (OIDC) 身份提供商签发的 ID 令牌。代理成功验证 ID 令牌后,会将用户模拟 HTTP 标头添加到原始请求中,并将其转发给 API 服务器。该代理以 Kubernetes 服务账号的身份运行,该账号有权模拟用户和群组。

Identity Service for GKE 代理在集群节点上作为 Pod 运行。LoadBalancer 类型的 Kubernetes 服务在集群外部公开代理。如果在专用集群上启用了 Identity Service for GKE,则安装程序会向 Kubernetes 服务添加注解,以配置内部直通式网络负载平衡器。由于代理在您的 VPC 网络中的集群节点上运行,因此可通过 VPC 网络对等互连连接(例如从 Cloud Build 专用池)通过负载均衡器访问该代理。

您可以在 Identity Service for GKE 中将 Google 配置为 OpenID Connect 身份提供方,因为 Google 的 OAuth 2.0 身份验证系统符合 OpenID Connect 规范。要获取 Google 服务账号的 ID 令牌,您可以使用 Service Account Credentials APIgenerateIdToken 方法。ID 令牌由 Google 颁发并签名。

综上所述,此解决方案允许使用 Identity Service for GKE 代理访问专用 GKE 集群控制平面。在 Cloud Build 专用池上运行的构建通过 VPC 网络对等互连连接连接到代理。在 Cloud Build 专用池上运行的构建以 Google 服务账号身份运行。此 Google 服务账号可以从 Service Account Credentials API 获取 ID 令牌,以便向该代理进行身份验证。

下图显示了上述文本中所述的架构:

使用 Identity Service for GKE 访问专用 GKE 集群

此解决方案中的所有通信均通过内部 IP 地址空间进行。专用池中的工作器不需要公共互联网连接。

当用户账号和 Google 服务账号使用 Identity Service for GKE 进行身份验证时,向他们授予的 Identity and Access Management (IAM) 权限不适用。而是使用 Kubernetes 基于角色的访问权限控制 (RBAC) 来管理这些账号的集群权限。

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 安装 Google Cloud CLI。
  3. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  4. 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.

  5. 确保您的 Google Cloud 项目已启用结算功能

  6. 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
  7. 安装 Google Cloud CLI。
  8. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  9. 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.

  10. 确保您的 Google Cloud 项目已启用结算功能

  11. 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 集群 且安装了 Identity Service for GKE 的控制平面的公共端点的访问权限:

    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_PANE_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_PANE_CIDR:控制平面的 IP 地址范围。它必须具有 /28 前缀。在本教程中,您可以使用 172.16.0.32/28
    • NETWORK:控制平面连接的 VPC 网络。在本教程中,请使用 default
    • SUBNET:GKE 集群控制平面连接到的子网。子网必须属于 NETWORK 指定的 VPC 网络。在本教程中,请使用 default
    • NODE_TAGS:要应用于节点的网络标记的逗号分隔列表。在本教程中,请使用 private-cluster-node
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • ZONE:GKE 集群所在的区域。在本教程中,请使用 us-central1-f

    对于该命令,请注意以下事项:

    • --enable-identity-service 标志在集群上启用 Identity Service for GKE。在您自己的环境中,您可以在现有集群上启用 Identity Service for GKE

    • --enable-private-endpoint 标志将控制平面配置为可访问 只能使用内部 IP 地址

    • --enable-private-nodes 标志将集群节点配置为 内部 IP 地址。

    • --enable-master-authorized-networks--enable-private-nodes 标志 仅允许通过 --network 标志指定的专用网络访问 API 服务器。

    • 可选的 --workload-pool 标志用于启用 Workload Identity。本教程不需要此设置。

  2. 添加一条允许 GKE 集群控制 连接到验证 ClientConfig 资源的准入 webhook:

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

    ClientConfig 是 Kubernetes 自定义资源类型 (CRD),Identity Service for GKE 用于配置 如何与身份提供方进行交互。

将 Identity Service for GKE 注册为 OAuth 2.0 客户端应用

在本部分中,您将使用 Google 的 OAuth 2.0 身份验证系统将 Identity Service for GKE 注册为客户端应用。

  1. 在 Google Cloud 控制台中打开凭据页面。

    打开“凭据”页面

  2. 点击创建凭据

  3. 选择 OAuth 客户端 ID

    如果尚未为 Google Cloud 项目配置同意屏幕,请点击配置同意屏幕。请参阅有关如何配置同意屏幕的文档。在本教程中,请设置以下值:

    • 用户类型可以是内部外部。在本教程中,您可以选择“内部”。
    • “应用名称”“用户支持电子邮件地址”和“开发者联系信息”均为必填值,可以是任意值。
    • 您无需为本教程添加任何范围。

    配置完同意屏幕后,请点击“返回信息中心”,然后从当前流程的第 1 步重新开始操作。

  4. 应用类型列表中,选择 Web 应用

  5. 名称字段中,输入客户端 ID 的名称。在本教程中 请使用 Identity Service for GKE

  6. 点击创建

    系统会显示一个对话框。复制 Your Client ID 的值;在本专精课程稍后的部分中 过程。

  7. 点击 OK 关闭对话框。

  8. 在 Cloud Shell 中,在主目录下创建一个名为 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 令牌在子(主题)声明中包含唯一的数字标识符。在角色绑定中使用此不透明标识符会导致难以识别角色绑定的主题。因此,此补丁会将 Identity Service for GKE 配置为使用 ID 令牌中的电子邮件声明来识别用户,而不是使用默认的子声明。

    • 系统会添加电子邮件范围,以便颁发的 ID 令牌包含电子邮件声明。

    • 开发者使用 Identity Service for GKE 向集群进行身份验证时,会使用 cloudConsoleRedirectURIextraParamskubectlRedirectURI 和范围字段。Google 服务账号向集群进行身份验证时,不会用到这些凭据。kubectlRedirectURI 字段是必填项。

    • userPrefix 字段是使用所配置的身份提供方进行身份验证的用户的前缀。值 '-' 表示无前缀。

    • spec.authentication 字段是一个数组。您可以将多个 OpenID Connect 身份提供方与 Identity Service for GKE 搭配使用。例如,您可以使用 Google 作为身份提供方来验证 Google 服务账号,并使用其他身份提供方对开发者进行身份验证。

    如需详细了解此配置中的字段,请参阅使用外部身份提供方向 GKE 进行身份验证

创建 Google 服务账号以配置 Identity Service for GKE

  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 虚拟机实例,以便在集群上配置 Identity Service for GKE 和 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
    

    此角色提供执行本教程中的以下任务所需的权限:

    • 在项目中的集群上配置 Identity Service for GKE 设置。
    • 在集群中创建角色绑定和集群角色绑定。

配置 Identity Service for GKE

如需配置 Identity Service for GKE,您必须有权访问集群控制平面。在本教程中,您将创建一个 Compute Engine 虚拟机实例来访问控制平面。

您需要通过 SSH 访问虚拟机实例。如需启用从 VPC 网络外部到虚拟机实例的经过身份验证和授权的 SSH 访问,您可以将 TCP 转发与 Identity-Aware Proxy (IAP) 搭配使用。此功能可启用 SSH 访问,而无需虚拟机实例具有公共 IP 地址。

  1. 在 Cloud Shell 中,创建一条允许 SSH 访问的防火墙规则: 将 IAP TCP 转发到具有 ssh-iap 网络标记的任何虚拟机实例:

    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 集群:

    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 替换为您要用于虚拟机实例的名称。在本教程中,请使用 identity-service-for-gke-configuration

    对于上述命令,请注意以下几点:

  3. 将 ClientConfig 补丁文件复制到虚拟机实例:

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

    --tunnel-through-iap 标志指示 gcloud 建立隧道连接 购买 IAP

  4. 使用 SSH 连接到虚拟机实例:

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

    您将在 SSH 会话中运行本部分中的其余命令。

  5. 在虚拟机实例中安装 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
    

(可选)验证集群配置

在继续之前,您可以验证是否已在集群上正确设置 Identity Service for GKE。您进行验证 设置。

  1. 在 Cloud Shell 中,将 Google 服务账号的 Service Account OpenID Connect Identity Token Creator 授予该服务账号本身:

    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 连接到虚拟机实例:

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

    您将在 SSH 会话中运行本部分中的其余命令。

  3. 使用 OAuth 客户端 ID 作为请求的 aud(受众群体)声明,从元数据服务器为附加到虚拟机实例的 Google 服务账号请求 OAuth 2.0 访问令牌

    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 为附加到虚拟机实例的 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. 通过使用 Identity Service for GKE 向控制平面进行身份验证:

    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 权限,但在使用 Identity Service for GKE 进行身份验证时,IAM 权限不适用。您可以改用 Kubernetes 基于角色的访问权限控制 (RBAC) 来配置访问权限。

  7. 创建集群角色绑定,以便在服务账号使用 Google 的 OpenID Connect 提供方向集群进行身份验证时向 Google 服务账号授予 view 集群角色:

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

    如果您在自己的环境中的 ClientConfig 中设置的 userPrefix 值不是 -,请将前缀添加到此命令中的 --user 标志的值。

  8. 使用 Identity Service for GKE 访问 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 文件。上下文包含集群的 Identity Service for GKE 代理的连接详情。您无需向 kubeconfig 文件添加任何用户凭据。

  1. 在 Cloud Shell 中,将包含证书授权机构数据和服务器网址的文件从虚拟机实例复制到当前目录:

    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 服务账号的 Service Account OpenID Connect Identity Token Creator 授予服务账号本身:

    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 连接到虚拟机实例:

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

    您将在 SSH 会话中运行本部分中的其余命令。

  5. 在 SSH 会话中,创建一个 Kubernetes 集群角色绑定,以便在服务账号使用 Google 的 OpenID Connect 提供方向集群进行身份验证时,向 Google 服务账号授予 cluster-admin 集群角色:

    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 地址范围到 VPC 网络中的其他资源的入站流量:

    gcloud compute firewall-rules create allow-private-pools-ingress \
        --allow all \
        --network NETWORK \
        --source-ranges RESERVED_RANGE_START_IP/RESERVED_RANGE_PREFIX_LENGTH
    
  3. 创建专用服务连接,将您的 VPC 网络连接到 Service Networking 服务:

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

    Cloud Build 专用池使用 Service Networking 运行工作器。通过专用服务连接,您的 VPC 网络可以使用 VPC 网络对等互连连接与所分配的内部 IP 地址范围上的专用池进行通信。

    创建专用服务连接可能需要几分钟时间。

    如果您在自己的环境中使用共享 VPC,如需了解创建专用服务连接的其他步骤,请参阅设置您的环境

  4. 在与您的 VPC 网络对等互连的 Google 拥有的 VPC 网络中创建 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 专用池上运行构建来验证该解决方案。build 访问专用 GKE 集群。

  1. 在 Cloud Shell 中,创建一个 Cloud Storage 存储桶来存储来自 Cloud Build 的构建日志:

    gcloud storage buckets create gs://PROJECT_ID-build-logs --location=REGION
    
  2. 为 Cloud Build 创建 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
    

    build 配置文件中的步骤将执行以下操作:

    1. 切换到由 _KUBECTL_CONTEXT 替换指定的 kubectl 上下文。默认替换值为 private-cluster

    2. 从元数据服务器检索访问令牌。系统会将该访问令牌颁发给运行 build 的 Google 服务账号。

    3. 使用 Service Account Credentials API 生成 ID 令牌。使用访问令牌对生成 ID 令牌的请求进行身份验证。所请求的 ID 令牌的 aud(受众群体)声明是 _CLIENT_ID 替换指定的 OAuth 2.0 客户端 ID。

    4. 列出替代 _NAMESPACE 指定的命名空间中的 Kubernetes 服务。默认替换值为 default。系统使用在上一个命令中生成的 ID 令牌对请求进行身份验证。

    关于 build 配置文件,请注意以下几点:

    • $ 字符是 substitutions 的前缀。$$ 用于 bash 参数扩展和命令替换。

    • 借助替代变量 _KUBECONFIG_KUBECTL_CONTEXT,您可以在运行构建时指定不同的 kubeconfig 文件和不同的上下文。通过这些替代变量,您可以使用带有多个上下文的单个 kubeconfig 文件或使用多个 kubeconfig 文件来管理多个集群配置。

    • 替代变量 _SERVICE_ACCOUNT 没有默认值。在运行构建时,您必须为此替换提供值。

    • options 代码块为构建中的所有步骤设置 KUBECONFIG 环境变量。

    • 构建步骤使用 gcr.io/google.com/cloudsdktool/google-cloud-cli 构建器映像。这是一个大型容器映像,需要一些时间将其从注册表拉取到专用池工作器。为了缩短拉取构建器映像的时间,您可以创建自定义构建器映像,其中仅包含构建步骤所需的工具(例如 curlkubectl 和 Python)。

    如需详细了解 build 配置文件中的内嵌 Shell 脚本,请参阅运行 bash 脚本

  3. 使用 build 配置文件和当前目录中的文件运行 build:

    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
    

    此输出显示,专用池工作器已使用 Identity Service for GKE 身份验证代理连接到集群控制平面。

问题排查

如果您无法使用 SSH 连接到虚拟机实例,请添加 --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

如果您无法向 Identity Service for GKE 代理进行身份验证,请在 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 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

    删除 Google Cloud 项目:

    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 存储桶及其所有内容:

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

    gcloud container clusters delete CLUSTER --zone ZONE --quiet --async
    
  6. 删除 Compute Engine 虚拟机实例:

    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. 在该对话框中,点击删除

后续步骤