4. 集群升级对证书的影响:API Server 升级、kubelet 版本变更导致的证书信任链变化
Kubernetes 集群升级并非简单的组件版本替换,其核心风险之一在于证书信任链的断裂。API Server 与 kubelet 之间的双向 TLS 认证依赖于 CA 证书、服务端证书和客户端证书的协同工作。当集群从旧版本升级到新版本时,证书的签发策略、加密算法、组织名称(O/OU)以及 CA 根证书都可能发生变化,导致原本信任的证书链失效。
4.1 证书信任链的基本模型
在 Kubernetes 集群中,API Server 与 kubelet 之间的通信采用双向 TLS(mTLS)认证。其信任链模型如下:
核心原则:API Server 作为服务端,kubelet 作为客户端;同时 kubelet 也作为服务端提供 metrics 和 exec 接口,API Server 作为客户端访问。因此,双方都需要验证对方的证书是否由可信 CA 签发。
| 角色 | 证书类型 | 签发者 | 验证方 |
|---|---|---|---|
| API Server | 服务端证书(apiserver.crt) | 集群 CA(ca.crt) | kubelet 验证 API Server 身份 |
| kubelet | 客户端证书(kubelet-client.crt) | 集群 CA(ca.crt) | API Server 验证 kubelet 身份 |
| kubelet | 服务端证书(kubelet-server.crt) | 集群 CA 或 kubelet CA | API Server 验证 kubelet 服务端身份 |
升级过程中,任何一环的 CA 变更、证书轮换或版本差异,都会破坏这个信任链。
4.2 API Server 升级对证书的影响
API Server 升级主要从以下三个维度影响证书信任链:
- CA 证书变更:如果升级过程中集群 CA 被替换(例如从自签名 CA 切换到外部 CA,或 CA 证书过期轮换),则所有由旧 CA 签发的证书将不再被信任。API Server 启动时加载的
--client-ca-file指向的 CA 文件必须包含新 CA。 - 服务端证书 SAN 变化:新版本 API Server 可能要求服务端证书包含特定的 Subject Alternative Name(SAN),例如
kubernetes.default.svc、kubernetes.default、kubernetes以及集群 IP 地址。如果旧证书缺少这些 SAN,kubelet 在验证 API Server 时会报错Hostname mismatch。 - 加密算法与密钥长度升级:Kubernetes 1.24+ 默认使用 ECDSA 算法签发证书,而旧版本可能使用 RSA 2048。如果 kubelet 的证书验证库不支持新算法,会导致握手失败。
常见故障场景:API Server 升级后,kubelet 日志中出现
certificate signed by unknown authority 或 x509: certificate is valid for xxx, not yyy。这通常意味着 kubelet 持有的 CA 证书与 API Server 使用的 CA 不一致,或 API Server 证书的 SAN 不匹配。
4.3 kubelet 版本变更对证书的影响
kubelet 版本变更(无论是升级还是降级)同样会引发证书信任链问题:
- kubelet 客户端证书轮换机制变化:Kubernetes 1.19+ 默认启用
RotateKubeletClientCertificate特性,kubelet 会在证书过期前自动向 API Server 申请新证书。如果升级前该特性未启用,升级后突然启用,可能导致旧证书被提前吊销或新证书未被正确签发。 - kubelet 服务端证书的 CA 切换:旧版本 kubelet 可能使用集群 CA 签发服务端证书,而新版本 kubelet 默认使用独立的
kubelet-ca或--kubelet-certificate-authority指定的 CA。如果 API Server 未配置信任新 CA,则无法验证 kubelet 的服务端身份。 - 证书组织(O)字段校验:新版本 kubelet 可能要求客户端证书的 O 字段为
system:nodes,且 CN 字段为system:node:<nodeName>。如果旧证书的 O 字段缺失或错误,API Server 的 RBAC 会拒绝 kubelet 的请求。
4.4 升级前后证书信任链变化对比
以下表格总结了升级前后证书信任链的关键变化点:
| 信任链环节 | 升级前(旧版本) | 升级后(新版本) | 潜在风险 |
|---|---|---|---|
| CA 根证书 | 旧 CA(可能即将过期) | 新 CA 或追加 CA | 旧证书不被新 CA 信任 |
| API Server 证书 | RSA 2048,SAN 较少 | ECDSA,SAN 包含所有服务名 | kubelet 验证 SAN 失败 |
| kubelet 客户端证书 | O 字段可能为空 | O=system:nodes | RBAC 拒绝访问 |
| kubelet 服务端证书 | 由集群 CA 签发 | 由 kubelet CA 签发 | API Server 不信任 kubelet CA |
| 证书轮换策略 | 手动轮换或未启用 | 自动轮换(CSR 方式) | 旧证书过期后无法自动续期 |
4.5 信任链变化的影响范围
证书信任链的变化并非孤立事件,它会引发一系列连锁反应:
- kubelet 注册失败:新节点或重启后的 kubelet 无法通过 API Server 的 TLS 认证,导致节点状态变为
NotReady。 - Pod 调度与通信异常:kubelet 无法向 API Server 上报 Pod 状态,导致调度器认为节点不可用;同时 kubelet 无法执行 exec、logs、port-forward 等操作。
- metrics 与监控中断:kubelet 的 /metrics 接口需要 API Server 验证其服务端证书,如果信任链断裂,Prometheus 等监控组件将无法抓取指标。
- 节点证书轮换失败:kubelet 在证书过期前发起 CSR 请求,但 API Server 因证书验证失败而拒绝签发新证书,形成死锁。
最佳实践:在升级前,使用
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text -noout 检查 kubelet 客户端证书的签发者、有效期和 O 字段;使用 kubectl get csr 确认证书轮换 CSR 是否正常。升级后,立即验证 kubelet 与 API Server 的 TLS 握手是否成功。
4.6 升级过程中的证书信任链变化示意图
下图展示了从旧版本集群升级到新版本集群时,证书信任链的典型变化路径:
4.7 升级后的证书验证清单
为了确保升级后证书信任链完整,建议按以下清单逐项验证:
- CA 一致性验证:对比 API Server 的
--client-ca-file与 kubelet 的--client-ca-file是否指向相同的 CA 文件。使用openssl x509 -in ca.crt -fingerprint -noout比对指纹。 - API Server 证书 SAN 验证:使用
openssl x509 -in apiserver.crt -text -noout | grep -A1 "Subject Alternative Name"确认包含所有必要的 DNS 名称和 IP。 - kubelet 客户端证书 O 字段验证:检查证书的 Subject 字段是否包含
O = system:nodes和CN = system:node:<nodeName>。 - kubelet 服务端证书 CA 验证:确认 API Server 的
--kubelet-certificate-authority配置了正确的 CA 文件,或使用--kubelet-insecure-tls临时绕过(仅用于测试)。 - 证书轮换状态检查:执行
kubectl get csr --field-selector=spec.signerName=kubernetes.io/kubelet-serving确认 CSR 已被批准。
关键命令:
# 验证 API Server 与 kubelet 的 TLS 握手
echo | openssl s_client -connect <NODE_IP>:10250 -cert /var/lib/kubelet/pki/kubelet-client-current.pem -key /var/lib/kubelet/pki/kubelet-client-current.pem -CAfile /etc/kubernetes/pki/ca.crt 2>&1 | grep "Verify return code"
# 检查 kubelet 证书的签发者
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -issuer -noout
通过以上验证,可以系统性地排查升级导致的证书信任链问题,确保 kubelet 与 API Server 之间的通信安全可靠。