大家好!今天,我们将深入探讨 Kubernetes 安全的基础和核心——Service Account(服务账户)。
如果你仅仅认为“它是用来给 Pod 授予权限的吧?”,那么今天的博文将带你了解更深层次的内容。特别是,在最近的 Kubernetes 版本中已成为标准的 Projected Volume 和 Bound Token 概念,对于安全至关重要,务必理解。
投入短短 10 分钟,掌握 Kubernetes 认证结构的核心!🚀

1. Service Account (SA): Pod 的身份证 🪪
就像我们刷员工卡进入公司大楼一样,Kubernetes 集群内部的Pod 中的应用程序需要一个身份证才能与 API 服务器通信。这就是 Service Account。
👤 用户账户 vs. 🤖 服务账户
- 用户账户 (User Account): 供人类(Human)使用的账户(管理员、开发人员等)。它通常是全局管理的,并与 AWS IAM 或 Google 账户等外部系统关联。
- 服务账户 (Service Account): 供进程(Bot)使用的账户。其最显著的特点是它依赖于命名空间(Namespace)。
如果在创建 Pod 时未单独指定,Kubernetes 会自动分配该命名空间下的默认服务账户。
2. 旧方法:“永不失效的钥匙”(Legacy) 🗝️
在旧(Legacy)方法中,创建服务账户时会自动生成一个 Secret(密钥)资源。这个 Secret 中包含一个没有过期时间(No Expiration)的令牌。
这种方法存在一个致命的缺点:
- 安全漏洞:令牌一旦被盗,在管理员手动吊销之前,黑客可以永远使用它。
- 管理不便:要轮换令牌,需要执行删除并重新创建 Secret 的繁琐操作。
因此,Kubernetes 社区引入了一项新技术,称为 Projected Volume。
3. 当前标准:Projected Volume 与“活着的令牌” ✨
在最新的 Kubernetes 中,令牌不再存储在静态的 Secret 中。取而代之的是,使用 Projected Volume,在 Pod 创建的那一刻,从 API 服务器获取一个“临时令牌”并注入到 Pod 中。
📽️ 为什么叫“Projected(投影)”?
一般的卷挂载(Volume Mount)是连接一个存储源,而 Projected Volume 是一种将多个源聚合(投影)到一个目录中显示的技术。
它通常会将以下三种信息混合到一个文件夹(/var/run/secrets/kubernetes.io/serviceaccount)中显示:
- serviceAccountToken: 用于认证的 JWT 令牌
- configMap (kube-root-ca.crt): 用于信任 API 服务器的证书
- downwardAPI: Pod 的命名空间信息
4. 核心技术:Bound Service Account Token 🔗
通过 Projected Volume 注入的令牌被称为 Bound Token。这是因为它们被“强力绑定(Bound)”到了某个东西上。这个概念是安全的核心。
① Time Bound(时间限制) ⏳
这些令牌有有效期(默认为 1 小时)。
- Legacy: 无有效期。
- Modern: 设置了
expirationSeconds。
② Object Bound(Pod 依赖) 📦
此令牌与其颁发的特定 Pod(Pod UID)共存亡。
- Pod 被删除时,令牌也会立即失效。
- 如果攻击者复制了令牌并试图在另一个 Pod 中使用,但令牌内的信息与运行环境不匹配,可能会被拒绝。
③ Audience Bound(使用范围限制) 🎯
可以在令牌中设置 aud(Audience)字段。
- 如果令牌是为“AWS 认证”颁发的,那么试图用它来攻击 Kubernetes API 服务器将会被拒绝,提示“嘿,你不是用于 AWS 的吗?”。
- Istio 等服务网格积极利用此功能来实现服务间的认证。
5. 剖析 YAML 文件 📝
如果你查看 Pod 的 YAML 文件底部,会发现 kubelet 自动添加了以下配置:
YAML
volumes:
- name: kube-api-access-xxxxx
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607 # 👈 1 小时后过期!
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
得益于此配置,Pod 内的应用程序可以读取 /var/run/secrets/kubernetes.io/serviceaccount/token 文件,从而安全地进行通信。
6. 令牌过期后应用会停止吗?(Token Rotation) 🔄
“如果 1 小时后过期,我的服务也会在 1 小时后停止吗?”
不!请放心。
Kubelet 会非常勤奋地工作。
- 当令牌的过期时间临近时,Kubelet 会自动向 API 服务器请求新令牌。
- 然后,它会用新令牌值覆盖(更新) Pod 中挂载的 token 文件。
- 应用程序(大多数 K8s 客户端库)会定期重新读取文件以刷新令牌。
⚠️ 注意事项:如果你是直接开发应用程序,需要实现定期重新读取令牌文件(Reload)的逻辑,而不是只在开始时读取一次。(Go 客户端等标准库已内置此功能。)
7. 总结 🎁
让我们用三句话总结今天的内容:
- Service Account 是 Pod 与 Kubernetes API 对话的身份证。
- 为了安全起见,采用 Projected Volume 方式,使用生命周期短且自动轮换的令牌(Bound Token)。
- 此令牌与 Pod 共存亡,并绑定到特定 Pod,即使被盗用,风险也较低。
现在,当你运行 kubectl get pod -o yaml 时,看到复杂的 projected 语法应该不再害怕了吧?这是 Kubernetes 为保护你的集群安全而付出的细致考量。🛡️
祝你今天也有一个安全愉快的 Kubernetes 生活!
发表回复