K8S 更换 CA 证书
文章目录
证书是 K8S 集群内部通讯的必备配置。K8S 大规模使用到现在也有接近10年时间了,很多搭建的比较早的集群,CA 基本都快过期了,这里记录一下更换 CA 的步骤和注意事项。
先给一下官方文档:https://kubernetes.io/zh-cn/docs/tasks/tls/manual-rotation-of-ca-certificates/
先了解一下证书的分类和用处
一个完整的 K8S 集群,总共需要2个 CA 证书。一个是 K8S 相关组件使用的,另一个是 ETCD 组件使用的。这2个CA 证书,会签发出其他客户端证书。
CA 一般是10年-20年有效期;客户端证书一般是1年有效期,并且可以自动重新签发。
集群的通讯关系如下
ETCD 默认只和 kube-apiserver 通信。如果有监控或者使用 Cilium 等组件,会产生额外的访问,需要一起更新掉相关证书。
- etcd <-> kube-apiserver
- etcd <-> Prometheus, Cilium
其他组件默认只和 kube-apiserver 通信。
- kube-apiserver <-> kube-controller-manager
- kube-apiserver <-> kube-scheduler
- kube-apiserver <-> kube-proxy
- kube-apiserver <-> kubelet
- kube-apiserver <-> kubectl
因为这些通讯一般都是双向验证,所以想成功通讯,必须满足2个条件
- 信任 CA
- 持有 CA 签发的有效证书
基于以上条件,更新 CA 的步骤就是
- 创建新的 CA
- 同时信任新旧 CA (下面都叫 bundle CA )
- 使用新 CA 签发的证书
- 删除旧 CA (部分地方可以跳过)
详细的步骤如下
以下步骤适用于不停机更新的情况,所以较为复杂。如果可以停机,则直接暴力替换(先停止所有服务,再把对应的证书替换到正确的目录下,然后重启服务)即可。
一、准备工作
- 创建新的 CA
- 使用新的 CA 签发需要的全部证书
- 把旧的 CA 追加到新 CA 里面
二、更新 ETCD CA 和 证书
先备份 ETCD 数据
查看 ETCD 状态
alias et='etcdctl --endpoints=192.168.10.101:2379,192.168.10.102.2379,192.168.10.103.2379 --cacert=/etc/etcd/ssl/ca-etcd.pem --cert=/etc/etcd/ssl/cert-etcd.pem --key=/etc/etcd/ssl/cert-etcd-key.pem'
et endpoint status -w table
备份 ETCD DB
et1 snapshot save etcd-backup-$(date +%Y%m%d).db
检查备份文件
et1 snapshot status etcd-backup-$(date +%Y%m%d).db --write-out=table更新 ETCD 使用 CA bundle 证书
1. 先更新 ETCD 使用 CA bundle 证书,然后重启 ETCD 节点。【在每个 ETCD 节点上执行】
--trusted-ca-file "/etc/ssl/certs/ca-etcd-bundle.pem" \
--peer-trusted-ca-file "/etc/ssl/certs/ca-etcd-bundle.pem" \
上一步做完之后,每个 ETCD 节点都同时信任新旧 CA 证书。
下面可以更新客户端证书了。
2. 使用新 CA 签发的客户端证书 `cert-etcd.pem` 和 `cert-etcd-key.pem`,然后重启 ETCD 节点生效。
--client-cert-auth \
--trusted-ca-file "/etc/ssl/certs/ca-etcd-bundle.pem" \ # 上一步的修改
--cert-file "/etc/ssl/certs/cert-etcd.pem" \ # 新签发的证书
--key-file "/etc/ssl/certs/cert-etcd-key.pem" \ # 新签发的证书
--peer-client-cert-auth \
--peer-trusted-ca-file "/etc/ssl/certs/ca-etcd-bundle.pem" \ # 上一步的修改
--peer-cert-file "/etc/ssl/certs/cert-etcd.pem" \ # 新签发的证书
--peer-key-file "/etc/ssl/certs/cert-etcd-key.pem" \ # 新签发的证书到这里 ETCD 之间已经使用新的 CA 进行通讯了。但是 kube-apiserver 还是使用旧的 CA 证书和 ETCD 通讯。
三、更新 K8S 组件使用 CA bundle 证书
更新 kube-controller-manager
确认 Controller Manager 的主节点
kubectl get lease -n kube-system
ssh 到非主控节点,更新 kube-controller-manager.yaml 使用新 CA 证书
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
- --cluster-signing-cert-file=/etc/kubernetes/ssl/new-ca/ca-kubernetes.pem # 保证使用的是新的 CA ,这里不能使用 Bundle CA
- --cluster-signing-key-file=/etc/kubernetes/ssl/new-ca/ca-kubernetes-key.pem # 保证使用的是新的 CA key
- --root-ca-file=/etc/kubernetes/ssl/new-ca/ca-kubernetes-bundle.pem # 老的和新的 bundle CA
使用 docker stop 来重启 Controller-Manager 容器。
在每一个节点上执行。且保证主节点是最后一个做。
检查 Default 命名空间里的 ServiceAccount 证书,查看是否自动更新成 Bundle CA 证书。
重启所有使用了 Service Account 的集群内服务:比如 coredns, kubeproxy 等。更新 kube-apiserver 使用 Bundle CA 证书
# 更新 kube-apiserver.yaml 使用 Bundle CA 证书
vim /etc/kubernetes/manifests/kube-apiserver.yaml
- --client-ca-file=/etc/kubernetes/ssl/new-ca/ca-kubernetes-bundle.pem
# 使用 docker stop 来重启 API Server
# 在每一个节点上执行并重启服务。更新 kube-controller-manager 的 client-ca-file 使用新 CA 证书
# 这个证书是用于和 API Server 通信的,所以需要上一步完成之后,才做这一步。
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
- --client-ca-file=/etc/kubernetes/ssl/new-ca/ca-kubernetes.pem # 保证使用的是新的 CA 证书。这里只能使用单CA证书,不能使用 Bundle CA !!!
# 在每一个节点上执行并重启服务。更新 kube-scheduler.yaml 使用 Bundle CA 证书
vim /etc/kubernetes/scheduler.conf
certificate-authority: /etc/kubernetes/ssl/new-ca/ca-kubernetes-bundle.pem
# 在每一个节点上执行并重启服务。更新 kubelet 节点使用 Bundle 证书
vim /etc/kubernetes/kubelet.conf
certificate-authority: /etc/kubernetes/ssl/new-ca/ca-kubernetes-bundle.pem
# 在每一个节点上执行并重启服务。
四、更新控制节点使用新 CA 签发的客户端证书
更新到这里如果没有错误,后面就可以正常更新节点证书了。
期间 API Server 会出现少量 非法的 beader token 错误,可以忽略。全部的控制节点更新完成之后,这个错误就会消失。
五、最后更新其他地方使用到的客户端证书
- 比如 Prometheus 监控 ETCD 或者 Kubelet 的情况会用到的证书。
- 还有 kubeconfig 文件里的 CA 和 Client 证书等等。Kubeconfig 的里的 CA 可以写多个,但是好像默认使用第一个。
写在最后
如果中间某一步出现了问题,怎么办?
答:肯定是证书文件没放对! 一个一个检查证书文件。
如果实在没有检查出来哪里有问题,怎么办?
答:直接停止全部的服务,然后把正确的证书文件复制到对应目录,然后启动服务。直接暴力全部替换。