k8s 证书更新

确定问题的过程:

由于项目要验收,于是上服务器看了一下 k8s 的状态,发现报错了:

由于对 k8s 不是很懂并且好久没整了,就去问通义,通义让我去看一下 kubelet 的状态(这个我想到了,但是我执行的命令是 systemctl status kubectl,真是全忘了):

systemctl status kubelet

发现 kubelet 正常运行,但是日志报错如下:

10月 09 10:41:55 kctd kubelet[1182]: E1009 10:41:55.655679    1182 kubelet_node_status.go:92] "Unable to register node with API server" err="Post \"https://(本机ip省略了):6443/api/v1/nodes\": dial tcp (省略)>

问了通义,它解释该报错的意思为:

kubelet 正在尝试向 Kubernetes API Server (在 master)注册本节点,但连接被拒绝

于是按照通义给出的方法依次检查错误在哪:

1、确认本机 IP 是否变化:没变

2、检查 API Server 是否在运行:看了 docker,还在运行

2、使用 docker logs 查看 API Server 容器日志:错误找到了,报错如下:

W1009 02:44:05.846601       1 clientconn.go:1331] [core] grpc: addrConn.createTransport failed to connect to {127.0.0.1:2379 127.0.0.1 <nil> 0 <nil>}. Err: connection error: desc = "transport: authentication handshake failed: x509: certificate has expired or is not yet valid: current time 2025-10-09T02:44:05Z is after 2025-03-25T02:23:15Z". Reconnecting...

交给通义得出结论:etcd 的 TLS 证书已过期!

  • 当前时间:2025-10-09
  • 证书有效期截止:2025-03-25
  • 已过期 近 7 个月

这是导致 etcd 无法启动kube-apiserver 无法连接 etcdAPI Server 无法提供服务kubectl 连接被拒绝 的根本原因。

关于证书为什么会过期的说明:

kubeadm 部署的集群中:

  • etcd 默认以静态 Pod 方式运行在 control-plane 节点上
  • etcd 使用 TLS 证书进行客户端/对端认证
  • 这些证书由 kubeadmkubeadm init 时生成,默认有效期为 1 年

解决问题的过程

结合通义的说法和网上的博文,以及实操,总结如下过程:

以下操作都在 master 节点操作,我的 k8s 版本为 v1.23.5

1. 查看证书过期时间

# 通过命令查看证书过期时间
kubeadm certs check-expiration

2. 备份文件

# 将 k8s 和 etcd 相关文件备份
cp -r /etc/kubernetes /etc/kubernetes.bak
cp -r /var/lib/etcd /var/lib/etcd.bak

3. 证书更新

kubeadm certs renew all          # v1.14 及更早版本,已废弃(deprecated)
kubeadm alpha certs renew all    # v1.15 及之后版本
# 注意:从 v1.19+ 起,kubeadm alpha certs 已被完全移除,执行会报错。

4. 更新管理员访问凭证并重启 kubelet

cp -r /root/.kube /root/.kube.bak   # 备份管理员访问凭证
kubeadm init phase kubeconfig all   # 该命令会(使用新的证书)更新 kubeconfig 文件
cp -f /etc/kubernetes/admin.conf /root/.kube/config   # -f 选项强制覆盖

systemctl restart kubelet	# 重启控制平面组件

kubectl get node  # 经过测试,发现成功

对解决问题每一步的说明

第二步说明

/etc/kubernetes —— Kubernetes 的配置与证书目录

这是 kubeadm 初始化集群时创建的核心配置目录,提供 组件间安全通信所需的证书服务启动配置。包含:

文件/子目录 作用
admin.conf 集群管理员的 kubeconfig 文件(kubectl 默认读取 ~/.kube/config,通常就是它)
kubelet.conf kubelet 连接 API Server 所用的配置
controller-manager.conf kube-controller-manager 的 kubeconfig
scheduler.conf kube-scheduler 的 kubeconfig
pki/ 所有 TLS 证书和私钥,包括: – ca.crt / ca.key(根证书) – apiserver.crt / .keyetcd/(etcd 专用证书) – front-proxy-ca.crt
manifests/ 静态 Pod 清单目录 kubelet 会自动在此目录创建 Pod: – kube-apiserver.yamletcd.yamlkube-controller-manager.yamlkube-scheduler.yaml

如果这个目录丢失,你将无法恢复集群的认证体系和控制平面配置,即使数据还在,也无法安全地重建 API Server。

/var/lib/etcd —— etcd 数据存储目录(集群的“数据库”)

  • etcd 是 Kubernetes 的唯一状态存储后端持久化整个集群的状态。所有资源(Pod、Service、Node、ConfigMap 等)都保存在这里。

  • /var/lib/etcd 是 etcd 的数据目录(默认路径),里面包含:

    • WAL(Write-Ahead Log)日志
    • 快照(snapshots)
    • 实际的键值数据(以 BoltDB 或 MVCC 格式存储)
  • 如果你丢失 /var/lib/etcd所有 Kubernetes 资源都会永久消失(即使重新 kubeadm init,也是一个全新空集群)。

  • 只要这个目录完好,配合正确的证书和配置,可以恢复整个集群状态

  • 注意:

    • 直接 cp -r 备份 etcd 数据目录 仅适用于单节点 etcd 且服务已停止的情况
    • 在 etcd 运行时直接复制,可能导致数据不一致(因为文件在变化)。
    • 生产环境应使用 etcdctl snapshot save 做一致性快照备份。

第三步说明

kubeadm certs renew all重新生成以下证书(默认有效期 1 年),位于 /etc/kubernetes/pki/ 目录下:

证书类型 文件路径
Kubernetes API Server /etc/kubernetes/pki/apiserver.crt
API Server ↔ kubelet 客户端 /etc/kubernetes/pki/apiserver-kubelet-client.crt
前端代理(Aggregator) /etc/kubernetes/pki/front-proxy-client.crt
etcd 服务端 /etc/kubernetes/pki/etcd/server.crt
etcd 节点间通信(peer) /etc/kubernetes/pki/etcd/peer.crt
etcd 健康检查客户端 /etc/kubernetes/pki/etcd/healthcheck-client.crt

不会更新 CA 证书ca.crt, etcd/ca.crt),因为 CA 通常有效期更长(10 年),且更新 CA 会导致所有下游证书失效,需全量重签。

第四步说明

  • /etc/kubernetes 目录

    • 提供 组件间安全通信所需的证书服务启动配置
  • /var/lib/etcd 目录

    • 持久化整个集群的状态
  • /root/.kube/config 文件

    • 一个 kubeconfig 文件,通常就是 /etc/kubernetes/admin.conf 的副本

    • 作用:

      • kubectl 能以 集群管理员身份 安全地连接 API Server,这样才能使用 kubectl 命令。
    • 包含:

      • API Server 地址(如 https://10.0.0.1:6443
      • CA 证书(certificate-authority-data
      • 客户端证书和私钥(client-certificate-data / client-key-data
    • 其他说明:

      • 相当于管理员的“门禁卡 + 身份证”。 普通用户也可以有自己的 ~/.kube/config,但权限由证书或 token 决定。
      • 波浪号 ~ 表示当前登录用户的目录,root 用户和普通用户的目录不一样,存放的配置文件也不一样,就可以用来控制不同用户的权限(大概是这样?)。此外,创建配置文件时,一定要注意该文件的权限,不要让普通用户有修改配置文件的权限
  • 工作流程示例:kubectl get pods

    1. kubectl 读取 /root/.kube/config
    2. 使用其中的 客户端证书CA 证书,向 https://<API_SERVER>:6443 发起 TLS 连接
    3. API Server 验证客户端证书(是否属于 system:masters 组)
    4. 验证通过后,API Server 从 /var/lib/etcd 查询 Pod 数据
    5. 返回结果给 kubectl
  • 执行完证书更新命令后,以下配置文件内嵌了旧的客户端证书(base64 编码),即使底层 .crt 文件已更新,它们内容不会变!

    • /etc/kubernetes/admin.conf
    • /etc/kubernetes/kubelet.conf
    • /etc/kubernetes/controller-manager.conf
    • /etc/kubernetes/scheduler.conf
  • 所以需要 kubeadm init phase kubeconfig all 命令更新配置文件,并将其复制到 /root/.kube/ 目录下

参考:

[1] k8s证书更新,kubeadm安装的K8S证书过期后无法使用后证书更新方法

[2] 通义千问

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐