本页面介绍了 Workload Identity Federation for GKE,包括其工作原理、启用该功能对 GKE 集群的影响,以及如何在 Identity and Access Management 政策中向 Kubernetes 实体授予角色。在大多数情况下,对于在 GKE 上运行的工作负载,建议使用 Workload Identity Federation for GKE 以安全且易于管理的方式访问 Google Cloud 服务。
本页面适用于需要在 GKE 上管理需要访问其他 Google Cloud 服务的工作负载的安全专家和运维人员。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE Enterprise 用户角色和任务。
在阅读本页面之前,请确保您熟悉以下资源:
- 如需了解其他环境中的工作负载身份联合,请参阅工作负载身份联合。
- 如需启用和使用 Workload Identity Federation for GKE,请参阅从 GKE 工作负载访问 Google Cloud API。
- 如需为舰队中的集群提供工作负载身份联合支持,请使用舰队 Workload Identity。
术语
本页面介绍了 Kubernetes 服务账号与 Identity and Access Management (IAM) 服务账号的区别。
- Kubernetes 服务账号
- Kubernetes 资源,用于为 GKE pod 中运行的进程提供身份。
- IAM 服务账号
- 允许应用对Google Cloud API 进行授权调用的Google Cloud 资源。
什么是适用于 GKE 的工作负载身份联合?
在 GKE 上运行的应用可能需要访问 Google Cloud API,例如 Compute Engine API、BigQuery Storage API 或 Machine Learning API。
借助 Workload Identity Federation for GKE,您可以使用 IAM 政策向 GKE 集群中的 Kubernetes 工作负载授予对特定Google Cloud API 的访问权限,而无需手动配置或安全性较低的方法(例如服务账号密钥文件)。利用适用于 GKE 的工作负载身份联合,您可以为集群中的每个应用分配不同的精细身份和授权。
适用于 GKE 的工作负载身份联合不再要求使用元数据隐藏。由元数据隐藏保护的敏感元数据也受适用于 GKE 的工作负载身份联合保护。
Workload Identity Federation for GKE 可通过 IAM 工作负载身份联合使用,后者为在 Google Cloud内部和外部的环境中运行的工作负载提供身份。您可以使用 IAM 工作负载身份联合从在 AWS、Azure 和自行管理的 Kubernetes 等工作负载中运行的受支持的 Google Cloud API 安全地进行身份验证。在 GKE 中,Google Cloud 会为您管理工作负载身份池和提供方,您无需外部身份提供方。
适用于 GKE 的工作负载身份联合的工作原理
在集群上启用适用于 GKE 的工作负载身份联合时,GKE 会执行以下操作:
使用以下格式为集群的 Google Cloud项目创建固定工作负载身份池:
PROJECT_ID.svc.id.goog
工作负载身份池提供了一种命名格式,使 IAM 能够理解和信任 Kubernetes 凭据。 即使您删除项目中的所有集群,GKE 也不会删除此工作负载身份池。
在工作负载身份池中将 GKE 集群注册为身份提供方。
部署 GKE 元数据服务器,用于拦截每个节点上来自工作负载的凭据请求。
在 Google Cloud 资源上创建 IAM 允许政策
如需使用 Workload Identity Federation for GKE 提供访问权限,您需要创建 IAM 允许政策,向与应用身份对应的主账号授予对特定 Google Cloud 资源的访问权限。例如,您可以向使用 database-reader
Kubernetes ServiceAccount 的所有 Pod 授予 Cloud Storage 存储桶的读取权限。
如需查看支持允许政策的资源列表,请参阅接受允许政策的资源类型。
在 IAM 政策中使用条件
您还可以通过在允许政策中设置条件来限制访问权限范围。条件是一种可扩展的方法,用于指定何时应该应用允许政策。例如,您可以使用条件向工作负载授予对特定 Google Cloud 资源的临时访问权限,而无需手动管理该访问权限。
如果您在项目、文件夹或组织级层(而不是对特定资源,例如 Secret Manager Secret 或 Cloud Storage 存储桶)设置允许政策,条件可能也很有用。
如需向允许政策添加条件,请使用以下资源:
- 管理条件角色绑定:添加、修改或移除条件角色绑定。
- 配置临时访问权限:在许可政策中使用条件设置对 Google Cloud 资源的限时访问权限。
- 标记和条件式访问权限:使用条件,仅在资源具有特定标记时应用允许政策。
以下示例表达式适用于您可能使用条件的常见场景。如需查看表达式中可用的属性列表,请参阅 IAM Conditions 的属性参考文档。
条件表达式示例 | ||
---|---|---|
在指定时间之前允许访问 | request.time < timestamp(' 将 |
|
在请求中的资源具有指定标记时允许访问 | resource.matchTag(' 替换以下内容:
|
在 IAM 政策中引用 Kubernetes 资源
在 IAM 政策中,您可以使用 IAM 主账号标识符来选择 Kubernetes 资源以引用该资源。此标识符的语法如下:
PREFIX://iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/example-project.svc.id.goog/SELECTOR
在此示例中,请考虑以下字段:
PREFIX
:必须是principal
或principalSet
,具体取决于您选择的资源。principal
适用于特定资源,例如单个 ServiceAccount。principalSet
适用于属于指定资源的多个资源,例如特定集群中的所有 Pod。SELECTOR
:用于选择主账号类型的字符串。例如,kubernetes.serviceaccount.uid/SERVICEACCOUNT_UID
按 UID 选择 ServiceAccount。
下表显示了 GKE 中支持的主账号类型:
主账号标识符类型 | 语法 |
---|---|
使用特定 Kubernetes ServiceAccount 的所有 Pod | 按名称选择 ServiceAccount:
principal://iam.googleapis.com/projects/ 替换以下内容:
按 UID 选择 ServiceAccount: principal://iam.googleapis.com/projects/ 替换以下内容:
|
命名空间中的所有 Pod(无论服务账号或集群如何) | principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/namespace/NAMESPACE 替换以下内容:
|
特定集群中的所有 Pod | principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/kubernetes.cluster/https://container.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME 替换以下内容:
|
凭据流程
当工作负载发送请求以访问 Google Cloud API 时(例如,使用 Google Cloud 客户端库时),系统会执行以下身份验证步骤:
- 应用默认凭据 (ADC) 从虚拟机上运行的 Compute Engine 元数据服务器请求 Google Cloud 访问令牌。
- GKE 元数据服务器拦截令牌请求,并向 Kubernetes API 服务器请求 Kubernetes ServiceAccount 令牌,以标识请求工作负载。此凭据是由 API 服务器签名的 JSON Web 令牌 (JWT)。
- GKE 元数据服务器使用 Security Token Service 将 JWT 交换为引用 Kubernetes 工作负载身份的短期联合访问令牌。
在尝试访问某些 Google Cloud 服务时,Security Token Service 返回的联合访问令牌可能存在限制,如支持的产品和限制中所述。如果您选择的 Google Cloud 服务存在限制,您可以选择配置服务账号模拟。此方法会为 IAM 服务账号生成访问令牌,您的工作负载可以使用该令牌访问目标服务。如需了解详情,请参阅将 Kubernetes ServiceAccount 关联到 IAM。
然后,工作负载可以访问其 IAM 主账号标识符有权访问的任何 Google Cloud API。
身份相同性
对于共享一个工作负载身份池的多个集群中的工作负载,由于它们属于同一个 Google Cloud 项目,因此如果主账号标识符中的元数据相同,则 IAM 会将这些工作负载标识为相同的工作负载。例如,如果您在两个集群中有相同的命名空间,并且在 IAM 中授予对该命名空间的访问权限,则这两个集群中该命名空间的工作负载会获得该访问权限。您可以使用条件 IAM 政策来限制此访问权限,以便仅访问特定集群。
例如,请考虑下面的图表。集群 A 和集群 B 属于同一工作负载身份池。 Google Cloud 会将集群 A 和集群 B 的 backend
命名空间中使用 back-ksa
ServiceAccount 的应用标识为同一身份。IAM 不区分发出调用的集群。
此身份相同性还意味着您必须能够信任特定 Workload Identity 池中的每个集群。例如,如果上述示例中的新集群(集群 C)归不受信任的团队所有,则它们可以创建 backend
命名空间,并使用 back-ksa
ServiceAccount 访问 Google Cloud API,就像集群 A 和集群 B 一样。
为了避免不受信任的访问,请将集群放在不同的项目中,以确保它们获得不同的 Workload Identity 池,或者确保命名空间名称彼此不同,以避免使用共同的主账号标识符。
GKE 元数据服务器
启用了适用于 GKE 的工作负载身份联合的 GKE 中的每个节点都会将其元数据存储在 GKE 元数据服务器上。GKE 元数据服务器是 Kubernetes 工作负载所需的 Compute Engine 元数据服务器端点的子集。
GKE 元数据服务器作为 DaemonSet 运行,在每个 Linux 节点上运行一个 Pod,或者在集群中的每个 Windows 节点上运行一个原生 Windows 服务。元数据服务器会拦截对 http://metadata.google.internal
(169.254.169.254:80
) 的 HTTP 请求。例如,GET
/computeMetadata/v1/instance/service-accounts/default/token
请求将会检索 Pod 已配置为进行模拟的 IAM 服务账号的令牌。指向 GKE 元数据服务器的流量绝不会离开托管 Pod 的虚拟机实例。
下表介绍了 GKE 元数据服务器可用的 Compute Engine 元数据服务器端点的子集。如需查看 Compute Engine 元数据服务器中可用的端点的完整列表,请参阅默认虚拟机元数据值。
实例元数据
实例元数据存储在以下目录下。
http://metadata.google.internal/computeMetadata/v1/instance/
条目 | 说明 |
---|---|
hostname |
节点的主机名。 |
id |
节点的唯一 ID。 |
service-accounts/ |
与节点关联的服务账号的目录。对于每个服务账号,系统会提供以下信息:
|
zone |
GKE 节点的 Compute Engine 可用区。 |
实例特性
实例特性存储在以下目录下。
http://metadata.google.internal/computeMetadata/v1/instance/attributes/
条目 | 说明 |
---|---|
cluster-location |
集群的 Compute Engine 可用区或区域。 |
cluster-name |
GKE 集群的名称。 |
cluster-uid |
GKE 集群的 UID。 |
表中列出的属性是唯一受支持的属性。如果您尝试访问任何不受支持的属性,kube-system
命名空间中的 gke-metadata-server
Pod 会生成并记录 404
错误。错误类似于以下内容:
HTTP/404: generic::not_found: no child "", Reason: "NOT_FOUND", UserMessage: "Not Found"
如果您使用的是 istio-proxy
,则会遇到类似于以下内容的错误消息:
Error fetching GCP Metadata property gcp_gce_instance_template: metadata: GCE metadata "instance/attributes/UNSUPPORTED_ATTRIBUTE" not defined
项目元数据
集群项目元数据存储在以下目录下。
http://metadata.google.internal/computeMetadata/v1/project/
条目 | 说明 |
---|---|
project-id |
您的 Google Cloud 项目 ID。 |
numeric-project-id |
您的 Google Cloud 项目编号。 |
Workload Identity Federation for GKE 的限制
您无法更改 GKE 为您的 Google Cloud 项目创建的工作负载身份池的名称。
当 GKE 在节点池上启用 GKE 元数据服务器时,Pod 将无法再访问 Compute Engine 元数据服务器。相反,GKE 元数据服务器会拦截从这些 pod 向元数据端点发出的请求,但主机网络上运行的 Pod 除外。
GKE 元数据服务器需要几秒钟的时间才能开始接受新创建的 Pod 发出的请求。因此,尝试在 Pod 生命周期的前几秒内使用适用于 GKE 的工作负载身份联合进行身份验证可能会失败。重试调用会解决问题。如需了解详情,请参阅问题排查。
GKE 内置的日志记录和监控代理将继续使用节点的服务账号。
Workload Identity Federation for GKE 需要手动设置 Knative serving 才能继续发布请求指标。
适用于 GKE 的工作负载身份联合将每个节点的 GKE 元数据服务器连接限制为 200 个,以避免内存问题。如果您的节点数超出此限制,则可能会遇到超时情况。
Windows Server 节点的适用于 GKE 的工作负载身份联合可在 GKE 版本 1.18.16-gke.1200、1.19.8-gke.1300、1.20.4-gke.1500 及更高版本中使用。
GKE 元数据服务器的内存资源用量与集群中的 Kubernetes 服务账号总数成正比。如果您的集群拥有超过 3000 个 Kubernetes 服务账号,则 kubelet 可能会终止元数据服务器 Pod。如需了解缓解措施,请参阅问题排查。
适用于 GKE 的工作负载身份联合的替代方案
您可以使用 Workload Identity Federation for GKE 的以下任一替代方案从 GKE 访问Google Cloud API。我们建议您使用适用于 GKE 的工作负载身份联合,因为这些替代方案要求您做出特定的安全妥协。
使用节点的 Compute Engine 默认服务账号。您可以使用项目中的任何 IAM 服务账号身份运行节点池。如果您在创建节点池期间未指定服务账号,则 GKE 会使用项目的 Compute Engine 默认服务账号。Compute Engine 服务账号由该节点上部署的所有工作负载共享。这会导致权限过度预配,从而违反最小权限原则,不适合多租户集群。
导出服务账号密钥并将其存储为 Kubernetes Secret,您会将其作为卷装载到 Pod 中。