主题
Kubernetes v1.37:Pod Certificates 与 Cluster Trust Bundles —— 生产级身份认证的范式跃迁
核心摘要:Kubernetes v1.37 将
Pod Certificates(基于 X.509 的 Pod 级 TLS/mTLS 身份)与ClusterTrustBundle(集群级可信根证书统一分发机制)正式 GA。这并非对 ServiceAccount JWT 的替代,而是补全了 Kubernetes 原生身份栈的关键拼图:从“我能声明我是谁”(JWT bearer token),迈向“我能被密码学证明我是谁”(PKI-based identity with mutual TLS)。对中高级 SRE 而言,这意味着——零信任网络策略可落地、跨集群/跨云服务调用可强验证、Sidecar-less mTLS 成为可能,但同时也引入了证书生命周期管理的新运维面。
背景动机:为什么 JWT 不足以支撑现代零信任架构?
ServiceAccount JWT 自 v1.0 起就是 Kubernetes 的“默认身份”,它简洁、轻量、开箱即用。但正如官方博客所坦诚的:“If you have the token, then you are the identity”——这句话精准点出了其本质缺陷:Bearer Token 天然缺乏绑定性(binding)与抗泄露能力。
我们来拆解三个现实中的“JWT 痛点”,这些正是推动 Pod Certificates GA 的真实驱动力:
容器逃逸后的身份冒用风险
JWT 文件(如/var/run/secrets/kubernetes.io/serviceaccount/token)以明文形式挂载在容器内。一旦攻击者突破容器边界(例如通过 runc 漏洞或特权容器),即可直接读取并复用该 token 访问 API Server 或其他依赖 JWT 的外部系统(如云厂商 IAM)。而 X.509 证书若配合私钥硬件保护(如 KMS-backed key store 或 TPM),可实现密钥不可导出(non-exportable private key),从根本上阻断此类横向移动。无法满足双向 TLS(mTLS)强制要求
金融、政务、信创等合规场景普遍要求服务间通信必须启用 mTLS。传统方案需引入 Istio/Linkerd 等 Service Mesh,带来 Sidecar 注入、性能损耗(~10–15% CPU overhead)、可观测性复杂度飙升等问题。Pod Certificates 允许 Kubelet 直接为每个 Pod 签发唯一证书,并自动注入到容器文件系统(如/var/run/secrets/tls/),使curl --cert /var/run/secrets/tls/tls.crt --key /var/run/secrets/tls/tls.key https://backend.default.svc.cluster.local成为原生能力。跨集群/跨云身份联邦的信任锚缺失
JWT 可通过audience和issuer实现跨集群验证,但其信任链终点仍是 JWT 签名密钥——该密钥由 kube-apiserver 内部管理,无法被外部系统(如企业 PKI CA 或 HashiCorp Vault)权威背书。而ClusterTrustBundle提供了一种声明式、版本化、自动同步的机制,将集群信任锚(root CA)作为 Kubernetes 原生资源(CRD)进行生命周期管理,使得 Vault、SPIFFE Workload API、甚至裸金属节点上的 nginx 都能动态加载同一套可信根。
✅ 技术判断:这不是“JWT vs X.509”的二选一,而是构建分层身份体系的必然演进。JWT 仍适用于短时、低敏感度的 API Server 认证;而 Pod Certificates 则承担高保障场景下的工作负载身份——二者共存,恰如 HTTP Basic Auth 与 TLS Client Cert 在 Web 架构中的分工。
核心技术:如何启用与验证?
1. 启用前提(v1.37+ 必须配置)
Pod Certificates 功能依赖 CertificateSigningRequest(CSR)API 和新的 PodSecurityPolicy 替代品 PodSecurityAdmission。需确保以下配置已就绪:
bash
# 检查 CSR API 是否启用(默认开启)
kubectl api-resources | grep certificatesigningrequests
# 确认 kube-controller-manager 启用了相关控制器(v1.37 默认启用)
# --enable-hostpath-provisioner=false \ # 仅示例,非必需
# --cluster-signing-key-file=/etc/kubernetes/pki/ca.key \
# --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt \2. ClusterTrustBundle:集中分发可信根
ClusterTrustBundle 是一个集群范围的 CRD,用于定义一组受信任的根证书(CA Bundle),并自动同步至所有节点的指定路径(如 /etc/kubernetes/pki/trust-bundle.pem):
yaml
# cluster-trust-bundle.yaml
apiVersion: crypto.k8s.io/v1alpha1
kind: ClusterTrustBundle
metadata:
name: enterprise-ca
labels:
kubernetes.io/cluster-service: "true"
spec:
signerName: kubernetes.io/kube-apiserver-client
trustBundle: |
-----BEGIN CERTIFICATE-----
MIICqjCCAZICCQDlJw6zO4kWgTANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhk
...
-----END CERTIFICATE-----应用后,Kubelet 会自动将该 bundle 合并写入 /etc/kubernetes/pki/trust-bundle.pem,并触发重启 kubelet(或通过 systemctl reload kubelet 触发重载)。
💡 运维提示:
ClusterTrustBundle支持revision字段实现灰度更新。SRE 可先创建enterprise-ca-v2,待 80% 节点完成同步后再删除旧版,避免证书吊销窗口期风险。
3. Pod Certificate:为 Pod 自动生成 TLS 凭据
只需在 Pod spec 中添加 securityContext 声明,Kubelet 即自动为其申请并注入证书:
yaml
# pod-with-cert.yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-backend
annotations:
# 可选:指定证书有效期(默认 24h,最小 1h)
kubernetes.io/certificate-expiration: "48h"
spec:
serviceAccountName: backend-sa
securityContext:
# 关键:启用 Pod Certificate
seccompProfile:
type: RuntimeDefault
# 新增字段:请求 TLS 证书
certificate:
request:
commonName: "secure-backend.default.svc.cluster.local"
usages:
- client auth
- server auth
- digital signature
- key encipherment
containers:
- name: app
image: nginx:alpine
volumeMounts:
- name: tls-certs
mountPath: /var/run/secrets/tls
readOnly: true
volumes:
- name: tls-certs
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
- configMap:
name: ca-bundle # 可选:注入 ClusterTrustBundle 内容
items:
- key: ca-bundle.pem
path: ca-bundle.pemKubelet 会:
- 向
certificates.k8s.io/v1API 创建CertificateSigningRequest(CSR) - 使用集群 CA 签发证书(含 SAN
secure-backend.default.svc.cluster.local) - 将
tls.crt/tls.key/ca.crt自动注入到/var/run/secrets/tls/
验证方式(进入容器):
bash
$ kubectl exec -it secure-backend -- sh
/ # openssl x509 -in /var/run/secrets/tls/tls.crt -text -noout | grep -E "(Subject|Issuer|DNS)"
Subject: CN = secure-backend.default.svc.cluster.local
Issuer: CN = kubernetes
DNS:secure-backend.default.svc.cluster.local
/ # curl -v --cert /var/run/secrets/tls/tls.crt --key /var/run/secrets/tls/tls.key \
--cacert /var/run/secrets/tls/ca.crt \
https://kubernetes.default.svc.cluster.local:443/version运维建议:从 GA 到生产就绪的 5 条实战守则
绝不关闭 CSR 审批自动化
默认csrapprovingcontroller 会自动批准kubernetes.io/kube-apiserver-client类型 CSR。若你使用自定义 CA 或需人工审计,请部署cert-manager的CertificateRequest+Approval Policy,而非禁用 controller——否则 Pod Certificates 将永久 Pending。监控 CSR 状态与证书续期延迟
建议 Prometheus 抓取指标:promqlkube_certificate_signing_request_condition{condition="Approved"} == 0 histogram_quantile(0.95, rate(kube_certificate_signing_request_duration_seconds_bucket[1h]))若 P95 续期耗时 > 30s,需检查
kube-controller-manager负载及 etcd 延迟。ClusterTrustBundle 版本必须与业务发布流水线对齐
将ClusterTrustBundleYAML 纳入 GitOps 工具链(Argo CD / Flux),并与企业 PKI 的证书轮换计划联动。避免出现“新服务用新根证书签名,但旧节点尚未同步 bundle”的信任断裂。Sidecar 场景下需显式挂载证书路径
若你仍使用 Istio,需在Sidecarresource 中显式声明挂载:yamlspec: template: spec: volumes: - name: pod-tls projected: sources: - secret: name: istio-token # 保留 JWT - downwardAPI: items: - path: "certs" fieldRef: fieldPath: metadata.annotations['kubernetes.io/pod-certificate-path']审计所有使用
hostNetwork: true的 Pod
HostNetwork Pod 无法获得 Pod-level 证书(因无独立 network namespace),必须改用 Node CSR 或明确标记securityContext.certificate.disabled: true,避免误配导致启动失败。
延伸阅读:超越 v1.37 的演进路线图
- v1.38(规划中):支持
CertificateSigningRequest的spec.signerName引用ClusterTrustBundle,实现多 CA 签发策略(如:内部服务用 Let’s Encrypt,对外 API 用企业 CA)。 - SIG Auth 正在推进:将
Pod Certificates与 SPIFFE ID (spiffe://cluster.example.com/ns/default/sa/backend-sa) 深度集成,打通 Kubernetes 与零信任中间件生态。 - 生产警示:当前
ClusterTrustBundle不支持 OCSP Stapling 或 CRL 分发点(CRL Distribution Points),如需实时吊销能力,仍需依赖外部证书管理平台(如 Smallstep 或 HashiCorp Vault)。
🌐 最后结语:Kubernetes 正从“容器编排平台”加速蜕变为“云原生身份基础设施”。Pod Certificates 的 GA,不是终点,而是 SRE 团队重构安全边界的起点——你的下一个 CI/CD 流水线,是否已准备好用
kubectl get clustetrustbundle替代openssl s_client?答案,就在你明天的kubectl apply -f命令里。