kubernetes認證授權機制

剛開始使用二進制搭建kubernetes集群的時候,看著一堆證書頭皮發(fā)麻,雖然最后集群還是跑起來,但是對其中的流程和細節(jié)原理還是很模糊。特此從二進制集群搭建的流程梳理一下。以下原理及配置均基于v1.10.0版本

Kubernetes過一系列機制來實現(xiàn)集群的安全機制,包括API Server的認證、授權、準入控制機制等。集群的安全性必須考慮以下的幾個目標:

  • 保證容器與其所在宿主機的隔離;
  • 限制容器給基礎設施及其他容器帶來消極影響的能力;
  • 最小權限原則,合理限制所有組件權限,確保組件只執(zhí)行它被授權的行為,通過限制單個組件的能力來限制他所能達到的權限范圍;
  • 明確組件間邊界的劃分;
  • 劃分普通用戶和管理員角色;
  • 在必要的時候允許將管理員權限賦給普通用戶;
  • 允許擁有Secret數(shù)據(jù)(Keys、Certs、Passwords)的應用在集群中運行;

這里對認證和授權做出詳細闡述,重點關注TLS Bootstrapping、證書自動頒發(fā)、證書輪換、認證過程的RBAC授權

https 數(shù)字證書認證

以下簡單講解下https數(shù)字證書認證的原理。


https工作流程

  1. 瀏覽器發(fā)起https請求,將自己支持的一套加密規(guī)則發(fā)送給服務端。
  2. 服務端從中選出一組加密算法與HASH算法,并將自己的身份信息以證書的形式發(fā)回給瀏覽器。證書里面包含了服務端地址,加密公鑰,以及證書的頒發(fā)機構等信息。
  3. 獲得服務端證書之后瀏覽器要做以下工作:
    • 驗證證書的合法性(頒發(fā)證書的機構是否合法,證書中包含的服務端地址是否與正在訪問的地址一致等),如果證書受信任,則瀏覽器欄里面會顯示一個小鎖頭,否則會給出證書不受信的提示。
    • 如果證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數(shù)的密碼,并用證書中提供的公鑰加密。
    • 使用約定好的HASH計算握手消息,并使用生成的隨機數(shù)對消息進行加密,最后將之前生成的所有信息發(fā)送給服務端。
  4. 服務端接收瀏覽器發(fā)來的數(shù)據(jù)之后要做以下的操作:
    • 使用自己的私鑰將信息解密取出密碼,使用密碼解密瀏覽器發(fā)來的握手消息,并驗證HASH是否與瀏覽器發(fā)來的一致。
    • 使用密碼加密一段握手消息,發(fā)送給瀏覽器
  5. 瀏覽器解密并計算握手消息的HASH,如果與服務端發(fā)來的HASH一致,此時握手過程結束,之后所有的通信數(shù)據(jù)將由之前瀏覽器生成的隨機密碼并利用加密算法進行加密。

加密解密原理

kubernetes內(nèi)部常用的加解密算法為非對稱加密算法RSA

  1. 每個用戶都有一對私鑰和公鑰。
    • 私鑰用來進行解密和簽名,是給自己用的。
    • 公鑰由本人公開,用于加密和驗證簽名,是給別人用的。
  2. 當該用戶發(fā)送文件時,用私鑰簽名,別人用他給的公鑰解密,可以保證該信息是由他發(fā)送的。即數(shù)字簽名。
  3. 當該用戶接受文件時,別人用他的公鑰加密,他用私鑰解密,可以保證該信息只能由他看到。即安全傳輸

數(shù)字證書

數(shù)字證書則是由證書認證機構(CA)對證書申請者真實身份驗證之后,用CA的根證書對申請人的一些基本信息以及申請人的公鑰進行簽名(相當于加蓋發(fā)證書機 構的公章)后形成的一個數(shù)字文件。CA完成簽發(fā)證書后,會將證書發(fā)布在CA的證書庫(目錄服務器)中,任何人都可以查詢和下載,因此數(shù)字證書和公鑰一樣是公開的。實際上,數(shù)字證書就是經(jīng)過CA認證過的公鑰

CA認證流程

SSL雙向認證步驟:

  1. HTTPS通信雙方的服務器端向CA機構申請證書,CA機構是可信的第三方機構,它可以是一個公認的權威的企業(yè),也可以是企業(yè)自身。企業(yè)內(nèi)部系統(tǒng)一般都使用企業(yè)自身的認證系統(tǒng)。CA機構下發(fā)根證書、服務端證書及私鑰給申請者;
  2. HTTPS通信雙方的客戶端向CA機構申請證書,CA機構下發(fā)根證書、客戶端證書及私鑰個申請者;
  3. 客戶端向服務器端發(fā)起請求,服務端下發(fā)服務端證書給客戶端??蛻舳私邮盏阶C書后,通過私鑰解密證書,并利用服務器端證書中的公鑰認證證書信息比較證書里的消息,例如域名和公鑰與服務器剛剛發(fā)送的相關消息是否一致,如果一致,則客戶端認為這個服務器的合法身份;
  4. 客戶端發(fā)送客戶端證書給服務器端,服務端接收到證書后,通過私鑰解密證書,獲得客戶端的證書公鑰,并用該公鑰認證證書信息,確認客戶端是否合法;
  5. 客戶端通過隨機秘鑰加密信息,并發(fā)送加密后的信息給服務端。服務器端和客戶端協(xié)商好加密方案后,客戶端會產(chǎn)生一個隨機的秘鑰,客戶端通過協(xié)商好的加密方案,加密該隨機秘鑰,并發(fā)送該隨機秘鑰到服務器端。服務器端接收這個秘鑰后,雙方通信的所有內(nèi)容都都通過該隨機秘鑰加密;

幾個重要的認證憑據(jù)

ca.pem & ca-key.pem & ca.csr

有上文我們可以知道,建立完整TLS加密通信,需要有一個CA認證機構,會向客戶端下發(fā)根證書、服務端證書以及簽名私鑰給客戶端。ca.pem & ca-key.pem & ca.csr組成了一個自簽名的CA機構。

證書名稱 作用
ca.pem CA根證書文件
ca-key.pem 服務端私鑰,用于對客戶端請求的解密和簽名
ca.csr 證書簽名請求,用于交叉簽名或重新簽名

token.csv

該文件為一個用戶的描述文件,基本格式為 Token,用戶名,UID,用戶組;這個文件在 apiserver 啟動時被 apiserver 加載,然后就相當于在集群內(nèi)創(chuàng)建了一個這個用戶;接下來就可以用 RBAC 給他授權

bootstrap.kubeconfig

該文件中內(nèi)置了 token.csv 中用戶的 Token,以及 apiserver CA 證書;kubelet 首次啟動會加載此文件,使用 apiserver CA 證書建立與 apiserver 的 TLS 通訊,使用其中的用戶 Token 作為身份標識像 apiserver 發(fā)起 CSR 請求

kubelet-client-current.pem

這是一個軟連接文件,當 kubelet 配置了 --feature-gates=RotateKubeletClientCertificate=true選項后,會在證書總有效期的 70%~90% 的時間內(nèi)發(fā)起續(xù)期請求,請求被批準后會生成一個 kubelet-client-時間戳.pem;kubelet-client-current.pem 文件則始終軟連接到最新的真實證書文件,除首次啟動外,kubelet 一直會使用這個證書同 apiserver 通訊

kubelet-server-current.pem

同樣是一個軟連接文件,當 kubelet 配置了 --feature-gates=RotateKubeletServerCertificate=true 選項后,會在證書總有效期的 70%~90% 的時間內(nèi)發(fā)起續(xù)期請求,請求被批準后會生成一個 kubelet-server-時間戳.pemkubelet-server-current.pem 文件則始終軟連接到最新的真實證書文件,該文件將會一直被用于 kubelet 10250 api 端口鑒權

組件證書級配置參數(shù)

所有客戶端的證書首先要經(jīng)過集群CA的簽署,否則不會被集群認可 .

kubectl

kubectl只是個go編寫的可執(zhí)行程序,只要為kubectl配置合適的kubeconfig,就可以在集群中的任意節(jié)點使用 。kubectl的權限為admin,具有訪問kubernetes所有api的權限。

證書名稱 作用
ca.pem CA根證書
admin.pem kubectl的TLS認證證書,具有admin權限
admin-key.pem kubectl的TLS認證私鑰
  • --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

證書名稱 作用
ca.pem CA根證書
kubelet-client.crt kubectl的TLS認證證書
kubelet-client.key kubectl的TLS認證私鑰
kubelet.crt 獨立于 apiserver CA 的自簽 CA
kubelet.key 獨立于 apiserver CA 的私鑰

當成功簽發(fā)證書后,目標節(jié)點的 kubelet 會將證書寫入到 --cert-dir= 選項指定的目錄中;此時如果不做其他設置應當生成上述除ca.pem以外的4個文件

  • kubelet-client.crt 該文件在 kubelet 完成 TLS bootstrapping 后生成,此證書是由 controller manager 簽署的,此后 kubelet 將會加載該證書,用于與 apiserver 建立 TLS 通訊,同時使用該證書的 CN 字段作為用戶名,O 字段作為用戶組向 apiserver 發(fā)起其他請求
  • kubelet.crt 該文件在 kubelet 完成 TLS bootstrapping 后并且沒有配置 --feature-gates=RotateKubeletServerCertificate=true 時才會生成;這種情況下該文件為一個獨立于 apiserver CA 的自簽 CA 證書,有效期為 1 年;被用作 kubelet 10250 api 端口

kube-apiserver

kube-apiserver是我們在部署kubernetes集群是最需要先啟動的組件,也是我們和集群交互的核心組件。

以下是kube-apiserver所使用的證書

使用的證書 證書作用
ca.pem CA根證書
ca-key.pem CA端私鑰
kubernetes.pem kube-apiserver的tls認證證書
kubernetes-key.pem kube-apiserver的tls認證私鑰
  • --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 發(fā)起的 CSR 請求都是由 kube-controller-manager 來做實際簽署的,所有使用的證書都是根證書的密鑰對 。由于kube-controller-manager是和kube-apiserver部署在同一節(jié)點上,且使用非安全端口通信,故不需要證書

使用的證書 證書作用
ca.pem CA根證書
ca-key.pem kube-apiserver的tls認證私鑰
  • --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem 指定簽名的CA機構根證書,用來簽名為 TLS BootStrap 創(chuàng)建的證書和私鑰
  • --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem 指定簽名的CA機構私鑰,用來簽名為 TLS BootStrap 創(chuàng)建的證書和私鑰
  • --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem 同上
  • --root-ca-file=/etc/kubernetes/ssl/ca.pem 根CA證書文件路徑 ,用來對 kube-apiserver 證書進行校驗,指定該參數(shù)后,才會在Pod 容器的 ServiceAccount 中放置該 CA 證書文件
  • --kubeconfig kubeconfig配置文件路徑,在配置文件中包括Master的地址信息及必要認證信息

kube-scheduler && kube-proxy

kube-scheduler是和kube-apiserver一般部署在同一節(jié)點上,且使用非安全端口通信,故啟動參參數(shù)中沒有指定證書的參數(shù)可選 。 若分離部署,可在kubeconfig文件中指定證書,使用kubeconfig認證,kube-proxy類似

配置示例:

$ # 設置集群參數(shù)
$ kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-proxy.kubeconfig
$ # 設置客戶端認證參數(shù)
$ kubectl config set-credentials kube-proxy \
  --client-certificate=/etc/kubernetes/ssl/kube-proxy.pem \
  --client-key=/etc/kubernetes/ssl/kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig
$ # 設置上下文參數(shù)
$ kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig
$ # 設置默認上下文
$ kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
$ mv kube-proxy.kubeconfig /etc/kubernetes/

TLS Bootstrapping

每個 Kubernetes 集群都有一個集群根證書頒發(fā)機構(CA)。 集群中的組件通常使用 CA 來驗證 API server 的證書,由API服務器驗證 kubelet 客戶端證書等。為了支持這一點,CA 證書包被分發(fā)到集群中的每個節(jié)點,并作為一個 secret 附加分發(fā)到默認 service account 上 。

  • 想要與 apiserver 通訊就必須采用由 apiserver CA 簽發(fā)的證書,這樣才能形成信任關系,建立 TLS 連接;
  • 證書的 CN、O 字段來提供 RBAC 所需的用戶與用戶組

kubelet首次啟動流程

第一次啟動時沒有證書如何連接 apiserver ?

這個問題實際上可以去查看一下 bootstrap.kubeconfigtoken.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 聲明了自己的身份,然后創(chuàng)建 CSR 請求;但是不要忘記這個用戶在我們不處理的情況下他沒任何權限的,包括創(chuàng)建 CSR 請求;所以需要如下命令創(chuàng)建一個 ClusterRoleBinding,將預設用戶 kubelet-bootstrap 與內(nèi)置的 ClusterRole system:node-bootstrapper 綁定到一起,使其能夠發(fā)起 CSR 請求

kubectl create clusterrolebinding kubelet-bootstrap \
  --clusterrole=system:node-bootstrapper \
  --user=kubelet-bootstrap

CSR請求類型

kubelet 發(fā)起的 CSR 請求都是由 controller manager 來做實際簽署的,對于 controller manager 來說,TLS bootstrapping 下 kubelet 發(fā)起的 CSR 請求大致分為以下三種

  • nodeclient: kubelet 以 O=system:nodesCN=system:node:(node name) 形式發(fā)起的 CSR 請求
  • selfnodeclient: kubelet client renew 自己的證書發(fā)起的 CSR 請求(與上一個證書就有相同的 O 和 CN)
  • selfnodeserver: kubelet server renew 自己的證書發(fā)起的 CSR 請求
CSR 請求類型 作用
nodeclient 僅在kubelet第一次啟動時會產(chǎn)生
selfnodeclient kubelet renew 自己作為 client 跟 apiserver 通訊時使用的證書產(chǎn)生的
selfnodeserver kubelet 首次申請或后續(xù) renew 自己的 10250 api 端口證書時產(chǎn)生的

手動簽發(fā)

在 kubelet 首次啟動后,如果用戶 Token 沒問題,并且 RBAC 也做了相應的設置,那么此時在集群內(nèi)應該能看到 kubelet 發(fā)起的 CSR 請求 ,必須通過后kubernetes 系統(tǒng)才會將該 Node 加入到集群。查看未授權的CSR 請求

$ kubectl get csr
NAME                                                   AGE       REQUESTOR           CONDITION
node-csr--k3G2G1EoM4h9w1FuJRjJjfbIPNxa551A8TZfW9dG-g   2m        kubelet-bootstrap   Pending
$ kubectl get nodes
No resources found.

通過CSR 請求:

$ kubectl certificate approve node-csr--k3G2G1EoM4h9w1FuJRjJjfbIPNxa551A8TZfW9dG-g
certificatesigningrequest "node-csr--k3G2G1EoM4h9w1FuJRjJjfbIPNxa551A8TZfW9dG-g" approved
$ kubectl get nodes
NAME            STATUS    ROLES     AGE       VERSION
172.20.95.174   Ready     <none>    48s       v1.10.0

自動生成了kubelet kubeconfig 文件和公私鑰:

$ ls -l /etc/kubernetes/kubelet.kubeconfig
-rw------- 1 root root 2280 Nov  7 10:26 /etc/kubernetes/kubelet.kubeconfig
$ ls -l /etc/kubernetes/ssl/kubelet*
-rw-r--r-- 1 root root 1046 Nov  7 10:26 /etc/kubernetes/ssl/kubelet-client.crt
-rw------- 1 root root  227 Nov  7 10:22 /etc/kubernetes/ssl/kubelet-client.key
-rw-r--r-- 1 root root 1115 Nov  7 10:16 /etc/kubernetes/ssl/kubelet.crt
-rw------- 1 root root 1675 Nov  7 10:16 /etc/kubernetes/ssl/kubelet.key

當成功簽發(fā)證書后,目標節(jié)點的 kubelet 會將證書寫入到 --cert-dir= 選項指定的目錄中;注意此時如果不做其他設置應當生成四個文件 .kubelet 與 apiserver 通訊所使用的證書為 kubelet-client.crt,剩下的 kubelet.crt 將會被用于 kubelet server(10250) 做鑒權使用;注意,此時 kubelet.crt 這個證書是個獨立于 apiserver CA 的自簽 CA,并且刪除后 kubelet 組件會重新生成它

自動簽發(fā)

上面提到,kubelet首次啟動時會發(fā)起CSR請求,如果我們未做任何配置,則需要手動簽發(fā),若集群龐大,那么手動簽發(fā)的請求就會很多,來了解一下自動簽發(fā)

RBAC授權

kubelet 所發(fā)起的 CSR 請求是由 controller manager 簽署的;如果想要是實現(xiàn)自動簽發(fā),就需要讓 controller manager 能夠在 kubelet 發(fā)起證書請求的時候自動幫助其簽署證書;那么 controller manager 不可能對所有的 CSR 證書申請都自動簽署,這時候就需要配置 RBAC 規(guī)則,保證 controller manager 只對 kubelet 發(fā)起的特定 CSR 請求自動批準即可;針對上面 提出的 3 種 CSR 請求分別給出了 3 種對應的 ClusterRole,如下所示

# 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"]

RBAC 中 ClusterRole 只是描述或者說定義一種集群范圍內(nèi)的能力,這三個 ClusterRole 在 1.7 之前需要自己手動創(chuàng)建,在 1.8 后 apiserver 會自動創(chuàng)建前兩個;以上三個 ClusterRole 含義如下

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

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

CluserRole 綁定

要實現(xiàn)自動簽發(fā),創(chuàng)建的 RBAC 規(guī)則,則至少能滿足四種情況:

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

基于以上2種情況,實現(xiàn)自動簽發(fā)需要創(chuàng)建 2個 ClusterRoleBinding,創(chuàng)建如下 :

# 自動批準 kubelet 的首次 CSR 請求(用于與 apiserver 通訊的證書)
kubectl create clusterrolebinding node-client-auto-approve-csr --clusterrole=approve-node-client-csr --group=system:bootstrappers

# 自動批準 kubelet 發(fā)起的用于 10250 端口鑒權證書的 CSR 請求(包括后續(xù) renew)
kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=approve-node-server-renewal-csr --group=system:nodes

證書輪換

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

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

從以上流程我們可以看出,實現(xiàn)證書輪換創(chuàng)建 的RBAC 規(guī)則,則至少能滿足四種情況:

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

基于以上四種情況,我們只需在開啟了自動簽發(fā)的基礎增加一個ClusterRoleBinding:

# 自動批準 kubelet 后續(xù) renew 用于與 apiserver 通訊證書的 CSR 請求
kubectl create clusterrolebinding node-client-auto-renew-crt --clusterrole=approve-node-client-renewal-csr --group=system:nodes

開啟證書輪換的配置

kubelet 啟動時增加 --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true 選項,則 kubelet 在證書即將到期時會自動發(fā)起一個 renew 自己證書的 CSR 請求;增加--rotate-certificates 參數(shù),kubelet 會自動重載新證書

同時 controller manager 需要在啟動時增加 --feature-gates=RotateKubeletServerCertificate=true 參數(shù),再配合上面創(chuàng)建好的 ClusterRoleBinding,kubelet client 和 kubelet server 證才書會被自動簽署;

證書過期時間

TLS bootstrapping 時的證書實際是由 kube-controller-manager 組件來簽署的,也就是說證書有效期是 kube-controller-manager 組件控制的;kube-controller-manager 組件提供了一個 --experimental-cluster-signing-duration 參數(shù)來設置簽署的證書有效時間;默認為 8760h0m0s,將其改為 87600h0m0s 即 10 年后再進行 TLS bootstrapping 簽署證書即可。

TLS Bootstrapping總結

流程總結

  • kubelet 首次啟動通過加載 bootstrap.kubeconfig 中的用戶 Token 和 apiserver CA 證書發(fā)起首次 CSR 請求,這個 Token 被預先內(nèi)置在 apiserver 節(jié)點的 token.csv 中,其身份為 kubelet-bootstrap 用戶和 system:bootstrappers 用戶組;想要首次 CSR 請求能成功(成功指的是不會被 apiserver 401 拒絕),則需要先將 kubelet-bootstrap 用戶和 system:node-bootstrapper 內(nèi)置 ClusterRole 綁定;
  • 對于首次 CSR 請求可以手動簽發(fā),也可以將 system:bootstrappers 用戶組與 approve-node-client-csr ClusterRole 綁定實現(xiàn)自動簽發(fā)(1.8 之前這個 ClusterRole 需要手動創(chuàng)建,1.8 后 apiserver 自動創(chuàng)建,并更名為 system:certificates.k8s.io:certificatesigningrequests:nodeclient)
  • 默認簽署的的證書只有 1 年有效期,如果想要調(diào)整證書有效期可以通過設置 kube-controller-manager 的 --experimental-cluster-signing-duration 參數(shù)實現(xiàn),該參數(shù)默認值為 8760h0m0s
  • 對于證書輪換,需要通過協(xié)調(diào)兩個方面實現(xiàn);第一,想要 kubelet 在證書到期后自動發(fā)起續(xù)期請求,則需要在 kubelet 啟動時增加 --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true 來實現(xiàn);第二,想要讓 controller manager 自動批準續(xù)簽的 CSR 請求需要在 controller manager 啟動時增加 --feature-gates=RotateKubeletServerCertificate=true 參數(shù),并綁定對應的 RBAC 規(guī)則;同時需要注意的是 1.7 版本的 kubelet 自動續(xù)簽后需要手動重啟 kubelet 以使其重新加載新證書,而 1.8 后只需要在 kublet 啟動時附帶 --rotate-certificates 選項就會自動重新加載新證書

配置總結

apiserver 預先放置 token.csv,內(nèi)容樣例如下

6df3c701f979cee17732c30958745947,kubelet-bootstrap,10001,"system:bootstrappers"

允許 kubelet-bootstrap 用戶創(chuàng)建首次啟動的 CSR 請求 和RBAC授權規(guī)則

kubectl create clusterrolebinding kubelet-bootstrap \
  --clusterrole=system:node-bootstrapper \
  --user=kubelet-bootstrap
  
kubectl create clusterrolebinding kubelet-nodes \ 
  --clusterrole=system:node \ 
  --group=system:nodes

配置 kubelet 自動續(xù)期,RotateKubeletClientCertificate 用于自動續(xù)期 kubelet 連接 apiserver 所用的證書(kubelet-client-xxxx.pem),RotateKubeletServerCertificate 用于自動續(xù)期 kubelet 10250 api 端口所使用的證書(kubelet-server-xxxx.pem),--rotate-certificates 選項使得 kubelet 能夠自動重載新證書

KUBELET_ARGS="--cgroup-driver=cgroupfs \
              --cluster-dns=10.254.0.2 \
              --resolv-conf=/etc/resolv.conf \
              --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \
              --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true \
              --rotate-certificates \
              --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
              --fail-swap-on=false \
              --cert-dir=/etc/kubernetes/ssl \
              --cluster-domain=cluster.local. \
              --hairpin-mode=promiscuous-bridge \
              --serialize-image-pulls=false \
              --pod-infra-container-image=gcr.io/google_containers/pause-amd64:3.0"

配置 controller manager 自動批準相關 CSR 請求,如果不配置 --feature-gates=RotateKubeletServerCertificate=true 參數(shù),則即使配置了相關的 RBAC 規(guī)則,也只會自動批準 kubelet client 的 renew 請求

KUBE_CONTROLLER_MANAGER_ARGS="--address=0.0.0.0 \
                              --service-cluster-ip-range=10.254.0.0/16 \
                              --cluster-name=kubernetes \
                              --cluster-signing-cert-file=/etc/kubernetes/ssl/k8s-root-ca.pem \
                              --cluster-signing-key-file=/etc/kubernetes/ssl/k8s-root-ca-key.pem \
                              --service-account-private-key-file=/etc/kubernetes/ssl/k8s-root-ca-key.pem \
                              --feature-gates=RotateKubeletServerCertificate=true \
                              --root-ca-file=/etc/kubernetes/ssl/k8s-root-ca.pem \
                              --leader-elect=true \
                              --experimental-cluster-signing-duration 10m0s \
                              --node-monitor-grace-period=40s \
                              --node-monitor-period=5s \
                              --pod-eviction-timeout=5m0s"

創(chuàng)建自動批準相關 CSR 請求的 ClusterRole,1.8 的 apiserver 自動創(chuàng)建了前兩條 ClusterRole,所以只需要創(chuàng)建一條就行了

# 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/v1
metadata:
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups: ["certificates.k8s.io"]
  resources: ["certificatesigningrequests/selfnodeserver"]
  verbs: ["create"]

將 ClusterRole 綁定到適當?shù)挠脩艚M,以完成自動批準相關 CSR 請求

# 自動批準 system:bootstrappers 組用戶 TLS bootstrapping 首次申請證書的 CSR 請求
kubectl create clusterrolebinding node-client-auto-approve-csr --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --group=system:bootstrappers

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

See Also

http://www.iops.cc/make-local-ca-with-cfssl/

https://blog.csdn.net/21aspnet/article/details/7249401

https://jimmysong.io/kubernetes-handbook/concepts/rbac.html

https://paper.seebug.org/332/

https://k8smeetup.github.io/docs/tasks/tls/managing-tls-in-a-cluster/

https://k8smeetup.github.io/docs/tasks/tls/certificate-rotation/

https://k8smeetup.github.io/docs/admin/kubelet-tls-bootstrapping/

https://k8smeetup.github.io/docs/reference/generated/kubelet/

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • 安裝k8s Master高可用集群 主機 角色 組件 172.18.6.101 K8S Master Kubele...
    jony456123閱讀 8,087評論 0 9
  • 一:創(chuàng)建 k8s 各組件 TLS 加密通信的證書和秘鑰 kubernetes 系統(tǒng)的各組件需要使用 TLS 證書對...
    潘祖龍閱讀 1,775評論 0 1
  • 環(huán)境規(guī)劃 手里的環(huán)境是四臺安裝了CentOS 7的主機。環(huán)境規(guī)劃如下: Kubernetes Master 節(jié)點:...
    負二貸閱讀 3,310評論 6 26
  • 拖拖拉拉半年多,終于在昨天正式遞交了辭呈,從今天開始就要對過去的生活揮手告別,很奇怪,竟然沒有一絲留戀,整整兩年半...
    半憶夏閱讀 359評論 2 0
  • 前言 在開發(fā)中我們經(jīng)常會遇到使用計時器的情況,例如圖片輪播,進度條的繪制等就是比較常見的應用場景.常用的計時器有C...
    sea_biscute閱讀 15,259評論 1 21