Kubernetes 认证机制深度解析:从 Token 到证书的自动轮转
Kubernetes 认证机制深度解析:从 Token 到证书的自动轮转
你是否好奇过:为什么 Pod 内的应用只需要 Token 就能访问 API Server?为什么 Kubelet 使用客户端证书而不是 Token?当 Token 或证书更新后,正在运行的客户端是如何自动切换的?本文将深入解析 Kubernetes 认证机制的完整生命周期,揭示这些设计背后的原理。
引言
在 Kubernetes 集群中,安全认证是保障集群安全的第一道防线。无论是 Pod 内的应用访问 API Server,还是 Kubelet 这样的系统组件,都需要通过认证来证明自己的身份。
Kubernetes 提供了多种认证方式,其中 Bearer Token 和 TLS 客户端证书 都支持自动轮转,但它们的实现机制却大相径庭。本文将深入解析这两种认证方式的完整生命周期,揭示它们的设计原理和实现细节。
你将学到:
- Token 和客户端证书的本质区别
- 两种认证方式的自动轮转机制
- 客户端如何处理认证凭证的更新
- InClusterConfig 的工作原理
- 实际应用中的最佳实践
一、两种认证方式概览
1.1 Bearer Token 认证
使用场景:Pod 内的应用访问 API Server
特点:
- 应用层认证(HTTP Header)
- 短期有效(默认 1 小时 7 秒)
- 自动刷新机制
- 通过 Projected Volume 挂载到 Pod
典型使用:
|
|
1.2 TLS 客户端证书认证
使用场景:Kubelet、Kube-proxy 等系统组件
特点:
- 传输层认证(TLS 握手)
- 长期有效(通常数月)
- 通过 CSR(Certificate Signing Request)自动轮转
- 存储在节点文件系统
典型使用:
|
|
二、Token 的完整生命周期
2.1 Token 的类型
Kubernetes 中存在两种主要的 Service Account Token:
Legacy Token(传统 Token)
- 存储方式:存储在 Secret 中
- 过期时间:没有过期时间(除非 Secret 被删除)
- Issuer:
kubernetes/serviceaccount - 状态:逐步被淘汰,新版本推荐使用 Projected Token
Projected Token(投影 Token)
- 生成方式:通过 TokenRequest API 动态生成
- 过期时间:有明确的过期时间(默认 1 小时 7 秒)
- Issuer:
kubernetes.io/serviceaccount - 状态:现代 Kubernetes 推荐的标准方式

2.2 Token 的挂载机制
当 Pod 创建时,如果没有明确禁用,Kubernetes 会自动挂载 Token:
挂载流程:
- Admission 阶段:ServiceAccount Admission Controller 修改 Pod Spec
- Volume 创建:添加 Projected 类型的 Volume
- 文件挂载:挂载到
/var/run/secrets/kubernetes.io/serviceaccount/
挂载内容:
token:Service Account Tokenca.crt:集群 CA 证书namespace:Pod 所在命名空间

2.3 Token 的自动更新机制
Token Manager 负责管理 Token 的生命周期:
更新触发条件:
- Token 使用时间超过 24 小时,或
- Token 剩余有效期少于 20%(加上随机抖动)
更新流程:
|
|
文件更新机制:
- Projected Volume 使用 AtomicWriter 实现原子更新
- 通过符号链接的原子重命名实现文件更新
- 应用可以监控
..data符号链接的变化

2.4 客户端如何处理 Token 更新
这是很多开发者关心的问题:当 Token 更新后,正在使用旧 Token 的客户端(如 Informer)会如何处理?
文件更新机制
Projected Volume 使用符号链接实现原子更新:
- 用户可见文件:
/var/run/secrets/kubernetes.io/serviceaccount/token→..data/token - 数据目录:
..data→..2024_01_01_12_00_00.12345678/ - 通过重命名符号链接实现原子切换
client-go 的 Token 读取
client-go 使用两层机制处理 Token:
-
fileTokenSource:
- 每次调用
Token()时重新读取文件 - 不缓存文件内容,确保获取最新 Token
- 每次调用
-
cachingTokenSource:
- 提供缓存机制,减少文件 I/O
- 缓存时间短(1 分钟),确保及时刷新
- 缓存过期时自动重新读取文件

Informer 的处理
当 Token 更新后,Informer 通过以下机制自动处理:
- 自动重连:Watch 连接断开后自动重新建立
- 401 错误处理:收到 401 时清除缓存,强制重新读取 Token
- 无缝切换:整个过程对应用透明,不会丢失事件
关键设计:
- 缓存时间短(1 分钟),确保及时感知 Token 更新
- 401 错误时强制清除缓存
- 通过 ResourceVersion 恢复 Watch 事件
三、客户端证书的完整生命周期
3.1 证书轮转的触发
Kubelet 的客户端证书轮转在以下情况触发:
- 证书即将过期:剩余有效期少于 1/3
- 证书不存在:首次启动或证书丢失
- 强制轮转:使用 Bootstrap 证书时立即轮转
3.2 GetClientCertificate 机制
这是客户端证书轮转的核心机制:
|
|
关键点:
GetClientCertificate是 Go 标准库crypto/tls包提供的回调接口- 在每次 TLS 握手时被调用
- 允许动态获取证书,而不是在连接建立时固定
3.3 证书更新后的连接处理
这是客户端证书轮转的关键步骤:
|
|
为什么必须关闭连接?
因为 TLS 握手在连接建立时完成,已建立的连接使用握手时的证书。要使用新证书,必须:
- 关闭所有现有连接
- 强制重新进行 TLS 握手
- 新握手时调用
GetClientCertificate获取新证书

3.4 CSR 流程
证书轮转通过 CSR(Certificate Signing Request)实现:
- 生成 CSR:Kubelet 生成私钥和 CSR
- 提交 CSR:通过 API Server 的 CSR API 提交
- 等待批准:CSR Controller 自动批准(或手动批准)
- 获取证书:下载签名后的证书
- 更新文件:更新本地证书文件
四、两种机制的深度对比
4.1 本质区别
| 维度 | Bearer Token | TLS 客户端证书 |
|---|---|---|
| 认证层次 | 应用层(HTTP Header) | 传输层(TLS 握手) |
| 认证时机 | HTTP 请求时 | TLS 握手时 |
| 更新方式 | 文件更新 + 重新读取 | 关闭连接 + 重新握手 |
| Go 机制 | 文件系统 + HTTP Header | GetClientCertificate 回调 |
| 连接影响 | 不需要关闭连接 | 必须关闭连接 |
| 更新频率 | 高(Token 有效期短) | 低(证书有效期长) |
4.2 实现机制对比
Token 轮转实现
|
|
特点:
- ✅ 不需要关闭连接
- ✅ 在现有连接上更新 HTTP Header
- ✅ 更新频率高,但开销小
客户端证书轮转实现
|
|
特点:
- ⚠️ 必须关闭连接
- ⚠️ 需要重新进行 TLS 握手
- ✅ 更新频率低,但一次性开销大
4.3 为什么需要不同的机制?
TLS 握手的限制
问题:
- TLS 握手在连接建立时完成
- 已建立的连接使用握手时的证书
- 无法在已建立的连接上更换证书
解决方案:
- 关闭所有连接
- 强制重新握手
- 新握手时使用新证书
HTTP Header 的灵活性
优势:
- HTTP Header 在每个请求中发送
- 可以随时更新 Header 内容
- 不需要重新建立连接
实现:
- Token 文件更新后,应用重新读取
- 新请求使用新 Token
- 旧请求继续使用旧 Token(直到过期)
4.4 性能影响对比
客户端证书轮转:
- ⚠️ 连接中断:所有连接被关闭
- ⚠️ 重新握手开销:需要重新进行 TLS 握手
- ✅ 一次性开销:轮转频率低(通常数月一次)
Token 轮转:
- ✅ 无连接中断:连接保持打开
- ✅ 无握手开销:不需要重新握手
- ⚠️ 文件 I/O:需要读取文件(有缓存优化)
五、InClusterConfig 的工作原理
5.1 为什么只需要 Token 和 CA?
很多开发者疑惑:为什么 InClusterConfig 只需要 Token 和 CA,不需要客户端证书的私钥?
答案:
- Token 本身就是完整的认证凭证:Bearer Token 通过 HTTP Header 发送,本身就是认证凭证
- 不需要私钥:Token 验证在 API Server 端使用公钥进行,客户端只需要提供 Token
- CA 的作用:用于验证 API Server 的 TLS 证书,确保连接到正确的服务器
对比 TLS 客户端证书:
- TLS 客户端证书:需要私钥(用于 TLS 握手时的签名)
- Bearer Token:不需要私钥(Token 本身已包含签名,服务器用公钥验证)
5.2 TLS 握手仍然会发生
重要理解:即使没有客户端证书,TLS 握手仍然会发生!
原因:
- HTTPS 协议要求:
InClusterConfig使用https://协议,必须进行 TLS 握手 - CA 的作用:用于验证 API Server 的 TLS 证书
- 客户端证书是可选的:没有客户端证书不影响 TLS 握手,只是不发送客户端证书
完整流程:
|
|
5.3 为什么只能在集群内使用?
InClusterConfig 通过检查环境变量来判断是否在集群内:
|
|
原因:
KUBERNETES_SERVICE_HOST和KUBERNETES_SERVICE_PORT由 kubelet 在创建 Pod 时自动注入- Token 文件
/var/run/secrets/kubernetes.io/serviceaccount/token由 Projected Volume 挂载 - 这些资源在集群外不存在
六、实际应用场景
6.1 Pod 内应用使用 Token
典型场景:Pod 内的应用需要访问 Kubernetes API
|
|
优势:
- 零配置,自动发现
- Token 自动轮转
- 符合 Kubernetes 最佳实践
6.2 Kubelet 使用客户端证书
典型场景:Kubelet 需要与 API Server 通信
|
|
优势:
- 传输层认证,更安全
- 适合长期连接
- 证书有效期长,轮转频率低
6.3 混合使用
在实际场景中,两种方式可以同时使用:
- TLS 客户端证书:用于节点级别的认证(Kubelet、Kube-proxy)
- Bearer Token:用于 Pod 内应用的认证
两者互补而非替代:
- TLS 提供传输安全(加密 + 服务器身份验证)
- Token 提供应用层身份认证(客户端身份验证)
七、最佳实践
7.1 Token 使用建议
- 使用 Projected Token:新部署优先使用 Projected Token
- 合理设置过期时间:根据应用需求设置合适的过期时间
- 禁用不必要的自动挂载:对于不需要访问 API Server 的 Pod,禁用自动挂载
- 处理 Token 过期:应用需要正确处理 Token 过期和刷新
7.2 证书使用建议
- 启用自动轮转:生产环境必须启用证书自动轮转
- 配置 Bootstrap:使用 Bootstrap 机制支持自动化部署
- 监控证书状态:定期检查证书 TTL 和轮转状态
- 设置告警:对证书过期和轮转失败设置告警
7.3 故障排查
Token 相关问题:
- Token 未挂载:检查 Pod 和 ServiceAccount 的
automountServiceAccountToken设置 - Token 过期:检查 Token 的过期时间和 Token Manager 状态
- Token 刷新失败:检查 API Server 连接和 ServiceAccount 权限
证书相关问题:
- 证书轮转失败:检查 CSR 状态、Approver 日志、网络连接
- 证书过期:检查证书管理器状态,手动批准 CSR
- 连接问题:检查证书更新后的连接关闭机制
八、总结
8.1 核心要点
-
两种认证方式都支持自动轮转,但实现机制不同:
- Token:应用层认证,通过文件更新实现,不需要关闭连接
- 客户端证书:传输层认证,通过 GetClientCertificate 回调实现,需要关闭连接
-
本质区别:
- Token 在 HTTP 请求时认证,可以随时更新
- 客户端证书在 TLS 握手时认证,已建立的连接无法更新
-
设计考虑:
- Token 适合 Pod 内应用,更新频繁但开销小
- 客户端证书适合系统组件,更新频率低但需要重新握手
8.2 技术亮点
-
GetClientCertificate 机制:
- Go 标准库提供的 TLS 回调接口
- 允许动态获取证书
- 每次握手时调用,确保使用最新证书
-
AtomicWriter 机制:
- 通过符号链接实现原子文件更新
- 支持多个进程同时读取
- 避免文件更新的竞态条件
-
两层安全机制:
- TLS 层:传输加密 + 服务器身份验证
- 应用层:客户端身份认证(Token)
8.3 实践建议
- Pod 内应用:使用
InClusterConfig,自动使用 Token - 系统组件:使用客户端证书,启用自动轮转
- 开发测试:可以使用 kubeconfig 文件,即使是在集群内
理解这些机制有助于:
- 更好地设计应用架构
- 快速排查认证相关问题
- 优化应用的性能和安全性
参考资料:
