服务账号

了解 Kubernetes 中的 ServiceAccount 对象。

本页面介绍 Kubernetes 中的 ServiceAccount 对象,提供有关 ServiceAccount 如何工作、使用场景、限制、替代方案以及更多指导资源的链接。

Service Account 是什么?

Service Account 是一种非人类账户,在 Kubernetes 中,它为 Kubernetes 集群提供了独特的身份。应用程序 Pod、系统组件以及集群内部和外部的实体可以使用特定的 ServiceAccount 的凭据来标识自己为该 ServiceAccount。此身份在各种情况下都很有用,包括向 API Server 进行身份验证或实施基于身份的安全策略。

Service Account 作为 ServiceAccount 对象存在于 API Server 中。Service Account 具有以下特性:

  • 有命名空间: 每个 Service Account 都绑定到 Kubernetes 命名空间。每个命名空间创建时都会有一个 default ServiceAccount

  • 轻量级: Service Account 存在于集群中,并在 Kubernetes API 中定义。你可以快速创建 Service Account 来启用特定任务。

  • 可移植: 复杂容器化工作负载的配置包可能包含系统组件的 Service Account 定义。Service Account 的轻量级特性和按命名空间划分的身份使其配置具有可移植性。

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

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

默认 Service Account

创建集群时,Kubernetes 会自动为集群中的每个命名空间创建一个名为 default 的 ServiceAccount 对象。如果启用了基于角色的访问控制 (RBAC),则每个命名空间中的 default Service Account 默认不会获得任何权限,除了 Kubernetes 授予所有已验证主体的默认 API 发现权限。如果你删除命名空间中的 default ServiceAccount 对象,控制平面会用一个新的 ServiceAccount 对象替换它。

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

Kubernetes Service Account 的使用场景

通常,你可以在以下场景中使用 Service Account 来提供身份:

  • 你的 Pod 需要与 Kubernetes API Server 通信,例如在以下情况中:
    • 为存储在 Secret 中的敏感信息提供只读访问。
    • 授予跨命名空间访问,例如允许 example 命名空间中的 Pod 读取、列出和监视 kube-node-lease 命名空间中的 Lease 对象。
  • 你的 Pod 需要与外部服务通信。例如,工作负载 Pod 需要一个商业云 API 的身份,而商业提供商允许配置合适的信任关系。
  • 使用 imagePullSecret 对私有镜像仓库进行身份验证.
  • 外部服务需要与 Kubernetes API Server 通信。例如,作为 CI/CD 流水线的一部分对集群进行身份验证。
  • 你在集群中使用第三方安全软件,该软件依赖不同 Pod 的 ServiceAccount 身份将这些 Pod 分组到不同的上下文中。

如何使用 Service Account

要使用 Kubernetes Service Account,你需要执行以下操作:

  1. 使用 kubectl 等 Kubernetes 客户端或定义该对象的清单文件创建一个 ServiceAccount 对象。

  2. 使用 RBAC 等授权机制为 ServiceAccount 对象授予权限。

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

    如果你使用来自外部服务的身份,获取 ServiceAccount Token 并从该服务使用它。

有关说明,请参阅为 Pod 配置 Service Account

为 Service Account 授予权限

你可以使用内置的 Kubernetes 基于角色的访问控制 (RBAC) 机制来授予每个 Service Account 所需的最低权限。你创建一个授予访问权限的**角色**,然后将该角色**绑定**到你的 ServiceAccount。RBAC 允许你定义一组最小权限,以便 Service Account 权限遵循最小权限原则。使用该 Service Account 的 Pod 不会获得超出其正常运行所需的权限。

有关说明,请参阅ServiceAccount 权限

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

你可以使用 RBAC 允许一个命名空间中的 Service Account 对集群中不同命名空间中的资源执行操作。例如,考虑一个场景:你在 dev 命名空间中有一个 Service Account 和 Pod,并且希望你的 Pod 能够查看在 maintenance 命名空间中运行的 Job。你可以创建一个 Role 对象,授予列出 Job 对象的权限。然后,你在 maintenance 命名空间中创建一个 RoleBinding 对象,将该 Role 绑定到 ServiceAccount 对象。现在,dev 命名空间中的 Pod 可以使用该 Service Account 列出 maintenance 命名空间中的 Job 对象。

将 ServiceAccount 分配给 Pod

要将 ServiceAccount 分配给 Pod,你在 Pod 规约中设置 spec.serviceAccountName 字段。然后 Kubernetes 会自动为 Pod 提供该 ServiceAccount 的凭据。在 v1.22 及更高版本中,Kubernetes 使用 TokenRequest API 获取一个短生命周期、**自动轮换**的 Token,并将该 Token 挂载为一个投射卷

默认情况下,Kubernetes 会为 Pod 提供所分配 ServiceAccount 的凭据,无论是 default ServiceAccount 还是你指定的自定义 ServiceAccount。

要阻止 Kubernetes 自动注入指定 ServiceAccount 或 default ServiceAccount 的凭据,请将 Pod 规约中的 automountServiceAccountToken 字段设置为 false

在早于 v1.22 的版本中,Kubernetes 将一个长生命周期、静态的 Token 作为 Secret 提供给 Pod。

手动获取 ServiceAccount 凭据

如果你需要 ServiceAccount 的凭据以将其挂载到非标准位置,或者用于不是 API Server 的受众,请使用以下方法之一:

  • TokenRequest API(推荐):在你的**应用程序代码**中请求一个短生命周期的 Service Account Token。该 Token 会自动过期并在过期时轮换。如果你有一个不了解 Kubernetes 的传统应用程序,可以在同一个 Pod 中使用一个 Sidecar 容器来获取这些 Token,并使其可用于应用程序工作负载。
  • Token 卷投射(同样推荐):在 Kubernetes v1.20 及更高版本中,使用 Pod 规约告诉 kubelet 将 Service Account Token 作为**投射卷**添加到 Pod 中。投射的 Token 会自动过期,并且 kubelet 会在 Token 过期前轮换它。
  • Service Account Token Secrets(不推荐):你可以将 Service Account Token 作为 Kubernetes Secret 挂载到 Pod 中。这些 Token 不会过期,也不会轮换。在 v1.24 之前的版本中,每个 Service Account 都会自动创建一个永久 Token。由于与静态、长生命周期凭据相关的风险,不再推荐此方法,尤其是在大规模应用中。LegacyServiceAccountTokenNoAutoGeneration 特性门控(在 Kubernetes v1.24 到 v1.26 版本中默认启用)阻止 Kubernetes 自动为 ServiceAccount 创建这些 Token。该特性门控在 v1.27 中被移除,因为它已被提升为 GA 状态;你仍然可以手动创建无限期的 Service Account Token,但应考虑其安全隐患。

限制对 Secret 的访问(已弃用)

特性状态: Kubernetes v1.32 [已弃用]

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 受限于某些挂载限制。

  1. 在 Pod 中作为卷挂载的每个 Secret 的名称必须出现在 Pod 的 ServiceAccount 的 secrets 字段中。
  2. 在 Pod 中使用 envFrom 引用的每个 Secret 的名称也必须出现在 Pod 的 ServiceAccount 的 secrets 字段中。
  3. 在 Pod 中使用 imagePullSecrets 引用的每个 Secret 的名称也必须出现在 Pod 的 ServiceAccount 的 secrets 字段中。

通过理解和强制执行这些限制,集群管理员可以维护更严格的安全配置文件,并确保只有适当的资源才能访问 Secret。

Service Account 凭据认证

Service Account 使用签名的JSON Web Token (JWT) 来向 Kubernetes API Server 以及存在信任关系的任何其他系统进行身份验证。根据 Token 的颁发方式(使用 TokenRequest 的有时限 Token 或使用 Secret 的传统机制),Service Account Token 可能还具有过期时间、受众以及 Token**开始**生效的时间。当充当 Service Account 的客户端尝试与 Kubernetes API Server 通信时,客户端会在 HTTP 请求中包含 Authorization: Bearer <token> 头。API Server 按以下方式检查该 bearer token 的有效性:

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

TokenRequest API 为 ServiceAccount 生成**绑定 Token**。此绑定与充当该 ServiceAccount 的客户端(例如 Pod)的生命周期相关联。有关绑定的 Pod Service Account Token 的 JWT 模式和负载示例,请参阅Token 卷投射

对于使用 TokenRequest API 颁发的 Token,API Server 还会检查使用 ServiceAccount 的特定对象引用是否仍然存在,通过该对象的唯一 ID 进行匹配。对于作为 Secret 挂载在 Pod 中的传统 Token,API Server 会根据 Secret 检查 Token。

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

在你的代码中验证 Service Account 凭据

如果你有自己的服务需要验证 Kubernetes Service Account 凭据,可以使用以下方法:

Kubernetes 项目建议你使用 TokenReview API,因为当 Secrets、ServiceAccount、Pod 或 Node 等 API 对象被删除时,此方法会使绑定到这些对象的 Token 失效。例如,如果你删除了包含投射的 ServiceAccount Token 的 Pod,集群会立即使该 Token 失效,并且 TokenReview 会立即失败。如果你使用 OIDC 验证,你的客户端会继续将该 Token 视为有效,直到该 Token 达到其过期时间戳。

你的应用程序应始终定义其接受的受众,并应检查 Token 的受众是否与应用程序期望的受众匹配。这有助于最大限度地缩小 Token 的范围,使其只能在你的应用程序中使用,而不能在其他地方使用。

替代方案

下一步

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

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

上次修改时间:2024 年 11 月 19 日 太平洋标准时间下午 10:53:处理评论 (3b8c927a3b)