本文档介绍了如何在 GKE 舰队管理的集群中为 Google Kubernetes Engine (GKE) 配置托管式工作负载身份。还介绍了如何部署工作负载,以及如何验证工作负载的身份和证书。
为 GKE 设置和使用托管式工作负载身份涉及以下步骤:
Google 管理的工作负载身份池
将集群添加到 GKE 舰队时,舰队会自动创建一个 Google 管理的工作负载身份池,该池充当信任网域的根。Google 管理的工作负载身份池具有以下限制条件:
Google 会完全管理该池,因此您无法创建任何子资源,例如命名空间、身份或身份提供方。
该池只能用于 GKE 工作负载。您无法向该池中添加其他类型的工作负载,例如 Compute Engine 虚拟机。
该池中的所有集群都遵循标准的 Kubernetes 命名空间相同性模型。这意味着该池中的所有集群都具有同等权限。在该池中任何集群上运行的工作负载都可以使用该池中的任何身份。
多项目配置
您在本文档中使用的Trusted Cloud 资源(例如 GKE 集群、根 CA 和从属 CA)可以位于不同的项目中。在引用这些资源时,请使用 --project
标志为每种资源指定正确的项目。
准备工作
Create or select a Trusted Cloud project.
-
Create a Trusted Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Trusted Cloud project you are creating. -
Select the Trusted Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Trusted Cloud project name.
-
了解托管式工作负载身份。
确保您至少有一个 GKE 集群。确保您的集群运行的是 1.33.0-gke.2248000 或更高版本。
将集群添加到 GKE 舰队。如果您的集群是 Autopilot 集群,请省略
--enable-workload-identity
。舰队会自动创建一个 Google 管理的工作负载身份池,该池充当信任网域。运行以下命令以启用 GKE 舰队:
gcloud container clusters update CLUSTER_NAME \ --workload-pool=PROJECT_ID.svc.id.goog \ --enable-fleet \ --fleet-project=PROJECT_ID
替换以下内容:
CLUSTER_NAME
:您要向 GKE 舰队注册的 GKE 集群的名称PROJECT_ID
:GKE 舰队宿主项目 ID
Enable the IAM and Certificate Authority Service APIs:
gcloud services enable cloudresourcemanager.googleapis.com
iam.googleapis.com privateca.googleapis.com 配置 Google Cloud CLI 以使用结算和配额项目。
gcloud config set billing/quota_project PROJECT_ID
将 PROJECT_ID 替换为舰队项目的 ID。
所需的角色
如需获得创建托管式工作负载身份和预配托管式工作负载身份证书所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:
-
创建和配置托管式工作负载身份:IAM Workload Identity Pool Admin (
roles/iam.workloadIdentityPoolAdmin
) -
创建和配置 CA 池:CA Service Admin (
roles/privateca.admin
)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
配置 CA Service,以便为托管式工作负载身份颁发证书
如需为 GKE 配置托管式工作负载身份,您首先需要配置一个证书授权机构 (CA) 以及一个或多个从属 CA。此配置称为 CA 层次结构。
您可以使用 CA Service 池来设置此层次结构。在此层次结构中,从属 CA 池会向您的工作负载颁发 X.509 工作负载身份证书。
配置根 CA 池
如需创建根 CA 池,请执行以下操作:
使用 gcloud privateca pools create
在 Enterprise 层级中创建根 CA 池。此层级用于颁发长期、少量的证书。
gcloud privateca pools create ROOT_CA_POOL_ID \ --location=REGION \ --project=CA_PROJECT_ID \ --tier=enterprise
替换以下内容:
ROOT_CA_POOL_ID
:根 CA 池的唯一 ID。ID 不得超过 64 个字符,并且只能包含小写和大写字母数字字符、下划线或连字符。池 ID 在区域内必须是唯一的。REGION
:根 CA 池所在的区域。CA_PROJECT_ID
:您要在其中创建根 CA 的项目的 ID。
如需详细了解 CA 池、层级和区域,请参阅创建 CA 池。
配置根 CA
使用 gcloud privateca roots create
在根 CA 池中创建根 CA。如果这是根 CA 池中的唯一 CA,系统可能会提示您启用根 CA。
如需创建根 CA,请运行以下命令:
gcloud privateca roots create ROOT_CA_ID \ --pool=ROOT_CA_POOL_ID \ --subject="CN=ROOT_CA_CN, O=ROOT_CA_ORGANIZATION" \ --key-algorithm="KEY_ALGORITHM" \ --max-chain-length=1 \ --location=REGION \ --project=CA_PROJECT_ID \ --auto-enable
替换以下内容:
ROOT_CA_ID
:根 CA 的唯一名称。CA 名称不得超过 64 个字符,并且只能包含小写和大写字母数字字符、下划线或连字符。CA 名称在区域内必须是唯一的。ROOT_CA_POOL_ID
:根 CA 池的 ID。ROOT_CA_CN
:根 CA 的通用名称。ROOT_CA_ORGANIZATION
:根 CA 的组织。KEY_ALGORITHM
:密钥算法,例如ec-p256-sha256
。REGION
:根 CA 池所在的区域。CA_PROJECT_ID
:您在其中创建根 CA 的项目的 ID。
如需详细了解 CA 的 subject
字段,请参阅主体。
您可以选择在根 CA 池中创建其他根 CA。这样做对根 CA 变换可能非常有用。
配置从属 CA
您可以选择配置从属 CA。配置从属 CA 可帮助实现以下目标:
多个证书颁发场景:如果您有多个证书颁发场景,则可以为每个场景创建一个从属 CA。
更好的负载均衡:在 CA 池中添加多个从属 CA 有助于您更好地对证书请求进行负载均衡。
如需创建从属 CA 池和从属 CA,请执行以下操作:
在 DevOps 层级创建从属 CA 池,用于颁发大量、短期的证书。
gcloud privateca pools create SUBORDINATE_CA_POOL_ID \ --location=REGION \ --project=CA_PROJECT_ID \ --tier=devops
替换以下内容:
SUBORDINATE_CA_POOL_ID
:从属 CA 池的唯一 ID。ID 不得超过 64 个字符,并且只能包含小写和大写字母数字字符、下划线或连字符。池 ID 在区域内必须是唯一的。REGION
:要在其中创建从属 CA 池的区域。CA_PROJECT_ID
:您在其中创建从属 CA 的项目的 ID。
如需了解详情,请参阅创建 CA 池。
在从属 CA 池中创建从属 CA。请勿更改默认的基于配置的颁发模式。
gcloud privateca subordinates create SUBORDINATE_CA_ID \ --pool=SUBORDINATE_CA_POOL_ID \ --location=REGION \ --issuer-pool=ROOT_CA_POOL_ID \ --issuer-location=REGION \ --subject="CN=SUBORDINATE_CA_CN, O=SUBORDINATE_CA_ORGANIZATION" \ --key-algorithm="KEY_ALGORITHM" \ --use-preset-profile=subordinate_mtls_pathlen_0 \ --project=CA_PROJECT_ID \ --auto-enable
替换以下内容:
SUBORDINATE_CA_ID
:从属 CA 的唯一名称。名称不得超过 64 个字符,并且只能包含小写和大写字母数字字符、下划线或连字符。池名称在区域内必须是唯一的。SUBORDINATE_CA_POOL_ID
:从属 CA 池的名称。REGION
:从属 CA 池所在的区域。ROOT_CA_POOL_ID
:根 CA 池的 ID。REGION
:根 CA 池的区域。SUBORDINATE_CA_CN
:从属 CA 的通用名称。SUBORDINATE_CA_ORGANIZATION
:从属 CA 颁发组织的名称。KEY_ALGORITHM
:密钥算法,例如ec-p256-sha256
。CA_PROJECT_ID
:您在其中创建从属 CA 的项目的 ID。
如需详细了解 CA 的
subject
字段,请参阅主体。
创建证书颁发配置文件
如需将 CA 绑定到工作负载身份池,CA 需要具有证书颁发配置。(可选)如果您需要工作负载跨多个信任网域进行身份验证,还可以使用信任配置更新池。
如需配置证书颁发配置,请创建证书颁发配置文件。该文件的格式类似于以下内容:
{ "inlineCertificateIssuanceConfig": { "caPools": { "REGION1": "projects/CA_PROJECT_NUMBER1/locations/REGION1/caPools/SUBORDINATE_CA_POOL_ID1", "REGION2": "projects/CA_PROJECT_NUMBER2/locations/REGION2/caPools/SUBORDINATE_CA_POOL_ID2" }, "lifetime": "DURATION", "rotationWindowPercentage": ROTATION_WINDOW_PERCENTAGE, "keyAlgorithm": "ALGORITHM" } }
替换以下内容:
REGION
:CA 所在的区域。CA_PROJECT_NUMBER
:您在其中创建从属 CA 池的项目的编号。如需从 CA_PROJECT_ID 项目获取项目编号,请运行以下命令:gcloud projects describe CA_PROJECT_ID --format="value(projectNumber)"
SUBORDINATE_CA_POOL_ID
:从属 CA 池的名称。ALGORITHM
:可选。用于生成私钥的加密算法。有效值包括ECDSA_P256
(默认值)、ECDSA_P384
、RSA_2048
、RSA_3072
、RSA_4096
。DURATION
:可选。叶证书的有效期(以秒为单位)。该值必须介于 86400(1 天)到 2592000(30 天)之间。如果未指定,则系统会使用默认值 86400(1 天)。已颁发证书的实际有效性也取决于颁发证书的 CA,因为它可能会限制已颁发证书的生命周期。ROTATION_WINDOW_PERCENTAGE
:可选:触发续订时证书生命周期的百分比。值必须介于 50 到 80 之间。默认值为 50。
创建信任配置文件
默认情况下,同一信任网域中的工作负载可以使用托管式工作负载身份相互进行身份验证。如果您希望位于不同信任网域中的工作负载相互进行身份验证,则需要在工作负载身份池中明确声明信任关系。为此,您可以创建一个信任配置文件,其中包含为每个网域提供证书的 inlineTrustConfig
。
信任配置文件包含一组信任锚,托管式工作负载身份会使用这些信任锚来验证对等证书。信任配置文件会将 SPIFFE 信任网域映射到 CA 证书。
如需创建信任配置文件,请执行以下操作:
-
下载证书。
gcloud privateca pools get-ca-certs ROOT_CA_POOL_ID \ --output-file=CERTIFICATE_PATH \ --location=REGION
替换以下内容:
-
ROOT_CA_POOL_ID
:根 CA 池的 ID -
CERTIFICATE_PATH
:要将 PEM 编码的证书输出到的路径 -
REGION
:根 CA 池的区域
-
-
创建一个包含内嵌信任配置的文件,其中带有 PEM 格式的证书。该文件类似于以下内容:
{ "inlineTrustConfig": { "additionalTrustBundles": { "TRUST_DOMAIN_NAME1": { "trustAnchors": [ { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL1\n-----END CERTIFICATE-----" }, { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL2\n-----END CERTIFICATE-----" } ] }, "TRUSTED_DOMAIN_NAME2": { "trustAnchors": [ { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL3\n-----END CERTIFICATE-----" }, { "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL4\n-----END CERTIFICATE-----" } ] } } } }
替换以下内容:
-
TRUST_DOMAIN_NAME
:信任网域名称,格式如下:PROJECT_ID.svc.id.goog
-
CERTIFICATE_MATERIAL
:一组 PEM 格式的 CA 证书,受信任可在信任网域中颁发证书。
-
将 CA 绑定到工作负载身份池
创建 CA 层次结构并为每个 CA 创建证书颁发配置后,您需要将 CA 绑定到工作负载身份池。如需将 CA 绑定到工作负载身份池,您可以使用 CA 的证书颁发配置来更新工作负载身份池。然后,您可以验证该池是否已更新。
更新工作负载身份池
如需更新池,请运行以下命令:
gcloud iam workload-identity-pools update TRUST_DOMAIN_NAME \ --location="global" \ --inline-certificate-issuance-config-file=CIC_JSON_FILE_PATH \ --inline-trust-config-file=TC_JSON_FILE_PATH \ --project=PROJECT_ID
替换以下内容:
TRUST_DOMAIN_NAME
:信任网域的名称,格式如下:PROJECT_ID.svc.id.goog
CIC_JSON_FILE_PATH
:您之前创建的 JSON 格式的证书颁发配置文件 (cic.json
) 的路径。TC_JSON_FILE_PATH
:可选。您之前创建的 JSON 格式的信任配置文件 (tc.json
) 的路径。如果您的工作负载跨不同信任网域进行身份验证,则必须指定此文件。否则,您可以省略--inline-trust-config
。
验证工作负载身份池是否已更新
如需验证工作负载身份池是否已随证书颁发配置和信任配置一起更新,请运行以下命令:
gcloud iam workload-identity-pools describe TRUST_DOMAIN_NAME \ --location="global" \ --project=PROJECT_ID
将 TRUST_DOMAIN_NAME
替换为本文档前面部分用于更新工作负载身份池的信任网域名称。
命令输出类似于以下内容:
inlineCertificateIssuanceConfig: caPools: REGION1: projects/PROJECT_NUMBER1/locations/REGION1/caPools/SUBORDINATE_CA_POOL_ID1, REGION2: projects/PROJECT_NUMBER2/locations/REGION2/caPools/SUBORDINATE_CA_POOL_ID2 keyAlgorithm: ALGORITHM lifetime: DURATION rotationWindowPercentage: ROTATION_WINDOW_PERCENTAGE inlineTrustConfig: additionalTrustBundles: example.com: trustAnchors: - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL1 -----END CERTIFICATE----- - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL2 -----END CERTIFICATE----- myorg.com: trustAnchors: - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL3 -----END CERTIFICATE----- - pemCertificate: |- -----BEGIN CERTIFICATE----- CERTIFICATE_MATERIAL4 -----END CERTIFICATE----- name: PROJECT_ID.svc.id.goog state: ACTIVE
如果命令输出中不存在 inlineCertificateIssuanceConfig
或 inlineTrustConfig
,请验证您是否已正确配置 gcloud CLI 以将正确的项目用于结算和配额。您可能需要更新到较新版本的 gcloud CLI。
授权托管式工作负载身份从 CA 池请求证书
将 CA 绑定到工作负载身份池后,您需要授权托管式工作负载身份从 CA 池请求证书。如需向这些身份授权,请执行以下操作:
将每个从属 CA 池的 CA Service Workload Certificate Requester (
roles/privateca.workloadCertificateRequester
) IAM 角色授予给信任网域。以下gcloud privateca pools add-iam-policy-binding
命令会授权信任网域从 CA Service 证书链请求证书。gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_ID \ --location=REGION \ --role=roles/privateca.workloadCertificateRequester \ --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/name/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog" \ --project=CA_PROJECT_ID
替换以下内容:
SUBORDINATE_CA_POOL_ID
:从属 CA 池的 ID。REGION
:从属 CA 池的区域。PROJECT_NUMBER
:包含 GKE 工作负载身份池的项目的项目编号。如需从
PROJECT_ID
获取PROJECT_NUMBER
,请运行以下命令:gcloud projects describe PROJECT_ID --format="value(projectNumber)"
PROJECT_ID
:GKE 舰队宿主项目的项目 ID。CA_PROJECT_ID
:您在其中创建从属 CA 的项目的 ID。
将从属 CA 池的 CA Service Pool Reader (
roles/privateca.poolReader
) 角色授予给托管式工作负载身份。这将授权托管式工作负载身份从 CA 的证书链获取已签名的 X.509 证书。gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_ID \ --location=REGION \ --role=roles/privateca.poolReader \ --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/name/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog" \ --project=CA_PROJECT_ID
替换以下内容:
SUBORDINATE_CA_POOL_ID
:从属 CA 池的 ID。REGION
:从属 CA 池的区域。PROJECT_NUMBER
:包含 GKE 工作负载身份池的项目的项目编号。PROJECT_ID
:GKE 舰队宿主项目的项目 ID。CA_PROJECT_ID
:您在其中创建从属 CA 的项目的 ID。
部署具有托管式工作负载身份的工作负载
将 CA 池配置为可为托管式工作负载身份颁发证书后,您可以部署具有托管式工作负载身份的工作负载。
本部分介绍如何部署具有托管式工作负载身份的测试工作负载。为此,您需要部署一个 Pod,检查是否已生成凭证,然后查看证书和 SPIFFE ID。
部署 Pod
如需在集群中部署测试 Pod,请执行以下操作:
获取集群凭证。
gcloud container clusters get-credentials CLUSTER_NAME \ --location=CLUSTER_ZONE \ --project=CLUSTER_PROJECT_ID
创建 Kubernetes 命名空间。
kubectl create namespace KUBERNETES_NAMESPACE
部署测试 PodSpec。
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: namespace: KUBERNETES_NAMESPACE name: example-pod spec: containers: - name: main image: debian command: ['sleep', 'infinity'] volumeMounts: - name: fleet-spiffe-credentials mountPath: /var/run/secrets/workload-spiffe-credentials readOnly: true nodeSelector: iam.gke.io/gke-metadata-server-enabled: "true" volumes: - name: fleet-spiffe-credentials csi: driver: podcertificate.gke.io volumeAttributes: signerName: spiffe.gke.io/fleet-svid trustDomain: fleet-project/svc.id.goog EOF
列出工作负载凭证
如需列出工作负载凭证,请运行以下命令。凭证可能需要几分钟才能创建完成。
kubectl exec -it example-pod -n KUBERNETES_NAMESPACE -- ls /var/run/secrets/workload-spiffe-credentials
您应该会看到以下输出内容:
ca_certificates.pem
certificates.pem
private_key.pem
trust_bundles.json
查看证书
如需查看证书,请执行以下操作:
将证书导出到证书文件。
kubectl exec -it example-pod --namespace=KUBERNETES_NAMESPACE -- cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -noout -text > certfile
查看证书文件。
cat certfile
在证书的
X509v3 Subject Alternative Name
属性中,您会看到 SPIFFE ID,其格式如下:spiffe://PROJECT_ID.svc.id.goog/ns/KUBERNETES_NAMESPACE/sa/default
default
引用默认 Kubernetes ServiceAccount。
测试工作负载到工作负载身份验证
如需测试工作负载到工作负载身份验证,请参阅使用 Go 测试 mTLS 身份验证。
代码库中的示例代码会创建客户端和服务器工作负载。您可以使用本文档前面部分生成的证书来测试工作负载之间的双向身份验证。
后续步骤
- 为 GKE 排查托管式工作负载身份问题。
- 详细了解如何创建 CA 池。