kubeadm拉起的k8s集群证书过期的做法
这个是很久之前遇到的了,今天有空(心血来潮)就都回忆回忆写在这里为爱发光,部分内容来自arch先生(死党)的帮助。
有时候有很多部门提了建k8s的需求,有些是临时的,有些没有说具体用多久,但是某天,他们和你说集群坏了,这时候你上去一看证书过期了,这里又有两种情况我们分别说明:
集群还活着
集群已归西(麻烦事儿)
集群还活着
bash
#查看证书过期时间
kubeadm certs check-expiration
#如果过期就更新
kubeadm certs renew all
#更新完证书再次查看
kubeadm certs check-expiration
#更新完证书后还需要重启api-server,controller-manager,scheduler,etcd
#看看有没有这个文件
ll /etc/crictl.yaml
#没有就主动生成
echo "runtime-endpoint: unix:///run/containerd/containerd.sock" \
| tee /etc/crictl.yaml
containerd执行脚本更新相关服务
pods="crictl pods --namespace kube-system --state READY"
for component in kube-apiserver kube-controller-manager kube-scheduler etcd; do
echo "> `date +%DT%T` Restart $component"
$pods | grep "$component" | awk '{print "crictl stopp "$1 | "sh"}'
sleep 5
echo "---------------------------------------"
done
使用kubectl获取集群资源看是否正常。
集群已归西
此时集群无法连接、无法管理,甚至无法启动
1、备份数据
bash
mkdir ~/recovery
sudo rsync -av /etc/kubernetes/ ~/recovery/etc-kubernetes/
sudo rsync -av /var/lib/etcd/ ~/recovery/var-lib-etcd/
sudo rsync -av /var/lib/kubelet/ ~/recovery/var-lib-kubelet/
2、报错内容及分析
bash
journalctl -u kubelet.service
kubelet[2447]: E0923 bootstrap.go:265] part of the existing bootstrap client certificate in /etc/kubernetes/kubelet.conf is expired: xxxxxxxxx
显而易见,kubelet 使用的证书过期了
查看 /etc/kubernetes/kubelet.conf 内容,看它使用的证书文件路径
yaml
users:
- name: system:node:xxxx
user:
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
接着进入 /var/lib/kubelet/pki kubelet 的证书、私钥都在这里,而且还有一个 kubelet.conf 引用的 pem 文件
.crt + .key = .pem
接着解析 kubelet.crt 内容
bash
openssl x509 -in kubelet/pki/kubelet.crt -noout -text
Certificate:
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Jan 6 15:53:54 2022 GMT
Not After : Jan 6 15:53:54 2023 GMT
Subject: O=system:nodes, CN=system:node:vm-m1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:vm-m1
主机名是 vm-m1,被 CN 和 DNS 用到
Subject 格式 O=system:nodes, CN=system:node:${主机名}
DNS 格式 ${主机名}
3、生成证书
由于过期的是 kubelet 使用的证书,而 ca 没过期,因此基于已有 ca 生成证书
node_name=vm-m1
bash
#生成 EC 私钥 (P-256 椭圆曲线)
openssl ecparam -genkey -name prime256v1 -noout -out kubelet.key
#创建证书签署请求 (CSR)
openssl req -new -key kubelet.key -out kubelet.csr -subj "/O=system:nodes/CN=system:node:${node_name}"
#引用已有 ca,生成 crt 证书
openssl x509 -req -in kubelet.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out kubelet.crt \
-days 365 \
-extensions v3_req \
-extfile <(cat <<EOF
[ v3_req ]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = ${node_name}
EOF
)
4、证书内容合并
date_time= ( d a t e + c a t k u b e l e t . c r t > k u b e l e t − c l i e n t − (date +%F-%H-%M-%S) cat kubelet.crt > kubelet-client- (date+catkubelet.crt>kubelet−client−{date_time}.pem
cat kubelet.key >> kubelet-client-${date_time}.pem
5、证书替换
bash
systemctl stop kubelet.service
cp -vf kubelet.crt kubelet.key /var/lib/kubelet/pki/
cd /var/lib/kubelet/pki/
ln -sf /var/lib/kubelet/pki/kubelet-client-${date_time}.pem kubelet-client-current.pem
systemctl start kubelet.service
6、证书生效
当然这个场景下也得同步更新其他组件的证书
bash
kubeadm certs renew all
接着刷新各个组件使用的证书,更建议直接 reboot 刷新