Kubernetes集群证书轮换,涵盖kubeadm证书续期、kubelet证书自动轮换与CA替换
Kubernetes 集群是一套全量基于 TLS 的分布式系统,控制平面组件之间、kubelet 与 apiserver 之间、etcd 成员之间全部靠证书互相认证。证书过期是自建集群最经典的「到点集体趴窝」故障:kube-apiserver 起不来、kubectl 报 x509: certificate has expired、节点集体 NotReady。
kubeadm 集群的证书分三类,轮换方式完全不同:
| 类别 | 位置 | 默认有效期 | 谁负责轮换 |
|---|---|---|---|
| 控制平面证书 | /etc/kubernetes/pki/、*.conf |
1 年 | kubeadm certs renew(手工或随 upgrade) |
| CA 证书 | /etc/kubernetes/pki/ca.crt、etcd/ca.crt |
10 年 | kubeadm 不自动轮换,需手工流程 |
| kubelet 证书 | /var/lib/kubelet/pki/ |
1 年 | kubelet 自己轮换(客户端证书默认开) |
控制平面证书的完整清单:
/etc/kubernetes/pki/ca.crt 集群根 CA(签发 apiserver、kubelet 客户端等)
/etc/kubernetes/pki/apiserver.crt kube-apiserver 服务端证书
/etc/kubernetes/pki/apiserver-kubelet-client.crt apiserver 访问 kubelet 的客户端证书
/etc/kubernetes/pki/apiserver-etcd-client.crt apiserver 访问 etcd 的客户端证书
/etc/kubernetes/pki/front-proxy-ca.crt front-proxy 专用 CA
/etc/kubernetes/pki/front-proxy-client.crt aggregation 层客户端证书
/etc/kubernetes/pki/etcd/ca.crt etcd 独立 CA
/etc/kubernetes/pki/etcd/server.crt etcd 服务端证书
/etc/kubernetes/pki/etcd/peer.crt etcd 成员间通信证书
/etc/kubernetes/pki/etcd/healthcheck-client.crt etcd 健康检查客户端证书
/etc/kubernetes/pki/sa.key /etc/kubernetes/pki/sa.pub ServiceAccount token 签名密钥
/etc/kubernetes/admin.conf 集群管理员 kubeconfig
/etc/kubernetes/super-admin.conf super-admin kubeconfig(1.29 起新增)
/etc/kubernetes/kubelet.conf kubelet 用的 kubeconfig(内含客户端证书)
/etc/kubernetes/controller-manager.conf
/etc/kubernetes/scheduler.conf
# 一次性列出所有证书的到期时间与剩余天数,最常用的巡检命令
sudo kubeadm certs check-expiration
# 输出形如:
# CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
# admin.conf Sep 01, 2027 08:00 UTC 364d ca no
# apiserver Sep 01, 2027 08:00 UTC 364d ca no
# apiserver-kubelet-client Sep 01, 2027 08:00 UTC 364d ca no
# front-proxy-client Sep 01, 2027 08:00 UTC 364d front-proxy-ca no
# etcd-server Sep 01, 2027 08:00 UTC 364d etcd-ca no
# 用 openssl 逐个核对(不依赖 kubeadm)
sudo openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates -subject -issuer
sudo openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -dates
# 检查 kubelet 自己的证书
sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
kubeadm certs check-expiration 查看所有证书状态
kubeadm certs renew <name> 续期单个证书
kubeadm certs renew all 续期全部叶子证书
kubeadm certs certificate-key 生成 --certificate-key(用于 join 上传证书)
kubeadm certs generate-csr 只生成 CSR,交给外部 CA 签
renew 可接受的
all
admin.conf
apiserver
apiserver-etcd-client
apiserver-kubelet-client
controller-manager.conf
etcd-healthcheck-client
etcd-peer
etcd-server
front-proxy-client
scheduler.conf
super-admin.conf
注意这个列表里没有 ca —— CA 不在 renew 的范围内,这是设计使然,不是遗漏。
# 1. 备份(CA 私钥丢了就是灾难)
sudo cp -a /etc/kubernetes/pki /etc/kubernetes/pki.bak
sudo cp -a /etc/kubernetes/*.conf /etc/kubernetes/conf.bak
# 2. 续期
sudo kubeadm certs renew all
# 3. 必须重启控制平面组件(静态 Pod),否则仍在用旧证书
sudo systemctl restart kubelet
kubectl -n kube-system delete pod -l component=kube-apiserver
kubectl -n kube-system delete pod -l component=kube-controller-manager
kubectl -n kube-system delete pod -l component=kube-scheduler
kubectl -n kube-system delete pod -l component=etcd
# 4. 更新本地 kubeconfig(admin.conf 变了)
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
# 5. 复查
sudo kubeadm certs check-expiration
renew 的行为是无条件续期,不看是否临近过期;SAN 等属性沿用已有证书文件的内容,不需要重新提供。
kubeadm upgrade apply / kubeadm upgrade node 会顺带续期所有 kubeadm 管理的证书,所以保持版本跟进本身就是一种轮换策略。长期不升级的集群,证书到期就会集体失效。
也可以把续期挂到定时任务上:
# /etc/cron.d/kubeadm-cert-renew
0 3 1 * * root kubeadm certs renew all && systemctl restart kubelet
kubelet 有两套证书,轮换机制完全不同 —— 这是最容易被混淆的地方:
# 客户端证书:访问 apiserver 时证明「我是这个节点」
/var/lib/kubelet/pki/kubelet-client-current.pem ← 软链接,指向当前证书
/var/lib/kubelet/pki/kubelet-client-2026-01-01-00-00-00.pem
# 服务端证书:kube-apiserver 反向访问 kubelet(exec/logs/port-forward)时用
/var/lib/kubelet/pki/kubelet.crt ← 默认是自签名的
/var/lib/kubelet/pki/kubelet.key
客户端证书由 KubeletConfiguration 的 rotateCertificates 控制:
# kubeadm 生成的 /var/lib/kubelet/config.yaml 里默认就有这一行
sudo grep -n "rotateCertificates" /var/lib/kubelet/config.yaml
# rotateCertificates: true
轮换流程:证书剩余有效期进入 30%–10% 区间时,kubelet 用 bootstrap token 或已有凭据发起 CSR,由 kube-controller-manager 自动批准并签发新证书(签发时长由 --cluster-signing-duration 决定,默认 1 年)。
服务端证书由另一个开关控制,且默认关闭:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
serverTLSBootstrap: true # 默认 false,kubeadm 不会帮你打开
打开后 kubelet 会发起 kubernetes.io/kubelet-serving 类型的 CSR,这类 CSR 不会被自动批准,需要人工放行:
kubectl get csr
# NAME AGE SIGNERNAME REQUESTOR CONDITION
# csr-abc12 10s kubernetes.io/kubelet-serving system:node:node1 Pending
kubectl describe csr csr-abc12 | grep -A5 "Subject\|DNS Names\|IP Addresses"
kubectl certificate approve csr-abc12
kubeadm 不提供 CA 轮换命令,只能手工做。核心思路是「先双向信任,再逐点切换」:
# 1. 生成新 CA
sudo openssl genrsa -out /etc/kubernetes/pki/ca-new.key 4096
sudo openssl req -x509 -new -nodes -key /etc/kubernetes/pki/ca-new.key \
-subj "/CN=kubernetes" -days 3650 -out /etc/kubernetes/pki/ca-new.crt
# 2. 合并新旧 CA 成一个信任包(过渡期两边都认)
cat /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/ca-new.crt > /etc/kubernetes/pki/ca-combined.crt
# 3. 把合并后的信任包分发到【所有节点】(含 kubelet 的 ca.crt)
sudo cp /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/ca.crt.old
sudo cp /etc/kubernetes/pki/ca-combined.crt /etc/kubernetes/pki/ca.crt
sudo systemctl restart kubelet
# 4. 用新 CA 重签所有组件证书(此时 ca.crt 是合并包,ca-new.key 是新私钥)
sudo kubeadm init phase certs all --config kubeadm-config.yaml
# 5. 验证一切正常后,收敛为只剩新 CA,再滚动重启所有节点
certificateValidityPeriod 与 caCertificateValidityPeriod(Go duration 格式,单位最长到 h)在 ClusterConfiguration 中调整。视图里的 Sep 01, 2027 就是一年后的时间点。kubeadm certs renew 之后必须重启控制平面组件。kube-apiserver、controller-manager、scheduler、etcd 都是以静态 Pod 运行的进程,证书文件被替换后进程不会自动重载 —— 不重启的话,续期等于没做,到期照样挂。官方 kubeadm certs renew 的说明里明确写了 "restart control-plane components"。--rotate-certificates 与 --rotate-server-certificates 是两回事。前者管 kubelet 访问 apiserver 的客户端证书,后者管 kubelet 对外提供服务的服务端证书。kubeadm 默认只开前者,后者对应配置文件里的 serverTLSBootstrap: true,而且它产生的 CSR 需要 kubectl certificate approve 才会生效。RotateKubeletClientCertificate / RotateKubeletServerCertificate 在 1.19 就已 GA 并锁定为 true,老教程里让你加 --feature-gates=RotateKubeletServerCertificate=true 的写法完全过时。今天的开关是 kubelet 配置文件里的两个布尔字段。renew 不会动 CA。kubeadm certs renew all 只是用现有 CA 重签叶子证书;CA 本身到期(10 年)或私钥泄露,必须走上文的手工 CA 轮换流程,那是一次需要停机窗口的重大变更。/etc/kubernetes/pki/ca.crt 校验 apiserver 证书,只换控制平面不换节点,节点会立刻 NotReady,日志里是 x509: certificate signed by unknown authority。过渡期务必用「合并信任包」而不是直接替换。--external-ca 建的、/etc/kubernetes/pki/ca.key 已删除,则 kube-controller-manager 无法签发 kubelet 客户端证书,轮换链条断裂,证书到期需要人工重新签发并分发。kubectl 报 x509: certificate has expired or is not yet valid 不一定是集群挂了。先看是本地 ~/.kube/config 里的管理员证书过期,还是 apiserver 服务端证书过期 —— 前者只要 kubeadm certs renew admin.conf 并更新本地 kubeconfig,后者才需要重启控制平面。kubeadm certs renew all 加重启要一次一台、从主节点开始做,避免同时重启导致 apiserver 全挂。所有控制平面节点都要执行,漏掉任何一台都会在到期日出现单点故障。/etc/kubernetes/pki 与 *.conf。CA 私钥一旦损坏且无备份,整个集群只能重建 —— 这不是夸张,是自建集群最常见的不可恢复事故。super-admin.conf 是 1.29 新增的。它用 system:masters 组身份直连 apiserver,不经过本地 kubeconfig 的 admin.conf;renew 列表里单独有一项,漏续它会留下一个到期就失效的应急入口。kubeadm certs certificate-key 生成的 key 是敏感凭据。kubeadm join --certificate-key 用它解密上传到 kube-system/kubeadm-certs Secret 的证书;这个 Secret 默认有效期 2 小时,过期后 join 会报 the certificate key is invalid。kubeadm — 集群安装与证书管理的主要工具kubelet — 节点代理,客户端证书自带轮换kubectl — 查看与批准 CSRetcd — 独立 CA 与成员间证书serviceaccount — SA 签名密钥与证书体系的关联