本教程介绍如何使用 Cloud Build 专用池访问专用 Google Kubernetes Engine (GKE) 集群的控制平面。此访问权限可让您使用 Cloud Build 在专用 GKE 集群上部署应用和管理资源。本教程适用于平台管理员、集群管理员和开发者。本文假定您熟悉 GKE、Cloud Build、OpenID Connect 和 gcloud
命令行工具。
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 API API 的 generateIdToken
方法。ID 令牌由 Google 颁发并签名。
综上所述,此解决方案允许使用 Identity Service for GKE 代理访问专用 GKE 集群控制平面。在 Cloud Build 专用池上运行的构建通过 VPC 网络对等互连连接连接到代理。在 Cloud Build 专用池上运行的构建以 Google 服务账号身份运行。此 Google 服务账号可以从 Service Account Credentials API 获取 ID 令牌,以便向该代理进行身份验证。
下图展示了前文中介绍的架构:
此解决方案中的所有通信均通过内部 IP 地址空间进行。专用池中的工作器不需要公共互联网连接。
在用户账号和 Google 服务账号使用 Identity Service for GKE 进行身份验证时,向其授予的 Identity and Access Management (IAM) 权限不适用。而是使用 Kubernetes 基于角色的访问权限控制 (RBAC) 来管理这些账号的集群权限。
准备工作
- 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.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
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.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
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 - Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
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.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
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 集群
在 Cloud Shell 中,创建一个对控制层面公共端点没有客户端访问权限且安装了 GKE Identity Service 的 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
标志用于启用适用于 GKE 的工作负载身份联合。本教程不需要此设置。
- CLUSTER:集群的名称。 在本教程中,请使用
添加一条允许 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 用于配置 如何与身份提供方进行交互。
将 GKE Identity Service 注册为 OAuth 2.0 客户端应用
在本部分中,您将使用 Google 的 OAuth 2.0 身份验证系统将 Identity Service for GKE 注册为客户端应用。
在 Google Cloud 控制台中打开凭据页面。
点击创建凭据。
选择 OAuth 客户端 ID。
如果尚未为 Google Cloud 项目配置同意屏幕,请点击配置同意屏幕。请参阅有关配置意见征求屏幕的文档。在本教程中,请设置以下值:
- 用户类型可以是内部或外部。在本教程中,您可以选择“内部”。
- “应用名称”“用户支持电子邮件地址”和“开发者联系信息”均为必填值,可以是任意值。
- 在本教程中,您无需添加任何镜重。
配置完同意屏幕后,请点击“返回信息中心”,然后从当前流程的第 1 步重新开始操作。
在应用类型列表中,选择 Web 应用。
在名称字段中,输入客户端 ID 的名称。在本教程中 请使用
Identity Service for GKE
。点击创建。
系统会显示一个对话框。复制您的客户 ID 的值;您稍后将在此过程中用到此值。
点击 OK 关闭对话框。
在 Cloud Shell 中,在主目录下创建一个名为
cloud-build-private-pools-gke-tutorial
的目录,然后前往该目录:mkdir -p ~/cloud-build-private-pools-gke-tutorial cd ~/cloud-build-private-pools-gke-tutorial
在新目录中,创建一个名为
client-config-patch.yaml
的 YAML 文件,其中包含您稍后为 GKE ClientConfig 资源修补 Identity Service 所需的值: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 令牌在子(主体)声明中包含唯一的数字标识符。在角色绑定中使用此不透明标识符会导致难以识别角色绑定的主题。因此,此补丁会将 GKE Identity Service 配置为使用 ID 令牌中的电子邮件声明来识别用户,而不是使用默认的子声明。
添加电子邮件范围,使颁发的 ID 令牌包含电子邮件声明。
当开发者使用 Identity Service for GKE 对集群进行身份验证时,会使用
cloudConsoleRedirectURI
、extraParams
、kubectlRedirectURI
和 scopes 字段。当 Google 服务账号向集群进行身份验证时,不会使用这些凭据。kubectlRedirectURI 字段是必填项。userPrefix
字段是使用配置的身份提供程序进行身份验证的用户的前缀。值'-'
表示无前缀。spec.authentication
字段是一个数组。您可以将多个 OpenID Connect 身份提供方与 Identity Service for GKE 搭配使用。例如,您可以使用 Google 作为身份提供方来验证 Google 服务账号,并使用其他身份提供方对开发者进行身份验证。
如需详细了解此配置中的字段,请参阅使用外部身份提供方向 GKE 进行身份验证。
创建一个 Google 服务账号以配置 Identity Service for GKE
在 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 基于角色的访问权限控制。
向 Google 服务账号授予项目的 Kubernetes Engine 管理员角色:
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
如需配置 GKE Identity Service,您必须有权访问集群控制平面。在本教程中,您将创建一个 Compute Engine 虚拟机实例来访问控制平面。
您需要通过 SSH 访问虚拟机实例。如需启用从 VPC 网络外部到虚拟机实例的经过身份验证和授权的 SSH 访问,您可以将 TCP 转发与 Identity-Aware Proxy (IAP) 搭配使用。此功能可启用 SSH 访问,而无需虚拟机实例具有公共 IP 地址。
在 Cloud Shell 中,创建一个防火墙规则,允许使用 IAP TCP 转发对具有
ssh-iap
网络标记的任何虚拟机实例进行 SSH 访问: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 地址。
在 GKE 集群所在的同一 VPC 网络中创建 Compute Engine 虚拟机实例:
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
。对于上述命令,请注意以下几点:
--service-account
标志用于将 Google 服务账号连接到虚拟机实例。您必须拥有
cloud-platform
范围才能访问 Service Account Credentials API。在创建用于管理 Kubernetes 基于角色的访问控制的虚拟机实例时,
userinfo-email
范围非常有用。在本教程中,此步骤是可选的。--no-address
标志表示虚拟机实例在没有外部 IP 地址的情况下创建。可选的
enable-oslogin
实例元数据值可在虚拟机实例上启用 OS Login。OS Login 支持使用 IAM 管理对虚拟机实例的 SSH 访问。
将 ClientConfig 补丁文件复制到虚拟机实例:
gcloud compute scp client-config-patch.yaml VM:~ --tunnel-through-iap --zone ZONE
--tunnel-through-iap
标志指示gcloud
建立隧道连接 购买 IAP使用 SSH 连接到虚拟机实例:
gcloud compute ssh VM --tunnel-through-iap --zone ZONE
您可以在 SSH 会话中运行本部分中的其余命令。
在虚拟机实例中安装
kubectl
命令行工具和 gke-gcloud-auth-plugin 二进制文件:sudo apt-get install -y kubectl google-cloud-sdk-gke-gcloud-auth-plugin
提取 GKE 集群的凭据:
export USE_GKE_GCLOUD_AUTH_PLUGIN=True gcloud container clusters get-credentials CLUSTER --zone ZONE
修补默认的 ClientConfig 资源:
kubectl patch clientconfig default \ --namespace kube-public \ --patch-file client-config-patch.yaml \ --type merge
从已修补的默认 ClientConfig 资源中提取
certificateAuthorityData
字段,并将其存储在名为certificateAuthorityData.pem
的文件中:kubectl get clientconfig default \ --namespace kube-public \ --output jsonpath='{.spec.certificateAuthorityData}' \ | base64 --decode > certificateAuthorityData.pem
从已修补的默认 ClientConfig 资源中提取 server 字段,并将其存储在名为
server.txt
的文件中:kubectl get clientconfig default \ --namespace kube-public \ --output jsonpath='{.spec.server}' > server.txt
退出 SSH 会话:
exit
(可选)验证集群配置
在继续操作之前,您可以验证 GKE Identity Service 是否已在集群上正确设置。您进行验证 设置。
在 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 令牌所必需的。使用 SSH 连接到虚拟机实例:
gcloud compute ssh VM --tunnel-through-iap --zone ZONE
您可以在 SSH 会话中运行本部分中的其余命令。
为关联到虚拟机实例的 Google 服务账号从元数据服务器请求 OAuth 2.0 访问令牌,并使用 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
字段。通过 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 进行身份验证。
- 请求正文 JSON 中的
查看 ID 令牌中的声明:
echo $ID_TOKEN \ | cut -d. -f2 \ | base64 --decode --ignore-garbage 2> /dev/null \ | python3 -m json.tool
验证
email
声明是否包含 Google 服务账号的电子邮件地址。使用 Identity Service for GKE 通过 ID 令牌向控制平面进行身份验证:
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 身份服务进行身份验证时,IAM 权限不适用。您可以改用 Kubernetes 基于角色的访问权限控制 (RBAC) 来配置访问权限。
创建一个集群角色绑定,以便在 Google 服务账号使用 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
标志的值。使用 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
退出 SSH 会话:
exit
为 kubectl
工具创建上下文
kubectl
命令可以使用 kubeconfig 文件来配置对集群的访问权限。一个 kubeconfig 文件包含一个或多个上下文。每个上下文都有一个名称,并且可以选择包含集群连接信息、用于向集群进行身份验证的凭据以及默认命名空间。
在本部分中,您将创建一个具有上下文的 kubeconfig 文件。上下文包括集群的 Identity Service for GKE 代理的连接详细信息。您无需向 kubeconfig 文件添加任何用户凭据。
在 Cloud Shell 中,将包含证书颁发机构数据和服务器网址的文件从虚拟机实例复制到当前目录:
gcloud compute scp VM:~/certificateAuthorityData.pem VM:~/server.txt . \ --tunnel-through-iap --zone ZONE
创建上下文和集群配置,以便稍后从 Cloud Build 连接到 GKE 集群:
kubectl config set-context private-cluster \ --cluster private-cluster \ --kubeconfig kubeconfig
--kubeconfig
标志在当前目录中名为 kubeconfig 的新文件中创建上下文和集群配置。此命令会将 GKE 集群名称用作上下文的集群配置名称。在您自己的环境中,您可以在上下文中使用其他集群配置名称。
在集群配置中设置
certificateAuthorityData
字段:kubectl config set-cluster private-cluster \ --certificate-authority certificateAuthorityData.pem \ --embed-certs \ --kubeconfig kubeconfig
在集群配置中设置
server
字段:kubectl config set-cluster private-cluster \ --kubeconfig kubeconfig \ --server $(cat server.txt)
为 Cloud Build 创建 Google 服务账号
在 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
。将项目的 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 服务账号的 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 令牌所必需的。使用 SSH 连接到虚拟机实例:
gcloud compute ssh VM --tunnel-through-iap --zone ZONE
您将在 SSH 会话中运行本部分中的其余命令。
在 SSH 会话中,创建一个 Kubernetes 集群角色绑定,以便在 Google 服务账号使用 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
标志值中添加该前缀。退出 SSH 会话:
exit
创建 Cloud Build 专用池
在 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
,不要输入开头的/
(正斜线)。
- RESERVED_RANGE_NAME:为托管 Cloud Build 专用池而分配的 IP 地址范围的名称。在本教程中,请使用
创建防火墙规则,以允许从预留 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
创建专用服务连接,将您的 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 网络对等互连的 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 地址连接到互联网,可以移除此标志。如需了解其他配置选项(例如专用池中工作器的机器类型和磁盘大小),请参阅创建和管理专用池。
- PRIVATE_POOL_NAME:专用池的名称。在本教程中,请使用
验证解决方案
在本部分中,您将在 Cloud Build 专用池上运行构建作业来验证解决方案。build 会访问专用 GKE 集群。
在 Cloud Shell 中,创建一个 Cloud Storage 存储桶来存储来自 Cloud Build 的构建日志:
gcloud storage buckets create gs://PROJECT_ID-build-logs --location=REGION
为 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 配置文件中的步骤将执行以下操作:
切换到由
_KUBECTL_CONTEXT
替换指定的kubectl
上下文。默认替换值为private-cluster
。从元数据服务器检索访问令牌。系统会将访问令牌颁发给运行 build 的 Google 服务账号。
使用 Service Account Credentials API 生成 ID 令牌。系统会使用访问令牌对生成 ID 令牌的请求进行身份验证。所请求的 ID 令牌的
aud
(受众群体)声明是_CLIENT_ID
替换指定的 OAuth 2.0 客户端 ID。列出替代
_NAMESPACE
指定的命名空间中的 Kubernetes 服务。默认替换值为default
。系统会使用上一个命令中生成的 ID 令牌对请求进行身份验证。
请注意关于构建配置文件的以下事项:
$
字符是 substitutions 的前缀。$$
用于 bash 参数扩展和命令替换。通过替换项
_KUBECONFIG
和_KUBECTL_CONTEXT
,您可以在运行 build 时指定不同的 kubeconfig 文件和不同的上下文。借助这些替换项,您可以使用包含多个上下文的单个 kubeconfig 文件或多个 kubeconfig 文件来管理多个集群配置。替代变量
_SERVICE_ACCOUNT
没有默认值。运行 build 时,您必须为此替换项提供值。options
块会为构建中的所有步骤设置KUBECONFIG
环境变量。构建步骤使用
gcr.io/google.com/cloudsdktool/google-cloud-cli
构建器映像。这是一个大型容器映像,从注册表中将其拉取到专用池工作器需要一些时间。为了缩短拉取构建器映像所需的时间,您可以创建自定义构建器映像,其中仅包含构建步骤所需的工具(例如curl
、kubectl
和 Python)。
如需详细了解 build 配置文件中的内嵌 Shell 脚本,请参阅运行 bash 脚本。
使用 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
此输出显示,专用池工作器已使用 GKE 身份验证代理的 Identity Service 连接到集群控制平面。
问题排查
如果您无法使用 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
如果您无法对 GKE 代理的 Identity Service 进行身份验证,请在 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
删除资源
如果您希望保留在本教程中使用的项目,请逐个删除资源:
在 Cloud Shell 中,删除 Cloud Build 专用池:
gcloud builds worker-pools delete PRIVATE_POOL_NAME --region REGION --quiet
删除与 Service Networking 的专用服务连接:
gcloud services vpc-peerings delete --network NETWORK \ --service servicenetworking.googleapis.com --quiet --async
删除分配给 Cloud Build 专用池的 IP 地址范围:
gcloud compute addresses delete RESERVED_RANGE_NAME --global --quiet
删除 Cloud Storage 存储桶及其所有内容:
gcloud storage rm gs://PROJECT_ID-build-logs --recursive
删除 GKE 集群:
gcloud container clusters delete CLUSTER --zone ZONE --quiet --async
删除 Compute Engine 虚拟机实例:
gcloud compute instances delete VM --zone ZONE --quiet
删除防火墙规则:
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
移除 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
删除 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
前往 Google Cloud 控制台中的凭据页面:
从项目选择器列表中选择您的项目。
在 OAuth 2.0 客户端 ID 表格中,找到 Identity Service for GKE 行,然后点击删除 OAuth 客户端图标。
在该对话框中,点击删除。
后续步骤
- 了解如何使用 Connect 网关从 Cloud Build 访问 Anthos 集群。
- 了解如何使用 Cloud VPN 通过 Cloud Build 专用池访问专用 GKE 集群。
- 了解如何创建使用网络代理的 GKE 专用集群,以实现控制平面访问。
- 了解如何使用静态外部 IP 地址访问私有网络中的外部资源。
- 探索 GKE Identity Service。借助 GKE Identity Service,您可以跨一组 Anthos 集群管理外部身份提供方身份验证。