Technical documentation

Pod 进程用谁的身份访问 API?揭秘 ServiceAccount 自动认证与 RBAC 权限陷阱

Pod 进程用谁的身份访问 API?揭秘 ServiceAccount 自动认证与 RBAC 权限陷阱

Kubernetes Pod 进程通过自动关联的 ServiceAccount 及其挂载令牌向 API Server 发起认证,以此确立其在集群内的唯一身份主体。

Pod 进程用哪个身份去认证:ServiceAccount 的核心定义

ServiceAccount 是绑定在特定命名空间下的专用身份标识,Pod 内容器进程启动后默认使用它作为向集群核心发起请求的唯一凭证。

当 Pod 里的容器进程启动后,它向 API Server 发起任何请求时,究竟用的是谁的身份?答案既不是某个具体的管理员账号,也不是共享的静态密码。它绑定的是该命名空间下专用的 ServiceAccount。[1]

为什么不能用普通用户账户作为 Pod 身份

Kubernetes 严格区分了“人”和“机器”。普通用户账户无法通过 Kubernetes API 直接创建,通常由外部身份提供商管理,代表具体的运维人员或开发者。[2] 如果让 Pod 进程直接使用这些账号,意味着所有运行在集群中的应用都要背负着真实人员的责任。一旦某个脚本出错,不仅影响业务,还可能直接关联到个人权限,导致密钥共享和权限管理的混乱。[1]

工程上,工作负载需要随部署边界独立存在。一个 Pod 可能每分钟重启、每秒扩缩容,它的生命周期极短且动态变化。普通用户模型是静态的,无法适配这种高频变动的上下文。[2] 而 ServiceAccount 则不同,它由 API 管理,天然具备命名空间作用域。当你在部署清单中指定一个 ServiceAccount,或者使用默认设置时,API Server 会在 Pod 启动瞬间将其注入为进程的唯一身份标识。[1]

这种设计把“我是谁”(认证)和“我能做什么”(授权)彻底拆开。进程拿到凭据去证明自己是 system:authenticated,但这只是入场券。[2] 真正的权限控制,要等到 RBAC 层根据该 ServiceAccount 绑定的角色规则来判定。如果把人和机器混为一谈,就等于放弃了这种精细的隔离能力。

这里有一个常被外行忽视的细节:很多人误以为 ServiceAccount 只是一个简单的“用户名”,实际上它是一个包含特定 UID 和组信息的动态对象。 在 Kubernetes 内部,每个 ServiceAccount 都会被分配一个唯一的数字 UID(例如 1000),这个 UID 会直接传递给底层操作系统。这意味着,当 Pod 内的进程尝试访问宿主机文件系统或进行网络操作时,Linux 内核看到的不是字符串形式的名称,而是那个特定的数字 ID。这种机制确保了即使攻击者窃取了 ServiceAccount 的名称,也无法直接复用其底层权限,因为权限是与那个动态生成的 UID 强绑定的。

Pod 进程用哪个身份去认证:从关联到 API Server 的完整路径

Pod 进程利用本地文件系统挂载的静态令牌,在不输入密码的情况下自动完成向 API Server 的身份认证与主体标记。

一个运行中的容器进程,如何在不输入密码的情况下向集群核心发起请求?它靠的是挂载在本地文件系统中的静态令牌。这种机制让 Pod 内部的程序能够以 ServiceAccount 的身份自动完成 API Server 认证,而无需人工干预。

ServiceAccount 凭据在 Pod 中的自动注入机制

Kubernetes 在创建 Pod 时,会自动将关联 ServiceAccount 的令牌文件挂载到容器内部。kubelet 负责这一动作,它将令牌写入 /var/run/secrets/kubernetes.io/serviceaccount/ 目录下的 token 文件中[1]。容器内的进程启动后,直接读取该文件内容,并将其作为 Bearer Token 填入 HTTP 请求头。这一过程对应用透明,就像把钥匙塞进锁孔,程序只需调用标准库发送请求,系统便自动带上凭证。

环节 操作主体 关键动作 数据流向
挂载准备 kubelet 生成并挂载 token 文件 宿主机 → 容器卷
读取凭证 应用进程 读取 /token 文件内容 内存 → 请求头
发送请求 网络层 携带 Bearer Token 访问 API 容器 → API Server

API Server 如何识别并确认 Pod 的身份

当携带令牌的请求抵达 API Server,服务端首先验证令牌的有效性。它检查签名是否由可信的密钥签发,且未过期。一旦校验通过,API Server 不会立即判断权限,而是先确立“你是谁”。此时,请求方被标记为 system:authenticated 主体,表示其身份已通过机器账号体系的验证[2]。这一步仅确认请求来自合法的集群内部实体,并不决定它能做什么。真正的权限边界,要等到后续的 RBAC 模块介入,根据绑定规则判定具体资源的访问范围。

整个过程像一道安检门:先核对证件真伪(认证),再查通行证允许进入的区域(授权)。只有两者都通过,请求才能落地执行。

认证成功不等于拥有权限:RBAC 授权的后续判断

API Server 仅负责验证 Pod 进程持有的 ServiceAccount 令牌有效性并将其归入通用组,实际资源访问权限需由 RBAC 机制二次判定。

Pod 进程拿着 ServiceAccount 的 Token 成功登录 API Server,并不代表它就能随意读写集群里的任何资源。API Server 认证只是第一步,它只负责回答“你是谁”,系统会将通过验证的请求归入 system:authenticated 这一通用组中 [1][2]。真正的关卡在随后才开启:RBAC 需要再次介入,判定这个被确认身份的主体,究竟能对哪些资源执行什么动作 [1][2]。

审计误区:为何不能只检查身份而忽略 RBAC

很多运维人员在排查问题时,容易陷入一个思维陷阱:只要看到 Pod 持有有效的凭据,就默认该工作负载是安全的。这种思路混淆了“可认证”与“最小权限”的界限。取得 ServiceAccount 凭据,仅仅证明请求方拥有合法的机器身份,并不赋予其任意 API 的访问权 [1][2]。若审计流程只盯着身份是否有效,却跳过对 RBAC 绑定的检查,就会误以为所有能登录的进程都已被严格限制,实则可能埋下巨大的爆炸半径隐患。

为了看清这两者的区别,我们可以对比一下它们在安全链条中的不同作用:

阶段 核心问题 决策依据 典型结果
认证 你是谁? ServiceAccount Token 有效性 归入 system:authenticated 组
授权 你能做什么? RBAC Role/RoleBinding 绑定 决定具体资源的读写权限
风险点 仅查身份不查绑定 忽略 RBAC 策略配置 误判为“已受控”,实为“裸奔”

这种两段式结构揭示了机器身份治理的真实边界:身份层的作用是降低“无主体请求”的风险,而授权层才是真正控制破坏范围的闸门 [1][2]。如果只依赖身份验证,相当于给所有人发了门禁卡,却没规定他们能进哪个房间。只有将 RBAC 策略与 ServiceAccount 精确绑定,才能落实最小权限原则,确保每个 Pod 进程只能触及它必须接触的那部分资源 [1][2]。

在实际操作中,最容易被忽视的“隐形权限”往往来自于默认角色的宽泛定义。 许多团队在初始化集群时,习惯性地给 default ServiceAccount 绑定 cluster-admin 或 edit 角色,认为这样方便调试。然而,一旦某个应用被攻破,攻击者获取到的不仅是 Token,更是整个命名空间甚至集群的控制权。更隐蔽的情况是,某些第三方 Helm Chart 在安装时会隐式创建 RoleBinding,将新创建的 ServiceAccount 自动关联到高权限角色,而开发人员在审查代码时往往只关注应用逻辑,忽略了这些自动生成的权限配置。因此,在部署任何新服务前,必须显式地检查其关联的 ServiceAccount 是否继承了非预期的宽泛权限,而不是假设“没配就是没权限”。

总结:构建安全的 Pod 进程认证与授权体系

Pod 进程通过自动关联的 ServiceAccount 消除匿名访问风险并确立 system:authenticated 身份,但拥有凭证并不等同于具备任意操作权限。

Pod 进程启动时自动关联的 ServiceAccount,构成了它在集群内的唯一身份。这套机制让 API Server 能精准识别请求来源,将其标记为 system:authenticated,从而彻底消除了“无主体”的匿名访问风险[1][2]。但拿到身份只是第一步,拥有凭证绝不等于拥有任意权限。

真正的安全防线建立在“两段式”结构之上:身份层负责确认“你是谁”,授权层(RBAC)负责判定“你能做什么”。如果审计只盯着凭证有效性,却忽略了 RBAC 绑定关系,就会把“可认证”错误地等同于“最小权限”,让攻击者轻易扩大破坏范围[1][2]。这种认知偏差是许多安全事故的根源。

要让这套体系真正生效,必须遵循两个关键实践。首先,严禁将人员账户或共享密钥混入工作负载模型,坚持使用命名空间隔离的 ServiceAccount[1][2]。其次,在部署策略中强制实施最小权限原则,定期审查每个 Pod 绑定的 RoleBinding,确保其仅拥有完成业务所需的最小操作集。

身份层降低了被冒充的风险,授权层锁死了越界的可能。只有当这两层逻辑严丝合缝地协同工作时,Pod 进程才能在 Kubernetes 环境中实现从“被识别”到“被信任”的完整闭环。


FAQ:关于 Pod 身份认证的常见疑问

Q: 如果我不显式指定 ServiceAccount,Pod 会使用什么身份? A: 如果未在 Deployment 或 Pod 模板中指定,Kubernetes 会自动为该命名空间创建一个名为 default 的 ServiceAccount,并将 Pod 绑定到它。这意味着你的应用默认拥有该命名空间下 default 服务账号的权限。

Q: ServiceAccount 的 Token 会过期吗? A: 默认情况下,挂载在 Pod 中的 Token 具有较长的有效期(通常是 1 小时,取决于集群配置),但它是静态文件。一旦 Pod 重启,kubelet 会重新挂载新的 Token 文件。如果需要更细粒度的控制,可以启用动态令牌投影功能。

Q: 既然有了 ServiceAccount,还需要关注 RBAC 吗? A: 绝对需要。ServiceAccount 解决了“身份认证”问题,即确认请求来自哪里;而 RBAC 解决的是“授权”问题,即确认这个身份能做什么。没有 RBAC 的限制,拥有合法 Token 的 Pod 可能拥有过高的权限,造成安全隐患。


参考来源

  1. Authenticating | Kubernetes · https://kubernetes.io/docs/reference/access-authn-authz/authentication/(A级)
  2. Managing Service Accounts | Kubernetes · https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/(A级)