服务帐户

了解 Kubernetes 中的 ServiceAccount 对象。

本页面介绍了 Kubernetes 中的 ServiceAccount 对象,提供了有关服务帐户工作原理、用例、局限性、替代方案以及指向资源以获取更多指导的链接的信息。

什么是服务帐户?

服务帐户是一种非人类帐户类型,在 Kubernetes 中,它在 Kubernetes 集群中提供不同的身份。应用程序 Pod、系统组件和集群内部和外部的实体可以使用特定 ServiceAccount 的凭据来识别为该 ServiceAccount。此身份在各种情况下很有用,包括向 API 服务器进行身份验证或实施基于身份的安全策略。

服务帐户以 API 服务器中的 ServiceAccount 对象形式存在。服务帐户具有以下属性

  • 命名空间:每个服务帐户都绑定到 Kubernetes 命名空间。每个命名空间在创建时都会获得一个 default ServiceAccount

  • 轻量级:服务帐户存在于集群中,并在 Kubernetes API 中定义。您可以快速创建服务帐户以启用特定任务。

  • 可移植性:复杂容器化工作负载的配置包可能包括系统组件的服务帐户定义。服务帐户的轻量级性质和命名空间身份使配置可移植。

服务帐户与用户帐户不同,用户帐户是集群中经过身份验证的人类用户。默认情况下,用户帐户不存在于 Kubernetes API 服务器中;相反,API 服务器将用户身份视为不透明数据。您可以使用多种方法作为用户帐户进行身份验证。一些 Kubernetes 发行版可能会添加自定义扩展 API 来表示 API 服务器中的用户帐户。

服务帐户和用户的比较
描述ServiceAccount用户或组
位置Kubernetes API (ServiceAccount 对象)外部
访问控制Kubernetes RBAC 或其他 授权机制Kubernetes RBAC 或其他身份和访问管理机制
预期用途工作负载,自动化人员

默认服务帐户

创建集群时,Kubernetes 会自动为集群中每个命名空间创建一个名为 default 的 ServiceAccount 对象。每个命名空间中的 default 服务帐户默认情况下没有权限,除了 Kubernetes 授予所有经过身份验证的主体的 默认 API 发现权限(如果启用了基于角色的访问控制 (RBAC))。如果您删除了命名空间中的 default ServiceAccount 对象,则 控制平面 会用一个新的对象替换它。

如果您在命名空间中部署 Pod,并且没有 手动将 ServiceAccount 分配给 Pod,则 Kubernetes 会将该命名空间的 default ServiceAccount 分配给 Pod。

Kubernetes 服务帐户的用例

作为一般指南,您可以在以下情况下使用服务帐户来提供身份

  • 您的 Pod 需要与 Kubernetes API 服务器通信,例如在以下情况下
    • 提供对存储在 Secrets 中的敏感信息的只读访问权限。
    • 授予 跨命名空间访问权限,例如允许 example 命名空间中的 Pod 读取、列出和监视 kube-node-lease 命名空间中的租约对象。
  • 您的 Pod 需要与外部服务通信。例如,工作负载 Pod 需要商业上可用的云 API 的身份,并且商业提供商允许配置合适的信任关系。
  • 使用 imagePullSecret 向私有镜像注册表进行身份验证.
  • 外部服务需要与 Kubernetes API 服务器通信。例如,作为 CI/CD 管道的一部分向集群进行身份验证。
  • 您在集群中使用第三方安全软件,该软件依赖于不同 Pod 的 ServiceAccount 身份将这些 Pod 分组到不同的上下文中。

如何使用服务帐户

要使用 Kubernetes 服务帐户,您需要执行以下操作

  1. 使用 Kubernetes 客户端(如 kubectl)或定义对象的清单来创建一个 ServiceAccount 对象。

  2. 使用授权机制(如 RBAC)向 ServiceAccount 对象授予权限。

  3. 在 Pod 创建期间将 ServiceAccount 对象分配给 Pod。

    如果您使用的是来自外部服务的身份,请 检索 ServiceAccount 令牌 并在该服务中使用它。

有关说明,请参阅 为 Pod 配置服务帐户

向 ServiceAccount 授予权限

您可以使用内置的 Kubernetes 基于角色的访问控制 (RBAC) 机制来授予每个服务帐户所需的最低权限。您创建了一个角色,它授予访问权限,然后将角色绑定到您的 ServiceAccount。RBAC 使您能够定义一组最小权限,以便服务帐户权限遵循最小特权原则。使用该服务帐户的 Pod 不会获得超出正常运行所需权限的权限。

有关说明,请参阅 ServiceAccount 权限

使用 ServiceAccount 进行跨命名空间访问

您可以使用 RBAC 允许一个命名空间中的服务帐户对集群中另一个命名空间中的资源执行操作。例如,考虑一个场景,您在 dev 命名空间中有一个服务帐户和 Pod,并且您希望您的 Pod 看到在 maintenance 命名空间中运行的作业。您可以创建一个角色对象,该对象授予列出作业对象的权限。然后,您将在 maintenance 命名空间中创建一个 RoleBinding 对象,将该角色绑定到 ServiceAccount 对象。现在,dev 命名空间中的 Pod 可以使用该服务帐户在 maintenance 命名空间中列出作业对象。

将 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 会向 Pod 提供一个长期有效的静态令牌,作为 Secret。

手动检索 ServiceAccount 凭据

如果您需要 ServiceAccount 的凭据来安装在非标准位置,或供非 API 服务器的受众使用,请使用以下方法之一

  • TokenRequest API(推荐):从您自己的应用程序代码中请求一个短暂的服务帐户令牌。该令牌会自动过期,并在过期时旋转。如果您有遗留应用程序,它不知道 Kubernetes,则可以使用同一 Pod 中的辅助容器来获取这些令牌并将它们提供给应用程序工作负载。
  • 令牌卷投影(也推荐):在 Kubernetes v1.20 及更高版本中,使用 Pod 规范告诉 kubelet 将服务帐户令牌添加到底 Pod 中,作为投影卷。投影令牌会自动过期,并且 kubelet 会在令牌过期之前旋转令牌。
  • 服务账号令牌密钥(不推荐):您可以将服务账号令牌作为 Kubernetes 密钥挂载到 Pod 中。这些令牌不会过期,也不会轮换。在 v1.24 之前的版本中,会为每个服务账号自动创建一个永久令牌。由于与静态、长期存在的凭据相关的风险,这种方法不再推荐,尤其是在大规模情况下。 LegacyServiceAccountTokenNoAutoGeneration 功能门控(默认情况下从 Kubernetes v1.24 到 v1.26 启用)阻止了 Kubernetes 为服务账号自动创建这些令牌。该功能门控在 v1.27 中被移除,因为它已提升为 GA 状态;您仍然可以手动创建无限期的服务账号令牌,但应考虑安全隐患。

限制对密钥的访问

Kubernetes 提供了一个名为 kubernetes.io/enforce-mountable-secrets 的注释,您可以将其添加到您的服务账号中。当应用此注释时,服务账号的密钥只能挂载在指定类型的资源上,从而增强了您集群的安全态势。

您可以使用清单将注释添加到服务账号

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubernetes.io/enforce-mountable-secrets: "true"
  name: my-serviceaccount
  namespace: my-namespace

当此注释设置为 "true" 时,Kubernetes 控制平面确保来自此服务账号的密钥会受到某些挂载限制。

  1. 作为卷挂载到 Pod 中的每个密钥的名称必须出现在 Pod 的服务账号的 secrets 字段中。
  2. 在 Pod 中使用 envFrom 引用的每个密钥的名称也必须出现在 Pod 的服务账号的 secrets 字段中。
  3. 在 Pod 中使用 imagePullSecrets 引用的每个密钥的名称也必须出现在 Pod 的服务账号的 secrets 字段中。

通过了解和执行这些限制,集群管理员可以保持更严格的安全配置文件,并确保密钥仅被适当的资源访问。

验证服务账号凭据

服务账号使用签名的 JSON Web 令牌(JWT)向 Kubernetes API 服务器进行身份验证,以及向存在信任关系的任何其他系统进行身份验证。根据令牌的颁发方式(使用 TokenRequest 进行时间限制,或者使用使用密钥的传统机制),服务账号令牌也可能具有过期时间、受众和令牌开始有效的时限。当充当服务账号的客户端尝试与 Kubernetes API 服务器通信时,客户端会在 HTTP 请求中包含一个 Authorization: Bearer <token> 标头。API 服务器按如下方式检查该承载令牌的有效性

  1. 检查令牌签名。
  2. 检查令牌是否已过期。
  3. 检查令牌声明中的对象引用当前是否有效。
  4. 检查令牌当前是否有效。
  5. 检查受众声明。

TokenRequest API 为服务账号生成绑定令牌。此绑定与充当该服务账号的客户端(例如 Pod)的生命周期相关联。有关绑定 Pod 服务账号令牌的 JWT 模式和有效负载示例,请参阅 令牌卷投影

对于使用 TokenRequest API 颁发的令牌,API 服务器还会检查正在使用服务账号的特定对象引用是否仍然存在,并根据该对象的 唯一 ID 进行匹配。对于作为密钥挂载到 Pod 中的传统令牌,API 服务器会将令牌与密钥进行比较。

有关身份验证过程的更多信息,请参阅 身份验证

在您自己的代码中验证服务账号凭据

如果您有自己的服务需要验证 Kubernetes 服务账号凭据,您可以使用以下方法

Kubernetes 项目建议您使用 TokenReview API,因为这种方法会使绑定到 API 对象(例如密钥、服务账号、Pod 或节点)的令牌失效,当这些对象被删除时。例如,如果您删除了包含投影服务账号令牌的 Pod,则集群会立即使该令牌失效,并且 TokenReview 会立即失败。如果您使用 OIDC 验证,则您的客户端会继续将令牌视为有效,直到令牌到达其过期时间戳为止。

您的应用程序应始终定义它接受的受众,并应检查令牌的受众是否与应用程序期望的受众相匹配。这有助于最小化令牌的范围,使其只能在您的应用程序中使用,而不能在其他地方使用。

替代方案

下一步

此页面上的项目是指提供 Kubernetes 所需功能的第三方产品或项目。Kubernetes 项目作者对这些第三方产品或项目不承担任何责任。有关更多详细信息,请参阅 CNCF 网站指南

在提出添加额外第三方链接的更改之前,您应阅读 内容指南