在學習和搭建二進制Kubernetes叢集過程中,對其中涉及到的一推證書往往很懵,雖然參考網上大量的部署教程最後會成功部署并正常運作起來,但對其中的部署流程和原理細節等還是很模糊,下面根據搜集網上資料和kubernetes相關書籍特意梳理下kubernetes認證授權機制的基礎知識,重點關注TLS Bootstrapping (TLS 引導)、證書自動頒發、證書輪換、認證過程的RBAC授權, 以便後續深入了解和運用~
Kubernetes經過一系列認證授權機制來實作叢集的安全機制,包括API Server的認證、授權、準入控制機制等。叢集的安全性必須考慮以下的幾個目标:
-> 保證容器與其所在主控端的隔離;
-> 限制容器給基礎設施及其他容器帶來消極影響的能力;
-> 最小權限原則,合理限制所有元件權限,確定元件隻執行它被授權的行為,通過限制單個元件的能力來限制他所能達到的權限範圍;
-> 明确元件間邊界的劃分;
-> 劃分普通使用者和管理者角色;
-> 在必要的時候允許将管理者權限賦給普通使用者;
-> 允許擁有Secret資料(Keys、Certs、Passwords)的應用在叢集中運作;
一、HTTPS 數字證書認證
HTTPS工作流程
1. 浏覽器發起https請求,将自己支援的一套加密規則發送給服務端。
2. 服務端從中選出一組加密算法與HASH算法,并将自己的身份資訊以證書的形式發回給浏覽器。證書裡面包含了服務端位址,加密公鑰,以及證書的頒發機構等資訊。
3. 獲得服務端證書之後浏覽器要做以下工作:
-> 驗證證書的合法性(頒發證書的機構是否合法,證書中包含的服務端位址是否與正在通路的位址一緻等),如果證書受信任,則浏覽器欄裡面會顯示一個小鎖頭,否則會給出證書不受信的提示。
-> 如果證書受信任,或者是使用者接受了不受信的證書,浏覽器會生成一串随機數的密碼,并用證書中提供的公鑰加密。
-> 使用約定好的HASH計算握手消息,并使用生成的随機數對消息進行加密,最後将之前生成的所有資訊發送給服務端。
4. 服務端接收浏覽器發來的資料之後要做以下的操作:
-> 使用自己的私鑰将資訊解密取出密碼,使用密碼解密浏覽器發來的握手消息,并驗證HASH是否與浏覽器發來的一緻。
-> 使用密碼加密一段握手消息,發送給浏覽器。
5. 浏覽器解密并計算握手消息的HASH,如果與服務端發來的HASH一緻,則此時握手過程結束,之後所有通信資料将由之前浏覽器生成的随機密碼并利用加密算法進行加密。
二、Kubernetes加密解密原理
kubernetes内部常用的加解密算法為非對稱加密算法RSA。
1. 每個使用者都有一對私鑰和公鑰。
-> 私鑰用來進行解密和簽名,是給自己用的。
-> 公鑰由本人公開,用于加密和驗證簽名,是給别人用的。
2. 當該使用者發送檔案時,用私鑰簽名,别人用他給的公鑰解密,可以保證該資訊是由他發送的。即數字簽名。
3. 當該使用者接受檔案時,别人用他的公鑰加密,他用私鑰解密,可以保證該資訊隻能由他看到。即安全傳輸
三、 數字證書
數字證書則是由證書認證機構(CA)對證書申請者真實身份驗證之後,用CA的根證書對申請人的一些基本資訊以及申請人的公鑰進行簽名(相當于加蓋發證書機 構的公章)後形成的一個數字檔案。CA完成簽發證書後,會将證書釋出在CA的證書庫(目錄伺服器)中,任何人都可以查詢和下載下傳,是以數字證書和公鑰一樣是公開的。實際上,數字證書就是經過CA認證過的公鑰
四、CA認證流程
SSL雙向認證步驟
1. HTTPS通信雙方的伺服器端向CA機構申請證書,CA機構是可信的第三方機構,它可以是一個公認的權威的企業,也可以是企業自身。企業内部系統一般都使用企業自身的認證系統。CA機構下發根證書、服務端證書及私鑰給申請者;
2. HTTPS通信雙方的用戶端向CA機構申請證書,CA機構下發根證書、用戶端證書及私鑰個申請者;
3. 用戶端向伺服器端發起請求,服務端下發服務端證書給用戶端。用戶端接收到證書後,通過私鑰解密證書,并利用伺服器端證書中的公鑰認證證書資訊比較證書裡的消息,例如域名和公鑰與伺服器剛剛發送的相關消息是否一緻,如果一緻,則用戶端認為這個伺服器的合法身份;
4. 用戶端發送用戶端證書給伺服器端,服務端接收到證書後,通過私鑰解密證書,獲得用戶端的證書公鑰,并用該公鑰認證證書資訊,确認用戶端是否合法;
5. 用戶端通過随機秘鑰加密資訊,并發送加密後的資訊給服務端。伺服器端和用戶端協商好加密方案後,用戶端會産生一個随機的秘鑰,用戶端通過協商好的加密方案,加密該随機秘鑰,并發送該随機秘鑰到伺服器端。伺服器端接收這個秘鑰後,雙方通信的所有内容都都通過該随機秘鑰加密;
五、Kubernetes幾個重要的認證憑據
ca.pem & ca-key.pem & ca.csr
有上文我們可以知道,建立完整TLS加密通信,需要有一個CA認證機構,會向用戶端下發根證書、服務端證書以及簽名私鑰給用戶端。ca.pem & ca-key.pem & ca.csr組成了一個自簽名的CA機構。
token.csv
該檔案為一個使用者的描述檔案,基本格式為 Token,使用者名,UID,使用者組;這個檔案在 apiserver 啟動時被 apiserver 加載,然後就相當于在叢集内建立了一個這個使用者;接下來就可以用 RBAC 給他授權
bootstrap.kubeconfig
該檔案中内置了 token.csv 中使用者的 Token,以及 apiserver CA 證書;kubelet 首次啟動會加載此檔案,使用 apiserver CA 證書建立與 apiserver 的 TLS 通訊,使用其中的使用者 Token 作為身份辨別像 apiserver 發起 CSR 請求
kubelet-client-current.pem
這是一個軟連接配接檔案,當 kubelet 配置了 --feature-gates=RotateKubeletClientCertificate=true選項後,會在證書總有效期的 70%~90% 的時間内發起續期請求,請求被準許後會生成一個 kubelet-client-時間戳.pem;kubelet-client-current.pem 檔案則始終軟連接配接到最新的真實證書檔案,除首次啟動外,kubelet 一直會使用這個證書同 apiserver 通訊
kubelet-server-current.pem
同樣是一個軟連接配接檔案,當 kubelet 配置了 --feature-gates=RotateKubeletServerCertificate=true 選項後,會在證書總有效期的 70%~90% 的時間内發起續期請求,請求被準許後會生成一個 kubelet-server-時間戳.pem;kubelet-server-current.pem 檔案則始終軟連接配接到最新的真實證書檔案,該檔案将會一直被用于 kubelet 10250 api 端口鑒權
六、元件證書 及 配置參數
所有用戶端的證書首先要經過Kubernetes叢集CA的簽署,否則不會被叢集認可 .
kubectl
kubectl隻是個go編寫的可執行程式,隻要為kubectl配置合适的kubeconfig,就可以在叢集中的任意節點使用 。kubectl的權限為admin,具有通路kubernetes所有api的權限。
--certificate-authority=/etc/kubernetes/ssl/ca.pem 設定了該叢集的根證書路徑, --embed-certs為true表示将--certificate-authority證書寫入到kubeconfig中;
--client-certificate=/etc/kubernetes/ssl/admin.pem 指定kubectl證書;
--client-key=/etc/kubernetes/ssl/admin-key.pem 指定kubectl私鑰;
kubelet
當成功簽發證書後,目标節點的 kubelet 會将證書寫入到 --cert-dir= 選項指定的目錄中;此時如果不做其他設定應當生成上述除ca.pem以外的4個檔案。
-> kubelet-client.crt 該檔案在 kubelet 完成 TLS bootstrapping 後生成,此證書是由 controller manager 簽署的,此後 kubelet 将會加載該證書,用于與 apiserver 建立 TLS 通訊,同時使用該證書的 CN 字段作為使用者名,O 字段作為使用者組向 apiserver 發起其他請求。
-> kubelet.crt 該檔案在 kubelet 完成 TLS bootstrapping 後并且沒有配置 --feature-gates=RotateKubeletServerCertificate=true 時才會生成;這種情況下該檔案為一個獨立于 apiserver CA 的自簽 CA 證書,有效期為 1 年;被用作 kubelet 10250 api 端口。
kube-apiserver
kube-apiserver是我們在部署kubernetes叢集是最需要先啟動的元件,也是我們和叢集互動的核心元件。
以下是kube-apiserver所使用的證書:
--token-auth-file=/etc/kubernetes/token.csv 指定了token.csv的位置,用于kubelet 元件 第一次啟動時沒有證書如何連接配接 apiserver 。 Token 和 apiserver 的 CA 證書被寫入了 kubelet 所使用的 bootstrap.kubeconfig 配置檔案中;這樣在首次請求時,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 證書來與 apiserver 建立 TLS 通訊,使用 bootstrap.kubeconfig 中的使用者 Token 來向 apiserver 聲明自己的 RBAC 授權身份
--tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem 指定kube-apiserver證書位址
--tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem 指定kube-apiserver私鑰位址
--client-ca-file=/etc/kubernetes/ssl/ca.pem 指定根證書位址
--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem 包含PEM-encoded x509 RSA公鑰和私鑰的檔案路徑,用于驗證Service Account的token,如果不指定,則使用--tls-private-key-file指定的檔案
--etcd-cafile=/etc/kubernetes/ssl/ca.pem 到etcd安全連接配接使用的SSL CA檔案
--etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem 到etcd安全連接配接使用的SSL 證書檔案
--etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem 到etcd安全連接配接使用的SSL 私鑰檔案
kube-controller-manager
kubelet 發起的 CSR 請求都是由 kube-controller-manager 來做實際簽署的,所有使用的證書都是根證書的密鑰對 。由于kube-controller-manager是和kube-apiserver部署在同一節點上,且使用非安全端口通信,故不需要證書。
--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem 指定簽名的CA機構根證書,用來簽名為 TLS BootStrap 建立的證書和私鑰;
--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem 指定簽名的CA機構私鑰,用來簽名為 TLS BootStrap 建立的證書和私鑰;
--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem 同上;
--root-ca-file=/etc/kubernetes/ssl/ca.pem 根CA憑證檔案路徑 ,用來對 kube-apiserver 證書進行校驗,指定該參數後,才會在Pod 容器的 ServiceAccount 中放置該 CA 證書檔案
--kubeconfig kubeconfig 配置檔案路徑,在配置檔案中包括Master的位址資訊及必要認證資訊;
kube-scheduler && kube-proxy
kube-scheduler是和kube-apiserver一般部署在同一節點上,且使用非安全端口通信,故啟動參參數中沒有指定證書的參數可選 。 若分離部署,可在kubeconfig檔案中指定證書,使用kubeconfig認證,kube-proxy類似
配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
TLS Bootstrapping
每個 Kubernetes 叢集都有一個叢集根證書頒發機構(CA)。 叢集中的元件通常使用 CA 來驗證 API server 的證書,由API伺服器驗證 kubelet 用戶端證書等。為了支援這一點,CA 證書包被分發到叢集中的每個節點,并作為一個 secret 附加分發到預設 service account 上 。
-> 想要與 apiserver 通訊就必須采用由 apiserver CA 簽發的證書,這樣才能形成信任關系,建立 TLS 連接配接;
-> 證書的 CN、O 字段來提供 RBAC 所需的使用者與使用者組;
kubelet首次啟動流程
第一次啟動時沒有證書如何連接配接 apiserver ? 這個問題實際上可以去檢視一下 bootstrap.kubeconfig 和 token.csv, 可以得到如下答案:
在 apiserver 配置中指定了一個 token.csv 檔案,該檔案中是一個預設的使用者配置;同時該使用者的 Token 和 apiserver 的 CA 證書被寫入了 kubelet 所使用的 bootstrap.kubeconfig 配置檔案中;這樣在首次請求時,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 證書來與 apiserver 建立 TLS 通訊,使用 bootstrap.kubeconfig 中的使用者 Token 來向 apiserver 聲明自己的 RBAC 授權身份。如下圖所示:
在首次啟動時,可能與遇到 kubelet 報 401 無權通路 apiserver 的錯誤;這是因為在預設情況下,kubelet 通過 bootstrap.kubeconfig 中的預設使用者 Token 聲明了自己的身份,然後建立 CSR 請求;但是不要忘記這個使用者在我們不處理的情況下他沒任何權限的,包括建立 CSR 請求;是以需要如下指令建立一個 ClusterRoleBinding,将預設使用者 kubelet-bootstrap 與内置的 ClusterRole system:node-bootstrapper 綁定到一起,使其能夠發起 CSR 請求。
1 2 3 | |
CSR請求類型
kubelet 發起的 CSR 請求都是由 controller manager 來做實際簽署的,對于 controller manager 來說,TLS bootstrapping 下 kubelet 發起的 CSR 請求大緻分為以下三種
-> nodeclient: kubelet 以 O=system:nodes 和 CN=system:node:(node name) 形式發起的 CSR 請求
-> selfnodeclient: kubelet client renew 自己的證書發起的 CSR 請求(與上一個證書就有相同的 O 和 CN)
-> selfnodeserver: kubelet server renew 自己的證書發起的 CSR 請求
手動簽發
在 kubelet 首次啟動後,如果使用者 Token 沒問題,并且 RBAC 也做了相應的設定,那麼此時在叢集内應該能看到 kubelet 發起的 CSR 請求 ,必須通過後kubernetes 系統才會将該 Node 加入到叢集。檢視未授權的CSR 請求:
1 2 3 4 5 6 | |
通過CSR 請求:
1 2 3 4 5 6 | |
自動生成了kubelet kubeconfig 檔案和公私鑰:
1 2 3 4 5 6 7 8 | |
當成功簽發證書後,目标節點的 kubelet 會将證書寫入到 --cert-dir= 選項指定的目錄中;注意此時如果不做其他設定應當生成四個檔案 .kubelet 與 apiserver 通訊所使用的證書為 kubelet-client.crt,剩下的 kubelet.crt 将會被用于 kubelet server(10250) 做鑒權使用;注意,此時 kubelet.crt 這個證書是個獨立于 apiserver CA 的自簽 CA,并且删除後 kubelet 元件會重新生成它。
自動簽發
上面提到,kubelet首次啟動時會發起CSR請求,如果我們未做任何配置,則需要手動簽發,若叢集龐大,那麼手動簽發的請求就會很多,來了解一下自動簽發
RBAC授權
kubelet 所發起的 CSR 請求是由 controller manager 簽署的;如果想要是實作自動簽發,就需要讓 controller manager 能夠在 kubelet 發起證書請求的時候自動幫助其簽署證書;那麼 controller manager 不可能對所有的 CSR 證書申請都自動簽署,這時候就需要配置 RBAC 規則,保證 controller manager 隻對 kubelet 發起的特定 CSR 請求自動準許即可;針對上面 提出的 3 種 CSR 請求分别給出了 3 種對應的 ClusterRole,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
RBAC 中 ClusterRole 隻是描述或者說定義一種叢集範圍内的能力,這三個 ClusterRole 在 1.7 之前需要自己手動建立,在 1.8 後 apiserver 會自動建立前兩個;以上三個 ClusterRole 含義如下:
-> approve-node-client-csr: 具有自動準許 nodeclient 類型 CSR 請求的能力;
-> approve-node-client-renewal-csr: 具有自動準許 selfnodeclient 類型 CSR 請求的能力;
-> approve-node-server-renewal-csr: 具有自動準許 selfnodeserver 類型 CSR 請求的能力;
是以,如果想要 kubelet 能夠自動簽發,那麼就應當将适當的 ClusterRole 綁定到 kubelet 自動續期時所所采用的使用者或者使用者組身上。
CluserRole 綁定
要實作自動簽發,建立的 RBAC 規則,則至少能滿足四種情況:
自動準許 kubelet 首次用于與 apiserver 通訊證書的 CSR 請求(nodeclient)
自動準許 kubelet 首次用于 10250 端口鑒權的 CSR 請求(實際上這個請求走的也是 selfnodeserver 類型 CSR)
基于以上2種情況,實作自動簽發需要建立 2個 ClusterRoleBinding,建立如下:
1 2 3 4 5 | |
證書輪換
開啟證書輪換下的引導過程
-> 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:
1 2 | |
開啟證書輪換的配置
kubelet 啟動時增加 --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true 選項,則 kubelet 在證書即将到期時會自動發起一個 renew 自己證書的 CSR 請求;增加--rotate-certificates 參數,kubelet 會自動重載新證書;
同時 controller manager 需要在啟動時增加 --feature-gates=RotateKubeletServerCertificate=true 參數,再配合上面建立好的 ClusterRoleBinding,kubelet client 和 kubelet server 證才書會被自動簽署;
證書過期時間
TLS bootstrapping 時的證書實際是由 kube-controller-manager 元件來簽署的,也就是說證書有效期是 kube-controller-manager 元件控制的;kube-controller-manager 元件提供了一個 --experimental-cluster-signing-duration 參數來設定簽署的證書有效時間;預設為 8760h0m0s,将其改為 87600h0m0s 即 10 年後再進行 TLS bootstrapping 簽署證書即可。
七、TLS Bootstrapping總結
=========================== 流程總結 =========================
1)kubelet 首次啟動通過加載 bootstrap.kubeconfig 中的使用者 Token 和 apiserver CA 證書發起首次 CSR 請求,這個 Token 被預先内置在 apiserver 節點的 token.csv 中,其身份為 kubelet-bootstrap 使用者和 system:bootstrappers 使用者組;想要首次 CSR 請求能成功(成功指的是不會被 apiserver 401 拒絕),則需要先将 kubelet-bootstrap 使用者和 system:node-bootstrapper 内置 ClusterRole 綁定;
2)對于首次 CSR 請求可以手動簽發,也可以将 system:bootstrappers 使用者組與 approve-node-client-csr ClusterRole 綁定實作自動簽發(1.8 之前這個 ClusterRole 需要手動建立,1.8 後 apiserver 自動建立,并更名為 system:certificates.k8s.io:certificatesigningrequests:nodeclient)
3)預設簽署的的證書隻有 1 年有效期,如果想要調整證書有效期可以通過設定 kube-controller-manager 的 --experimental-cluster-signing-duration 參數實作,該參數預設值為 8760h0m0s。
4)對于證書輪換,需要通過協調兩個方面實作;第一,想要 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 選項就會自動重新加載新證書。
八、kubernetes配置總結
apiserver 預先放置 token.csv,内容樣例如下:
1 | |
允許 kubelet-bootstrap 使用者建立首次啟動的 CSR 請求 和RBAC授權規則
1 2 3 4 5 6 7 | |
配置 kubelet 自動續期,RotateKubeletClientCertificate 用于自動續期 kubelet 連接配接 apiserver 所用的證書(kubelet-client-xxxx.pem),RotateKubeletServerCertificate 用于自動續期 kubelet 10250 api 端口所使用的證書(kubelet-server-xxxx.pem),--rotate-certificates 選項使得 kubelet 能夠自動重載新證書。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
配置 controller manager 自動準許相關 CSR 請求,如果不配置 --feature-gates=RotateKubeletServerCertificate=true 參數,則即使配置了相關的 RBAC 規則,也隻會自動準許 kubelet client 的 renew 請求:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
建立自動準許相關 CSR 請求的 ClusterRole,1.8 的 apiserver 自動建立了前兩條 ClusterRole,是以隻需要建立一條就行了。
1 2 3 4 5 6 7 8 9 10 | |
将 ClusterRole 綁定到适當的使用者組,以完成自動準許相關 CSR 請求
1 2 3 4 5 6 7 8 | |
轉自
kubernetes容器叢集 - HTTPS認證和授權機制學習 - 散盡浮華 - 部落格園
https://www.cnblogs.com/kevingrace/p/9882026.html
深入了解kubelet認證和授權 - 不言放棄 - 部落格園
https://www.cnblogs.com/zhongpan/p/11964017.html
(3條消息)kubernetes認證授權機制_weixin_33908217的部落格-CSDN部落格_kubernetes rotate secret
https://blog.csdn.net/weixin_33908217/article/details/92358600
Kubelet 證書自動續期 - 雲+社群 - 騰訊雲
https://cloud.tencent.com/developer/article/1638399
kubelet 證書自動續期 - ainimore - 部落格園
https://www.cnblogs.com/ainimore/p/12972858.html