服务账号
本页面介绍了 Kubernetes 中的 ServiceAccount 对象,提供了关于服务帐户如何工作、用例、限制、替代方案以及指向其他指南资源的链接。
什么是服务帐户?
服务帐户是一种非人类帐户,在 Kubernetes 中,它在 Kubernetes 集群中提供了一个独特的身份。应用程序 Pod、系统组件以及集群内部和外部的实体可以使用特定 ServiceAccount 的凭据来标识为该 ServiceAccount。这种身份在各种情况下都很有用,包括向 API 服务器进行身份验证或实施基于身份的安全策略。
服务帐户在 API 服务器中以 ServiceAccount 对象的形式存在。服务帐户具有以下属性:
命名空间绑定: 每个服务帐户都绑定到一个 Kubernetes 命名空间。每个命名空间在创建时都会获得一个
default
服务帐户。轻量级: 服务帐户存在于集群中,并在 Kubernetes API 中定义。你可以快速创建服务帐户以启用特定任务。
可移植: 复杂容器化工作负载的配置包可能包含系统组件的服务帐户定义。服务帐户的轻量级性质和命名空间绑定标识使其配置具有可移植性。
服务帐户与用户帐户不同,用户帐户是集群中经过身份验证的人类用户。默认情况下,用户帐户不存在于 Kubernetes API 服务器中;相反,API 服务器将用户身份视为不透明的数据。你可以使用多种方法以用户帐户的身份进行身份验证。一些 Kubernetes 发行版可能会添加自定义扩展 API 以在 API 服务器中表示用户帐户。
描述 | ServiceAccount | 用户或组 |
---|---|---|
位置 | Kubernetes API (ServiceAccount 对象) | 外部 |
访问控制 | Kubernetes RBAC 或其他授权机制 | Kubernetes RBAC 或其他身份和访问管理机制 |
预期用途 | 工作负载、自动化 | 人员 |
默认服务帐户
当你创建集群时,Kubernetes 会自动为集群中每个命名空间创建一个名为 default
的 ServiceAccount 对象。每个命名空间中的 default
服务帐户默认情况下没有其他权限,只有在启用基于角色的访问控制 (RBAC) 时,Kubernetes 授予所有经过身份验证的主体的默认 API 发现权限。如果你删除命名空间中的 default
ServiceAccount 对象,控制平面会将其替换为一个新的。
如果你在命名空间中部署一个 Pod,并且你没有手动将 ServiceAccount 分配给该 Pod,则 Kubernetes 会将该命名空间的 default
ServiceAccount 分配给该 Pod。
Kubernetes 服务帐户的用例
作为一般指导原则,你可以在以下场景中使用服务帐户来提供身份:
- 你的 Pod 需要与 Kubernetes API 服务器通信,例如在以下情况下:
- 提供对存储在 Secret 中的敏感信息的只读访问权限。
- 授予跨命名空间访问权限,例如允许
example
命名空间中的 Pod 读取、列出和监视kube-node-lease
命名空间中的 Lease 对象。
- 你的 Pod 需要与外部服务通信。例如,工作负载 Pod 需要一个用于商业云 API 的身份,并且商业提供商允许配置合适的信任关系。
- 使用
imagePullSecret
向私有镜像注册表进行身份验证. - 外部服务需要与 Kubernetes API 服务器通信。例如,作为 CI/CD 管道的一部分向集群进行身份验证。
- 你在集群中使用第三方安全软件,该软件依赖于不同 Pod 的 ServiceAccount 身份将这些 Pod 分组到不同的上下文中。
如何使用服务帐户
要使用 Kubernetes 服务帐户,你需要执行以下操作:
使用 Kubernetes 客户端(如
kubectl
)或定义该对象的清单创建一个 ServiceAccount 对象。使用授权机制(如RBAC)向 ServiceAccount 对象授予权限。
在 Pod 创建期间将 ServiceAccount 对象分配给 Pod。
如果你使用来自外部服务的身份,请检索 ServiceAccount 令牌并从该服务中使用它。
有关说明,请参阅为 Pod 配置服务帐户。
授予 ServiceAccount 权限
你可以使用内置的 Kubernetes 基于角色的访问控制 (RBAC) 机制来授予每个服务帐户所需的最小权限。你创建一个 *角色*,该角色授予访问权限,然后将该角色 *绑定* 到你的 ServiceAccount。RBAC 允许你定义最小的权限集,以便服务帐户权限遵循最小权限原则。使用该服务帐户的 Pod 不会获得比正确运行所需的更多权限。
有关说明,请参阅ServiceAccount 权限。
使用 ServiceAccount 进行跨命名空间访问
你可以使用 RBAC 允许一个命名空间中的服务帐户对集群中不同命名空间的资源执行操作。例如,考虑一个场景,其中你在 dev
命名空间中有一个服务帐户和 Pod,并且你希望你的 Pod 能够看到在 maintenance
命名空间中运行的 Job。你可以创建一个 Role 对象,该对象授予列出 Job 对象的权限。然后,你将在 maintenance
命名空间中创建一个 RoleBinding 对象,将 Role 绑定到 ServiceAccount 对象。现在,dev
命名空间中的 Pod 可以使用该服务帐户列出 maintenance
命名空间中的 Job 对象。
将 ServiceAccount 分配给 Pod
要将 ServiceAccount 分配给 Pod,你需要设置 Pod 规范中的 spec.serviceAccountName
字段。然后,Kubernetes 会自动为该 Pod 提供该 ServiceAccount 的凭据。在 v1.22 及更高版本中,Kubernetes 会使用 TokenRequest
API 获取一个短期的、自动轮换的令牌,并将该令牌作为投射卷挂载。
默认情况下,Kubernetes 会为 Pod 提供分配的 ServiceAccount 的凭据,无论是 default
ServiceAccount 还是你指定的自定义 ServiceAccount。
要阻止 Kubernetes 自动注入指定 ServiceAccount 或 default
ServiceAccount 的凭据,请将 Pod 规范中的 automountServiceAccountToken
字段设置为 false
。
在 1.22 之前的版本中,Kubernetes 会将一个长期存在的静态令牌作为 Secret 提供给 Pod。
手动检索 ServiceAccount 凭据
如果你需要将 ServiceAccount 的凭据挂载到非标准位置,或者用于不是 API 服务器的受众,请使用以下方法之一:
- TokenRequest API (推荐):从你自己的 *应用程序代码* 中请求一个短期的服务帐户令牌。该令牌会自动过期,并且可以在过期时轮换。如果你的应用程序不了解 Kubernetes,你可以在同一个 Pod 中使用 sidecar 容器来获取这些令牌,并将其提供给应用程序工作负载。
- 令牌卷投射(也推荐):在 Kubernetes v1.20 及更高版本中,使用 Pod 规范来告知 kubelet 将服务帐户令牌作为 *投射卷* 添加到 Pod 中。投射令牌会自动过期,并且 kubelet 会在令牌过期之前轮换令牌。
- 服务帐户令牌 Secret (不推荐):你可以将服务帐户令牌作为 Kubernetes Secret 挂载到 Pod 中。这些令牌不会过期,也不会轮换。在 v1.24 之前的版本中,会自动为每个服务帐户创建一个永久令牌。由于与静态的、长期存在的凭据相关的风险,不再推荐使用此方法,尤其是在大规模的情况下。LegacyServiceAccountTokenNoAutoGeneration 功能门控(在 Kubernetes v1.24 到 v1.26 中默认启用)阻止 Kubernetes 自动为 ServiceAccount 创建这些令牌。该功能门控已在 v1.27 中删除,因为它已提升为 GA 状态;你仍然可以手动创建无限期的服务帐户令牌,但应考虑到其安全影响。
注意
对于在 Kubernetes 集群外部运行的应用程序,你可能正在考虑创建一个存储在 Secret 中的长期存在的 ServiceAccount 令牌。这允许进行身份验证,但 Kubernetes 项目建议你避免使用这种方法。长期存在的持有者令牌代表着一种安全风险,因为一旦泄露,该令牌可能会被滥用。相反,请考虑使用其他替代方法。例如,你的外部应用程序可以使用受到良好保护的私钥 和
证书进行身份验证,或者使用自定义机制(如你自行实现的身份验证 Webhook)进行身份验证。
你还可以使用 TokenRequest 为你的外部应用程序获取短期令牌。
限制对 Secret 的访问权限(已弃用)
Kubernetes v1.32 [已弃用]
注意
kubernetes.io/enforce-mountable-secrets
自 Kubernetes v1.32 起已弃用。使用单独的命名空间来隔离对已挂载 Secret 的访问权限。Kubernetes 提供了一个名为 kubernetes.io/enforce-mountable-secrets
的注解,你可以将其添加到你的 ServiceAccount 中。应用此注解后,ServiceAccount 的 Secret 只能挂载到指定类型的资源上,从而增强集群的安全态势。
你可以使用清单将注解添加到 ServiceAccount 中:
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubernetes.io/enforce-mountable-secrets: "true"
name: my-serviceaccount
namespace: my-namespace
当此注解设置为“true”时,Kubernetes 控制平面会确保来自此 ServiceAccount 的 Secret 受到某些挂载限制。
- 每个作为卷挂载到 Pod 中的 Secret 的名称,都必须出现在 Pod 的 ServiceAccount 的
secrets
字段中。 - 在 Pod 中使用
envFrom
引用的每个 Secret 的名称,也必须出现在 Pod 的 ServiceAccount 的secrets
字段中。 - 在 Pod 中使用
imagePullSecrets
引用的每个 Secret 的名称,也必须出现在 Pod 的 ServiceAccount 的secrets
字段中。
通过理解和强制执行这些限制,集群管理员可以维护更严格的安全配置文件,并确保只有适当的资源才能访问 Secret。
验证服务帐户凭据
ServiceAccount 使用签名的 JSON Web 令牌 (JWT) 向 Kubernetes API 服务器进行身份验证,并向任何存在信任关系的其他系统进行身份验证。 根据令牌的颁发方式(使用 TokenRequest
的限时令牌,或使用 Secret 的传统机制),ServiceAccount 令牌也可能具有过期时间、受众以及令牌开始生效的时间。当充当 ServiceAccount 的客户端尝试与 Kubernetes API 服务器通信时,客户端会在 HTTP 请求中包含 Authorization: Bearer <令牌>
标头。API 服务器按如下方式检查该 bearer 令牌的有效性
- 检查令牌签名。
- 检查令牌是否已过期。
- 检查令牌声明中的对象引用当前是否有效。
- 检查令牌当前是否有效。
- 检查受众声明。
TokenRequest API 为 ServiceAccount 生成绑定令牌。此绑定链接到客户端(例如充当该 ServiceAccount 的 Pod)的生命周期。有关绑定 Pod 服务帐户令牌的 JWT 模式和有效负载的示例,请参阅令牌卷投影。
对于使用 TokenRequest
API 颁发的令牌,API 服务器还会检查使用 ServiceAccount 的特定对象引用是否仍然存在,通过该对象的唯一 ID 进行匹配。对于作为 Secret 挂载在 Pod 中的旧令牌,API 服务器会根据 Secret 检查令牌。
有关身份验证过程的更多信息,请参阅身份验证。
在您自己的代码中验证服务帐户凭据
如果您有自己的服务需要验证 Kubernetes 服务帐户凭据,可以使用以下方法
- TokenReview API(推荐)
- OIDC 发现
Kubernetes 项目建议您使用 TokenReview API,因为此方法会在绑定到 API 对象(如 Secret、ServiceAccount、Pod 或 Node)的令牌在这些对象被删除时使其失效。例如,如果您删除包含投影 ServiceAccount 令牌的 Pod,则集群会立即使该令牌失效,并且 TokenReview 会立即失败。如果您改为使用 OIDC 验证,则客户端会继续将该令牌视为有效,直到该令牌达到其过期时间戳。
您的应用程序应始终定义它接受的受众,并且应检查令牌的受众是否与应用程序期望的受众匹配。这有助于最大限度地缩小令牌的范围,以便它只能在您的应用程序中使用,而不能在其他任何地方使用。
替代方案
- 使用其他机制颁发您自己的令牌,然后使用Webhook 令牌身份验证,使用您自己的验证服务来验证 bearer 令牌。
- 向 Pod 提供您自己的身份。
使用 SPIFFE CSI 驱动程序插件将 SPIFFE SVID 作为 X.509 证书对提供给 Pod.
🛇 此项链接到不属于 Kubernetes 本身的第三方项目或产品。更多信息
- 从集群外部向 API 服务器进行身份验证,而不使用服务帐户令牌
- 配置 API 服务器以接受来自您的身份提供商的 OpenID Connect (OIDC) 令牌.
- 使用通过外部身份和访问管理 (IAM) 服务(例如来自云提供商的服务)创建的服务帐户或用户帐户,以向您的集群进行身份验证。
- 将 CertificateSigningRequest API 与客户端证书结合使用.
- 配置 kubelet 以从镜像注册表检索凭据.
- 使用设备插件来访问虚拟可信平台模块 (TPM),然后允许使用私钥进行身份验证。
下一步
此页面上的项目引用了第三方产品或项目,这些产品或项目提供了 Kubernetes 所需的功能。Kubernetes 项目的作者不负责这些第三方产品或项目。有关更多详细信息,请参阅CNCF 网站指南。
在提出添加额外第三方链接的更改之前,您应该阅读内容指南。