Kubelet 證書如何自動續期


因為之前在安裝K8S 節點的時候,使用的是手動簽發

1年后Kubernetes 集群日志中出現 certificate has expired or is not yet valid 錯誤信息時,表明證書過期

我搭建 Kubernetes 集群時,一般只聲明用於集群 Master、Etcd等通信的證書 為 10年 或者 更久,但未聲明集群 Kubelet 組件證書 ,Kubelet 組件證書 默認有效期為(8760h0m0s)1年

集群運行1年以后就會導致報 certificate has expired or is not yet valid 錯誤,導致集群 Node不能於集群 Master正常通信

 

Kubernetes 在 1.4 版本(我記着是)推出了 TLS bootstrapping 功能;這個功能主要解決了以下問題:

 

當集群開啟了 TLS 認證后,每個節點的 kubelet 組件都要使用由 apiserver 使用的 CA 簽發的有效證書才能與 apiserver 通訊;此時如果節點多起來,為每個節點單獨簽署證書將是一件非常繁瑣的事情;

TLS bootstrapping 功能就是讓 kubelet 先使用一個預定的低權限用戶連接到 apiserver,然后向 apiserver 申請證書,kubelet 的證書由 apiserver 動態簽署;在配合 RBAC 授權模型下的工作

解決方法

添加開啟證書輪換的配置參數

kubelet 在證書即將到期時會自動發起一個 renew 自己證書的 CSR 請求,同時 controller manager 需要在啟動時增加參數

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

    --feature-gates=RotateKubeletServerCertificate=true --feature-gates=RotateKubeletClientCertificate=true 
    --rotate-certificates #1.8版本以上包含1.8都支持證書更換自動重載,以下版本只能手動重啟服務
  • 修改 controller-manager 組件配置,TLS bootstrapping 時的證書實際是由 kube-controller-manager 組件來簽署的,也就是說證書有效期是 kube-controller-manager 組件控制的

  • --experimental-cluster-signing-duration=87600h0m0s #參數來設置簽署的證書有效時間;默認為 8760h0m0s,將其改為 87600h0m0s 即 10 年后再進行 TLS bootstrapping 簽署證書即可
    --feature-gates=RotateKubeletServerCertificate=true

RBAC授權

kubelet 所發起的 CSR 請求是由 controller manager 簽署的;如果想要是實現自動簽發,就需要讓 controller manager 能夠在 kubelet 發起證書請求的時候自動幫助其簽署證書;

那么 controller manager 不可能對所有的 CSR 證書申請都自動簽署,這時候就需要配置 RBAC 規則,保證 controller manager 只對 kubelet 發起的特定 CSR 請求自動批准即可

RBAC 中 ClusterRole 只是描述或者說定義一種集群范圍內的能力,這三個 ClusterRole 在 1.7 之前需要自己手動創建,在 1.8 后 apiserver 會自動創建前兩個;

# A ClusterRole which instructs the CSR approver to approve a user requesting # node client credentials. kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: approve-node-client-csr rules: - apiGroups: ["certificates.k8s.io"] resources: ["certificatesigningrequests/nodeclient"] verbs: ["create"] --- # A ClusterRole which instructs the CSR approver to approve a node renewing its # own client credentials. kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: approve-node-client-renewal-csr rules: - apiGroups: ["certificates.k8s.io"] resources: ["certificatesigningrequests/selfnodeclient"] verbs: ["create"] --- # A ClusterRole which instructs the CSR approver to approve a node requesting a # serving cert matching its client cert. kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: approve-node-server-renewal-csr rules: - apiGroups: ["certificates.k8s.io"] resources: ["certificatesigningrequests/selfnodeserver"] verbs: ["create"]

可以看到前面兩個是默認創建的,只需要創建最后一個

kubectl get clusterrole|egrep approve

approve-node-client-csr                                                 365d
approve-node-client-renewal-csr                                   365d
approve-node-server-renewal-csr                                  2m

以上三個 ClusterRole 含義如下

  • approve-node-client-csr: 具有自動批准 nodeclient 類型 CSR 請求的能力
  • approve-node-client-renewal-csr: 具有自動批准 selfnodeclient 類型 CSR 請求的能力
  • approve-node-server-renewal-csr: 具有自動批准 selfnodeserver 類型 CSR 請求的能力

所以,如果想要 kubelet 能夠自動簽發,那么就應當將適當的 ClusterRole 綁定到 kubelet 自動續期時所所采用的用戶或者用戶組身上

cat token.csv
f485b42fa3e4b75ae1eeac0ccdecbbc9,kubelet-bootstrap,10001,"system:kubelet-bootstrap"

cat bootstrap.kubeconfig |egrep user
user: kubelet-bootstrap

 

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

開啟證書輪換下的引導過程

  • kubelet 讀取 bootstrap.kubeconfig,使用其 CA 與 Token 向 apiserver 發起第一次 CSR 請求(nodeclient)
  • apiserver 根據 RBAC 規則自動批准首次 CSR 請求(approve-node-client-csr),並下發證書(kubelet-client.crt)
  • kubelet 使用剛剛簽發的證書(O=system:nodes, CN=system:node:NODE_NAME)與 apiserver 通訊,並發起申請 10250 server 所使用證書的 CSR 請求
  • apiserver 根據 RBAC 規則自動批准 kubelet 為其 10250 端口申請的證書(kubelet-server-current.crt)
  • 證書即將到期時,kubelet 自動向 apiserver 發起用於與 apiserver 通訊所用證書的 renew CSR 請求和 renew 本身 10250 端口所用證書的 CSR 請求
  • apiserver 根據 RBAC 規則自動批准兩個證書
  • kubelet 拿到新證書后關閉所有連接,reload 新證書,以后便一直如此

從以上流程我們可以看出,實現證書輪換創建 的RBAC 規則,則至少能滿足四種情況:

  • 自動批准 kubelet 首次用於與 apiserver 通訊證書的 CSR 請求(nodeclient)
  • 自動批准 kubelet 首次用於 10250 端口鑒權的 CSR 請求(實際上這個請求走的也是 selfnodeserver 類型 CSR)
  • 自動批准 kubelet 后續 renew 用於與 apiserver 通訊證書的 CSR 請求(selfnodeclient)
  • 自動批准 kubelet 后續 renew 用於 10250 端口鑒權的 CSR 請求(selfnodeserver)

基於以上四種情況ClusterRoleBinding最終的RBAC 規則如下:

#自動批准 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

kubectl get clusterrolebinding|egrep "node-(.*)-auto"
node-client-auto-approve-csr                            3h31m
node-client-auto-renew-crt                                3h30m
node-server-auto-renew-crt                              3h29m

重啟kube-controller-manager 和 kubelet 服務

systemctl daemon-reload
systemctl restart kube-controller-manager.service
# 進入到ssl配置目錄,刪除 kubelet 證書
rm -f kubelet-client-current.pem kubelet-client-*.pem kubelet.key kubelet.crt
重啟啟動,啟動正常后會頒發有效期10年的ssl證書
systemctl restart kubelet
進入到ssl配置目錄,查看證書有效期
openssl x509 -in kubelet-client-current.pem -noout -text | grep "Not"
Not Before: Jun 20 05:51:00 2020 GMT
Not After : Jun 17 07:44:29 2029 GMT

kubectl get nodes
NAME                   STATUS           ROLES                 AGE                VERSION
k8s-node1              Ready            <none>                 365d                   v1.14.3

TLS bootstrapping 總結以及詳細操作

kubelet 首次啟動通過加載 bootstrap.kubeconfig 中的用戶 Token 和 apiserver CA 證書發起首次 CSR 請求,這個 Token 被預先內置在 apiserver 節點的 token.csv 中,其身份為 kubelet-bootstrap 用戶和 system:bootstrappers 用戶組;

想要首次 CSR 請求能成功(成功指的是不會被 apiserver 401 拒絕),則需要先將 kubelet-bootstrap 用戶和 system:node-bootstrapper 內置 ClusterRole 綁定;

對於首次 CSR 請求可以手動批准,也可以將 system:bootstrappers 用戶組與 approve-node-client-csr ClusterRole 綁定實現自動批准(1.8 之前這個 ClusterRole 需要手動創建,1.8 后 apiserver 自動創建,並更名為 system:certificates.k8s.io:certificatesigningrequests:nodeclient)

默認簽署的的證書只有 1 年有效期,如果想要調整證書有效期可以通過設置 kube-controller-manager 的 --experimental-cluster-signing-duration 參數實現,該參數默認值為 8760h0m0s

對於證書自動續簽,需要通過協調兩個方面實現

第一,想要 kubelet 在證書到期后自動發起續期請求,則需要在 kubelet 啟動時增加 --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true 來實現;

第二,想要讓 controller manager 自動批准續簽的 CSR 請求需要在 controller manager 啟動時增加 --feature-gates=RotateKubeletServerCertificate=true 參數,並綁定對應的 RBAC 規則;

同時需要注意的是 1.7 版本的 kubelet 自動續簽后需要手動重啟 kubelet 以使其重新加載新證書,

而 1.8 后只需要在 kublet 啟動時附帶 --rotate-certificates 選項就會自動重新加載新證書

 

 參考文章:

https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/

https://www.cnblogs.com/lvcisco/p/11912637.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM