更新一個10年有效期的 Kubernetes 證書
使用 kubeadm 安裝 kubernetes 集群非常方便,但是也有一個比較煩人的問題就是默認(rèn)的證書有效期只有一年時間,所以需要考慮證書升級的問題,本文的演示集群版本為 v1.16.2 版本,不保證下面的操作對其他版本也適用,在操作之前一定要先對證書目錄進(jìn)行備份,防止操作錯誤進(jìn)行回滾。本文主要介紹兩種方式來更新集群證書。
手動更新證書
由 kubeadm 生成的客戶端證書默認(rèn)只有一年有效期,我們可以通過 check-expiration 命令來檢查證書是否過期:
$ kubeadm alpha certs check-expirationCERTIFICATE EXPIRES RESIDUAL TIME EXTERNALLY MANAGEDadmin.conf Nov 07, 2020 11:59 UTC 73d noapiserver Nov 07, 2020 11:59 UTC 73d noapiserver-etcd-client Nov 07, 2020 11:59 UTC 73d noapiserver-kubelet-client Nov 07, 2020 11:59 UTC 73d nocontroller-manager.conf Nov 07, 2020 11:59 UTC 73d noetcd-healthcheck-client Nov 07, 2020 11:59 UTC 73d noetcd-peer Nov 07, 2020 11:59 UTC 73d noetcd-server Nov 07, 2020 11:59 UTC 73d nofront-proxy-client Nov 07, 2020 11:59 UTC 73d noscheduler.conf Nov 07, 2020 11:59 UTC 73d no
該命令顯示 /etc/kubernetes/pki 文件夾中的客戶端證書以及 kubeadm 使用的 KUBECONFIG 文件中嵌入的客戶端證書的到期時間/剩余時間。
注意:kubeadm 不能管理由外部 CA 簽名的證書,如果是外部的證書,需要自己手動去管理證書的更新。
另外需要說明的是上面的列表中沒有包含 kubelet.conf,因?yàn)?kubeadm 將 kubelet 配置為自動更新證書。
另外 kubeadm 會在控制面板升級的時候自動更新所有證書,所以使用 kubeadm 搭建的集群最佳的做法是經(jīng)常升級集群,這樣可以確保你的集群保持最新狀態(tài)并保持合理的安全性。但是對于實(shí)際的生產(chǎn)環(huán)境我們可能并不會去頻繁的升級集群,所以這個時候我們就需要去手動更新證書。
要手動更新證書也非常方便,我們只需要通過 kubeadm alpha certs renew 命令即可更新你的證書,這個命令用 CA(或者 front-proxy-CA )證書和存儲在 /etc/kubernetes/pki 中的密鑰執(zhí)行更新。
注意:如果你運(yùn)行了一個高可用的集群,這個命令需要在所有控制面板節(jié)點(diǎn)上執(zhí)行。
接下來我們來更新我們的集群證書,下面的操作都是在 master 節(jié)點(diǎn)上進(jìn)行,首先備份原有證書:
$ mkdir /etc/kubernetes.bak$ cp -r /etc/kubernetes/pki/ /etc/kubernetes.bak$ cp /etc/kubernetes/*.conf /etc/kubernetes.bak$?cp?/etc/kubernetes/manifests/?etc/kubernetes/manifests.bak
然后備份 etcd 數(shù)據(jù)目錄:
$ cp -r /var/lib/etcd /var/lib/etcd.bak接下來執(zhí)行更新證書的命令:
$ kubeadm alpha certs renew all --config=kubeadm.yamlkubeadm alpha certs renew all --config=kubeadm.yamlcertificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewedcertificate for serving the Kubernetes API renewedcertificate the apiserver uses to access etcd renewedcertificate for the API server to connect to kubelet renewedcertificate embedded in the kubeconfig file for the controller manager to use renewedcertificate for liveness probes to healthcheck etcd renewedcertificate for etcd nodes to communicate with each other renewedcertificate for serving etcd renewedcertificate for the front proxy client renewedcertificate embedded in the kubeconfig file for the scheduler manager to use renewed
通過上面的命令證書就一鍵更新完成了,這個時候查看上面的證書可以看到過期時間已經(jīng)是一年后的時間了:
$ kubeadm?alpha?certs?check-expirationCERTIFICATE EXPIRES RESIDUAL TIME EXTERNALLY MANAGEDadmin.conf Aug 26, 2021 03:47 UTC 364d noapiserver Aug 26, 2021 03:47 UTC 364d noapiserver-etcd-client Aug 26, 2021 03:47 UTC 364d noapiserver-kubelet-client Aug 26, 2021 03:47 UTC 364d nocontroller-manager.conf Aug 26, 2021 03:47 UTC 364d noetcd-healthcheck-client Aug 26, 2021 03:47 UTC 364d noetcd-peer Aug 26, 2021 03:47 UTC 364d noetcd-server Aug 26, 2021 03:47 UTC 364d nofront-proxy-client Aug 26, 2021 03:47 UTC 364d noscheduler.conf Aug 26, 2021 03:47 UTC 364d no
然后記得更新下 kubeconfig 文件:
$ kubeadm init phase kubeconfig all --config kubeadm.yaml[] Using kubeconfig folder "/etc/kubernetes"[] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"[] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"[] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"[] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"
將新生成的 admin 配置文件覆蓋掉原本的 admin 文件:
$ mv $HOME/.kube/config $HOME/.kube/config.old$ cp -i /etc/kubernetes/admin.conf $HOME/.kube/config$ chown $(id -u):$(id -g) $HOME/.kube/config
完成后重啟 kube-apiserver、kube-controller、kube-scheduler、etcd 這4個容器即可,我們可以查看 apiserver 的證書的有效期來驗(yàn)證是否更新成功:
$ echo | openssl s_client -showcerts -connect 127.0.0.1:6443 -servername api 2>/dev/null | openssl x509 -noout -enddatenotAfter=Aug 26 03:47:23 2021 GMT
可以看到現(xiàn)在的有效期是一年過后的,證明已經(jīng)更新成功了。
用 Kubernetes 證書 API 更新證書
除了上述的一鍵手動更新證書之外,還可以使用 Kubernetes 證書 API 執(zhí)行手動證書更新。對于線上環(huán)境我們可能并不會去冒險經(jīng)常更新集群或者去更新證書,這些畢竟是有風(fēng)險的,所以我們希望生成的證書有效期足夠長,雖然從安全性角度來說不推薦這樣做,但是對于某些場景下一個足夠長的證書有效期也是非常有必要的。有很多管理員就是去手動更改 kubeadm 的源碼為10年,然后重新編譯來創(chuàng)建集群,這種方式雖然可以達(dá)到目的,但是不推薦使用這種方式,特別是當(dāng)你想要更新集群的時候,還得用新版本進(jìn)行更新。其實(shí) Kubernetes 提供了一種 API 的方式可以來幫助我們生成一個足夠長證書有效期。
要使用內(nèi)置的 API 方式來簽名,首先我們需要配置 kube-controller-manager 組件的 --experimental-cluster-signing-duration 參數(shù),將其調(diào)整為10年,我們這里是 kubeadm 安裝的集群,所以直接修改靜態(tài) Pod 的 yaml 文件即可:
$ vi /etc/kubernetes/manifests/kube-controller-manager.yaml......spec:containers:- command:- kube-controller-manager# 設(shè)置證書有效期為 10 年- --experimental-cluster-signing-duration=87600h- --client-ca-file=/etc/kubernetes/pki/ca.crt......
修改完成后 kube-controller-manager 會自動重啟生效。然后我們需要使用下面的命令為 Kubernetes 證書 API 創(chuàng)建一個證書簽名請求。如果您設(shè)置例如 cert-manager 等外部簽名者,則會自動批準(zhǔn)證書簽名請求(CSRs)。否者,您必須使用 kubectl certificate 命令手動批準(zhǔn)證書。以下 kubeadm 命令輸出要批準(zhǔn)的證書名稱,然后等待批準(zhǔn)發(fā)生:
kubeadm alpha certs renew all --use-api --config kubeadm.yaml &輸出類似于以下內(nèi)容:
[] 2890[] Certificate request "kubeadm-cert-kubernetes-admin-pn99f" created
然后接下來我們需要去手動批準(zhǔn)證書:
kubectl get csrNAME AGE REQUESTOR CONDITIONkubeadm-cert-kubernetes-admin-pn99f 64s kubernetes-admin Pending手動批準(zhǔn)證書kubectl certificate approve kubeadm-cert-kubernetes-admin-pn99fcertificatesigningrequest.certificates.k8s.io/kubeadm-cert-kubernetes-admin-pn99f approved
用同樣的方式為處于 Pending 狀態(tài)的 csr 執(zhí)行批準(zhǔn)操作,直到所有的 csr 都批準(zhǔn)完成為止。最后所有的 csr 列表狀態(tài)如下所示:
$ kubectl get csrNAME AGE REQUESTOR CONDITIONkubeadm-cert-front-proxy-client-llhrj 30s kubernetes-admin Approved,Issuedkubeadm-cert-kube-apiserver-2s6kf 2m43s kubernetes-admin Approved,Issuedkubeadm-cert-kube-apiserver-etcd-client-t9pkx 2m7s kubernetes-admin Approved,Issuedkubeadm-cert-kube-apiserver-kubelet-client-pjbjm 108s kubernetes-admin Approved,Issuedkubeadm-cert-kube-etcd-healthcheck-client-8dcn8 64s kubernetes-admin Approved,Issuedkubeadm-cert-kubernetes-admin-pn99f 4m29s kubernetes-admin Approved,Issuedkubeadm-cert-system:kube-controller-manager-mr86h 79s kubernetes-admin Approved,Issuedkubeadm-cert-system:kube-scheduler-t8lnw 17s kubernetes-admin Approved,Issuedkubeadm-cert-ydzs-master-cqh4s 52s kubernetes-admin Approved,Issuedkubeadm-cert-ydzs-master-lvbr5 41s kubernetes-admin Approved,Issued
批準(zhǔn)完成后檢查證書的有效期:
$ kubeadm alpha certs check-expirationCERTIFICATE EXPIRES RESIDUAL TIME EXTERNALLY MANAGEDadmin.conf Nov 05, 2029 11:53 UTC 9y noapiserver Nov 05, 2029 11:54 UTC 9y noapiserver-etcd-client Nov 05, 2029 11:53 UTC 9y noapiserver-kubelet-client Nov 05, 2029 11:54 UTC 9y nocontroller-manager.conf Nov 05, 2029 11:54 UTC 9y noetcd-healthcheck-client Nov 05, 2029 11:53 UTC 9y noetcd-peer Nov 05, 2029 11:53 UTC 9y noetcd-server Nov 05, 2029 11:54 UTC 9y nofront-proxy-client Nov 05, 2029 11:54 UTC 9y noscheduler.conf Nov 05, 2029 11:53 UTC 9y no
我們可以看到已經(jīng)延長小10年了,這是因?yàn)?ca 證書的有效期只有10年。
但是現(xiàn)在我們還不能直接重啟控制面板的幾個組件,這是因?yàn)槭褂?kubeadm 安裝的集群對應(yīng)的 etcd 默認(rèn)是使用的 /etc/kubernetes/pki/etcd/ca.crt 這個證書進(jìn)行前面的,而上面我們用命令 kubectl certificate approve 批準(zhǔn)過后的證書是使用的默認(rèn)的 /etc/kubernetes/pki/ca.crt 證書進(jìn)行簽發(fā)的,所以我們需要替換 etcd 中的 ca 機(jī)構(gòu)證書:
# 先拷貝靜態(tài) Pod 資源清單cp -r /etc/kubernetes/manifests/ /etc/kubernetes/manifests.bakvi /etc/kubernetes/manifests/etcd.yaml......spec:containers:command:etcd# 修改為 CA 文件--peer-trusted-ca-file=/etc/kubernetes/pki/ca.crt--trusted-ca-file=/etc/kubernetes/pki/ca.crt......volumeMounts:mountPath: /var/lib/etcdname: etcd-datamountPath: /etc/kubernetes/pki # 更改證書目錄name: etcd-certsvolumes:hostPath:path: /etc/kubernetes/pki # 將 pki 目錄掛載到 etcd 中去type: DirectoryOrCreatename: etcd-certshostPath:path: /var/lib/etcdtype: DirectoryOrCreatename: etcd-data......
由于 kube-apiserver 要連接 etcd 集群,所以也需要重新修改對應(yīng)的 etcd ca 文件:
vi /etc/kubernetes/manifests/kube-apiserver.yaml......spec:containers:command:kube-apiserver# 將etcd ca文件修改為默認(rèn)的ca.crt文件--etcd-cafile=/etc/kubernetes/pki/ca.crt......
除此之外還需要替換 requestheader-client-ca-file 文件,默認(rèn)是 /etc/kubernetes/pki/front-proxy-ca.crt 文件,現(xiàn)在也需要替換成默認(rèn)的 CA 文件,否則使用聚合 API,比如安裝了 metrics-server 后執(zhí)行 kubectl top 命令就會報錯:
cp /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/front-proxy-ca.crtcp /etc/kubernetes/pki/ca.key /etc/kubernetes/pki/front-proxy-ca.key
修改完成后重啟控制面板的幾個容器。由于我們當(dāng)前版本的 kubelet 默認(rèn)開啟了證書自動輪轉(zhuǎn),所以 kubelet 的證書也不用再去管理了,這樣我就將證書更新成10有效期了。在操作之前一定要先對證書目錄進(jìn)行備份,防止操作錯誤進(jìn)行回滾。
K8S進(jìn)階訓(xùn)練營,點(diǎn)擊下方圖片了解詳情

