關於kubernetes1.9證書過期(certificate has expired or is not yet valid)

膽戰心驚的一天

今天突然收到告警,k8s的節點NotReady,我靠!嚇了一身冷汗,遂遠程登錄上去查看,果然都是notready!這一嚇真是不輕啊,要知道所有node節點掛掉,等於整個集羣掛掉了,線上的服務都不能訪問。當時要是採訪我當時在想什麼,我只能高冷的回答你:“啥都沒想”,當時真是腦袋一片空白。
不過呢,辛好留了一手,使用k8s之前,也用虛擬機把k8s上的服務也部署了一遍,就是防止這種現象出現,當時也考慮到k8s集羣會有坑,沒想到這麼深,直接導致整個集羣不可用。部署的時候在想最好不要用到,果不其然,天不遂人願,竟然真的用到了。所以說多做些應急準備工作,就顯得非常有必要了。
既然對客戶訪問和使用不會造成影響,心裏如釋重負,壓力不是很大了。開始着手排查問題。

一、問題現象

Kubernetes 集羣日誌中出現

Apr 08 17:22:36 beta-k8s-master-1 kube-apiserver[1020]: E0408 17:22:36.857055    1020 authentication.go:64] Unable to authenticate the request due to an error: [x509: certificate has expired or is not yet valid, x509: certificate has expired or is not yet valid] 

還有以下日誌信息

Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.194226    3969 kubelet_node_status.go:383] Error updating node status, will retry: error getting node "node02": Unauthorized
Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.195088    3969 kubelet_node_status.go:383] Error updating node status, will retry: error getting node "node02": Unauthorized
Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.195961    3969 kubelet_node_status.go:383] Error updating node status, will retry: error getting node "node02": Unauthorized
Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.196918    3969 kubelet_node_status.go:383] Error updating node status, will retry: error getting node "node02": Unauthorized
Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.197846    3969 kubelet_node_status.go:383] Error updating node status, will retry: error getting node "node02": Unauthorized
Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.197870    3969 kubelet_node_status.go:375] Unable to update node status: update node status exceeds retry count
Apr 08 15:34:25 node02 kubelet[3969]: E0408 15:34:25.220090    3969 reflector.go:205] k8s.io/kubernetes/pkg/kubelet/config/apiserver.go:47: Failed to list *v1.Pod: Unauthorized

以上信息顯示證書過期了

二、排查思路

1.服務器時間不對,導致證書過期:登上k8s節點查看日誌,發現時間都是北京時間,分秒不差。。。
2.確實證書過期了:
我的集羣是自己手動搭建的,並沒有通過kubeadm安裝,證書也是手動一個個作的。

$ openssl x509 -in /root/cfssl/kubernetes/kubernetes-root-ca.pem  -noout -text |grep ' Not '
            Not Before: Apr  3 09:17:00 2018 GMT
            Not After : Apr  2 09:17:00 2023 GMT
$ openssl x509 -in /root/cfssl/kubernetes/kubernetes-client-proxy.pem  -noout -text |grep ' Not '                      
            Not Before: Apr  4 07:52:00 2018 GMT
            Not After : Apr  3 07:52:00 2023 GMT
$ openssl x509 -in /root/cfssl/kubernetes/kubernetes-client-kubectl.pem  -noout -text |grep ' Not '                           
            Not Before: Apr  3 09:29:00 2018 GMT
            Not After : Apr  2 09:29:00 2023 GMT

發現證書有效期是5年,還差好幾年呢,日誌怎麼會報證書過期呢?
集羣分爲兩種證書:
1.用於集羣 Master、Etcd等通信的證書。
2.用於集羣 Kubelet 組件證書。

這時坑位出現了:
我們在搭建 Kubernetes 集羣時,一般只聲明用於集羣 Master、Etcd等通信的證書 爲 10年 或者 更久,但未聲明集羣 Kubelet 組件證書 ,Kubelet 組件證書 默認有效期爲1年。集羣運行1年以後就會導致報 certificate has expired or is not yet valid 錯誤,導致集羣 Node不能於集羣 Master正常通信,node顯示是NotReady狀態。

三、解決問題

分兩種解決方案:
1.臨時解決證書問題:
重啓node節點上kube-proxy 和 kubelet 服務,

systemctl  restart kubelet && systemctl  restart kube-proxy

刪除NotReady節點重新加入k8s集羣

$ kubectl  delete  node  beta-k8s-node-1 beta-k8s-node-2 beta-k8s-node-3
$ kubectl get csr
$ kubectl certificate approve node-csr-T4t2IpJvE73djBPsqq-xx3FnMWOLTFyPNK-sQ
$ kubectl certificate approve node-csr-_FaAvAIsXGZ4_vYfbT43xxwX9kMJCKDElfsRwA 
$ kubectl certificate approve node-csr-nHBw2mUbjxK9ZZLvxpOx_gxxx9VYBDlUCKybW6Y8D4

最後查看弄的狀態都已經是ready了。服務也恢復正常

2.永久性解決證書問題(配置證書自動重載、輪轉)

添加參數:
修改 kubelet 組件配置,具體添加下面參數

--feature-gates=RotateKubeletServerCertificate=true
--feature-gates=RotateKubeletClientCertificate=true
# 1.8版本以上包含1.8都支持證書更換自動重載,以下版本只能手動重啓服務
--rotate-certificates

修改 controller-manager 組件配置,具體添加下面參數

# 證書有效期爲10年
--experimental-cluster-signing-duration=87600h0m0s
--feature-gates=RotateKubeletServerCertificate=true

創建自動批准相關 CSR 請求的 ClusterRole

vim tls-instructs-csr.yaml && kubectl apply -f tls-instructs-csr.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups: ["certificates.k8s.io"]
  resources: ["certificatesigningrequests/selfnodeserver"]
  verbs: ["create"]

自動批准 kubelet-bootstrap 用戶 TLS bootstrapping 首次申請證書的 CSR 請求

kubectl create clusterrolebinding node-client-auto-approve-csr --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --user=kubelet-bootstrap

自動批准 system:nodes 組用戶更新 kubelet 自身與 apiserver 通訊證書的 CSR 請求

kubectl create clusterrolebinding node-client-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --group=system:nodes

自動批准 system:nodes 組用戶更新 kubelet 10250 api 端口證書的 CSR 請求

kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeserver --group=system:nodes

重啓kube-controller-manager 和 kubelet 服務

$ systemctl restart kube-controller-manager

# 進入到ssl配置目錄,刪除 kubelet 證書
$ rm -f kubelet-client-current.pem kubelet-client-2019-05-10-09-57-21.pem kubelet.key kubelet.crt

# 重啓啓動,啓動正常後會頒發有效期10年的ssl證書
$ systemctl restart kubelet


# 進入到ssl配置目錄,查看證書有效期
$ openssl x509 -in kubelet-client-current.pem -noout -text | grep "Not"

Not Before: May 13 02:36:00 2019 GMT
Not After : May 10 02:36:00 2029 GMT
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章