CA 證書的手動輪換
本頁面介紹如何手動輪換證書頒發機構(CA)證書。
準備工作
你需要有一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。建議你在至少有兩個非控制平面主機節點的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者使用這些 Kubernetes 教程環境之一。
手動輪換 CA 證書
注意
務必備份你的證書目錄以及配置檔案和任何其他必要檔案。
此方法假定 Kubernetes 控制平面在具有多個 API 伺服器的 HA 配置中執行。還假定 API 伺服器正常終止,以便客戶端可以乾淨地從一個 API 伺服器斷開連線並重新連線到另一個 API 伺服器。
單 API 伺服器配置將在 API 伺服器重啟期間出現不可用。
將新的 CA 證書和私鑰(例如:
ca.crt
、ca.key
、front-proxy-ca.crt
和front-proxy-ca.key
)分發到所有控制平面節點上的 Kubernetes 證書目錄。更新 kube-controller-manager 的
--root-ca-file
標誌,以同時包含舊 CA 和新 CA,然後重啟 kube-controller-manager。此後建立的任何 ServiceAccount 都將獲取包含舊 CA 和新 CA 的 Secret。
注意
kube-controller-manager 標誌
--client-ca-file
和--cluster-signing-cert-file
指定的檔案不能是 CA 捆綁包。如果這些標誌和--root-ca-file
都指向同一個ca.crt
檔案,而該檔案現在是一個捆綁包(包含舊 CA 和新 CA),你將會遇到錯誤。為了解決此問題,你可以將新 CA 複製到單獨的檔案中,並使標誌--client-ca-file
和--cluster-signing-cert-file
指向該副本。一旦ca.crt
不再是捆綁包,你可以將問題標誌恢復為指向ca.crt
並刪除該副本。kubeadm 的問題 1350 跟蹤了 kube-controller-manager 無法接受 CA 捆綁包的錯誤。
等待控制器管理器更新服務賬號 Secret 中的
ca.crt
,使其包含舊 CA 證書和新 CA 證書。如果在 API 伺服器使用新 CA 之前啟動了任何 Pod,則這些新 Pod 將獲得此更新並信任舊 CA 和新 CA。
重啟所有使用叢集內配置的 Pod(例如:kube-proxy、CoreDNS 等),以便它們可以使用連結到 ServiceAccount 的 Secret 中更新的證書頒發機構資料。
- 確保 CoreDNS、kube-proxy 和其他使用叢集內配置的 Pod 正常工作。
將舊 CA 和新 CA 都新增到
kube-apiserver
配置中--client-ca-file
和--kubelet-certificate-authority
標誌所指向的檔案中。將舊 CA 和新 CA 都新增到
kube-scheduler
配置中--client-ca-file
標誌所指向的檔案中。透過分別替換
client-certificate-data
和client-key-data
的內容來更新使用者賬號的證書。有關為單個使用者賬號建立證書的資訊,請參閱 為使用者賬號配置證書。
此外,更新 kubeconfig 檔案中的
certificate-authority-data
部分,分別使用 Base64 編碼的舊證書頒發機構資料和新證書頒發機構資料。更新 雲控制器管理器 的
--root-ca-file
標誌,以同時包含舊 CA 和新 CA,然後重啟雲控制器管理器。注意
如果你的叢集沒有云控制器管理器,可以跳過此步驟。按滾動方式執行以下步驟。
重啟任何其他 聚合 API 伺服器 或 Webhook 處理程式,以信任新的 CA 證書。
透過更新所有節點上 kubelet 配置中的
clientCAFile
標誌所指向的檔案以及kubelet.conf
中的certificate-authority-data
,以使用舊 CA 和新 CA,從而重啟 kubelet。如果你的 kubelet 未使用客戶端證書輪換,請更新所有節點上
kubelet.conf
中的client-certificate-data
和client-key-data
,以及通常位於/var/lib/kubelet/pki
的 kubelet 客戶端證書檔案。使用由新 CA 簽名的證書(
apiserver.crt
、apiserver-kubelet-client.crt
和front-proxy-client.crt
)重啟 API 伺服器。你可以使用現有的私鑰或新的私鑰。如果更改了私鑰,請同時在 Kubernetes 證書目錄中更新它們。由於叢集中的 Pod 信任舊 CA 和新 CA,因此在 Pod 的 Kubernetes 客戶端重新連線到新的 API 伺服器後,將出現短暫的斷開連線。新的 API 伺服器使用由新 CA 簽名的證書。
- 重啟 kube-scheduler,使其使用並信任新的 CA。
- 確保控制平面元件日誌中沒有 TLS 錯誤。
注意
To generate certificates and private keys for your cluster using the `openssl` command line tool, see [Certificates (`openssl`)](/docs/tasks/administer-cluster/certificates/#openssl). You can also use [`cfssl`](/docs/tasks/administer-cluster/certificates/#cfssl).
標註任何 DaemonSet 和 Deployment,以更安全地觸發 Pod 的滾動替換。
for namespace in $(kubectl get namespace -o jsonpath='{.items[*].metadata.name}'); do for name in $(kubectl get deployments -n $namespace -o jsonpath='{.items[*].metadata.name}'); do kubectl patch deployment -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}'; done for name in $(kubectl get daemonset -n $namespace -o jsonpath='{.items[*].metadata.name}'); do kubectl patch daemonset -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}'; done done
注意
To limit the number of concurrent disruptions that your application experiences, see [configure pod disruption budget](/docs/tasks/run-application/configure-pdb/).
Depending on how you use StatefulSets you may also need to perform similar rolling replacement.
如果你的叢集使用引導令牌加入節點,請使用新的 CA 更新
kube-public
名稱空間中的 ConfigMapcluster-info
。base64_encoded_ca="$(base64 -w0 /etc/kubernetes/pki/ca.crt)" kubectl get cm/cluster-info --namespace kube-public -o yaml | \ /bin/sed "s/\(certificate-authority-data:\).*/\1 ${base64_encoded_ca}/" | \ kubectl apply -f -
驗證叢集功能。
檢查控制平面元件以及 kubelet 和 kube-proxy 的日誌。確保這些元件沒有報告任何 TLS 錯誤;有關更多詳細資訊,請參閱 檢視日誌。
驗證任何聚合 API 伺服器和使用叢集內配置的 Pod 的日誌。
一旦叢集功能成功驗證
更新所有服務賬號令牌,使其只包含新的 CA 證書。
- 所有使用叢集內 kubeconfig 的 Pod 最終都需要重啟以獲取新的 Secret,這樣就沒有 Pod 依賴舊的叢集 CA 了。
透過分別從 kubeconfig 檔案以及
--client-ca-file
和--root-ca-file
標誌所指向的檔案中移除舊 CA 來重啟控制平面元件。在每個節點上,透過從
clientCAFile
標誌所指向的檔案以及 kubelet kubeconfig 檔案中移除舊 CA 來重啟 kubelet。你應該以滾動更新的方式執行此操作。如果你的叢集允許你進行此更改,你也可以透過替換節點而不是重新配置它們來推出。