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 升级过程中的证书信任链变化示意图

下图展示了从旧版本集群升级到新版本集群时,证书信任链的典型变化路径:

集群升级证书信任链变化示意图 集群升级证书信任链变化示意图 旧版本集群(v1.22) 旧 CA(ca.crt) RSA 2048 API Server 证书 SAN 较少 kubelet 客户端证书 O 字段为空 kubelet 服务端证书 由集群 CA 签发 升级 版本变更 新版本集群(v1.28) 新 CA(ca.crt) ECDSA API Server 证书 SAN 完整 kubelet 客户端证书 O=system:nodes kubelet 服务端证书 由 kubelet CA 签发 ⚠ 信任链断裂点:旧 CA 不信任新证书 / 新 CA 不信任旧证书 / SAN 不匹配 / O 字段缺失 信任链断裂的影响范围 kubelet 注册失败 节点 NotReady Pod 通信异常 exec/logs 失败 监控中断 metrics 不可用 证书轮换死锁 CSR 被拒绝

4.7 升级后的证书验证清单

为了确保升级后证书信任链完整,建议按以下清单逐项验证:

  1. CA 一致性验证:对比 API Server 的 --client-ca-file 与 kubelet 的 --client-ca-file 是否指向相同的 CA 文件。使用 openssl x509 -in ca.crt -fingerprint -noout 比对指纹。
  2. API Server 证书 SAN 验证:使用 openssl x509 -in apiserver.crt -text -noout | grep -A1 "Subject Alternative Name" 确认包含所有必要的 DNS 名称和 IP。
  3. kubelet 客户端证书 O 字段验证:检查证书的 Subject 字段是否包含 O = system:nodes 和 CN = system:node:<nodeName>。
  4. kubelet 服务端证书 CA 验证:确认 API Server 的 --kubelet-certificate-authority 配置了正确的 CA 文件,或使用 --kubelet-insecure-tls 临时绕过(仅用于测试)。
  5. 证书轮换状态检查:执行 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 之间的通信安全可靠。