k8s

二进制k8s集群更换ca证书后报错解决

报错1

有一套老环境,集群版本是1.14,集群的ca证书要过期了,更换了集群的ca证书,重新生成相关证书文件,证书名叫Kubernetes,重启etcd,apiserver,controller-manager,scheduler,kube-proxy,kubelet后,node节点变为NotReady状态,所有node节点的kubelet都有如下的报错:

 error getting node "1.2.3.4": Get https://127.0.0.1:10250/api/v1/nodes/1.2.3.4?resourceVersion=0&timeout=10s:  x509:certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "Kubernetes")

file

apiserver报错:

http: TLS handshake error from 1.2.3.4:12345: remote error: tls: unknown certificate authority

file

etcd报错:

rejected connection from "1.2.3.4:33333" (error "remote error: tls: bad certificate", ServerName "")

file

解决

上面etcd的报错中拒绝连接的都是node节点的连接。etcd是只会连接apiserver的,不会连接node节点。但日志中显示有node节点的连接,这是为什么呢?查看集群的网络组件是calico,猜测calico是否使用了etcd为后端存储,然后节点的calico-node连到了etcd上。

kubectl get cm -n kube-system calico-config -o yaml

file

发现calico果然使用了etcd为后端存储。那就需要修改calico的secret中的ca证书。

kubectl get secret -n kube-system calico-etcd-secrets -o yaml
cat ca.pem | base64 -w 0 > etcd-ca
cat etcd.pem | base64 -w 0 > etcd-cert
cat etcd-key.pem | base64 -w 0 > etcd-key
kubectl edit secret -n kube-system calico-etcd-secrets

重启calico-node,pod处于pending状态,集群还是同样的报错没有恢复。说明还是kubelet的问题。

查看节点的kubelet配置。

ps aux |grep kubelet
cat /srv/kubernetes/10.conf

file

现在kubelet连接apiserver异常,无法更新节点状态。上面的certificate-authority-data即ca证书已经手动更新了,那问题就出现在下面的kubelet客户端证书kubelet-client-current.pem。这个证书用于确保apiserver在与kubelet通信时能够证明自己的身份。可以通过kube-controller-manager自动续签也可以手动更新。由于还没过期所以手动更新证书。

cd /var/lib/kubelet/pki
mv kubelet-client-current.pem ..
systemctl restart kubelet

移走后证书并没有自动生成。查看kube-controller-manager已经启用了RotateKubeletServerCertificate=true。这里就涉及到k8s的证书管理机制了。k8s使用 CSR(Certificate Signing Request)机制来管理节点和组件的证书。查看是否有csr请求。发现果然有一个,审批后节点的kubelet日志恢复正常,节点状态变为Ready。

kubectl certificate approve <csr-name>

同时kubelet日志中会有如下输出,证明kubelet已经使用了新的证书。

certificate rotation detected ,shutting down client connections to start using new credentials

问题2

所有节点的状态恢复Ready后,calico-node和controller状态都变为Running了,但是查看coreDNS日志仍然有证书报错。

file

想起来sa会自动生成一个secret,这个secret中会包含ca证书,但这个secret如果没有删除不会自动刷新,也就是说coreDNS仍然使用的旧的ca。手动删除这个secret让它自动生成即可。

kubectl get sa -n kube-system coredns -o yaml
kubectl get secret -n kube-system coredns-token-hqqnv -o yaml
kubectl delete secret -n kube-system coredns-token-hqqnv

file

secret重新生成后,重启coreDNS的pod,恢复正常。其他有同样的报错的也需要删除sa相关的secret,重启pod。

问题3

使用kubectl logs查看pod日志会报证书错误,但是在主机上查看容器日志没有报错。

解决

容器日志没有问题说明不是容器的问题,而且有多个pod都有同样的输出,那就还是kubelet的问题。
上面kubelet-client-current.pem的目录pki中还有一个文件:kubelet-server-current.pem该文件用于kubelet服务器端,与其他组件如apiserver、节点上的其他服务进行安全通信。

使用kubectl logs命令时会发送到apiserver,然后apiserver会发送请求到pod节点上的kubelet服务,然后kubelet通过CRI接口从容器的文件系统中获取日志再返回给apiserver。

kubelet接收到apiserver的请求后会使用kubelet-server-current.pem来证明自己的身份,并加密通信内容由于证书中的ca证书未更新导致无法证明自己的身份。所以需要更新该证书。具体步骤同上,删除证书,重启kubelet,批准csr,重启pod即可。

分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
最旧
最新 最多投票
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x