kubernetes實踐之八:TLS bootstrapping
當叢集開啟了 TLS 認證後,每個節點的 kubelet 元件都要使用由 apiserver 使用的 CA 簽發的有效證書才能與 apiserver 通訊;此時如果節點多起來,為每個節點單獨簽署證書將是一件非常繁瑣的事情;TLS bootstrapping 功能就是讓 kubelet 先使用一個預定的低許可權使用者連線到 apiserver,然後向 apiserver 申請證書,kubelet 的證書由 apiserver 動態簽署;
Bootstrap 是很多系統中都存在的程式,比如 Linux 的bootstrap,bootstrap 一般都是作為預先配置在開啟或者系統啟動的時候載入,這可以用來生成一個指定環境。Kubernetes 的 kubelet 的啟動時同樣可以載入一個這樣的配置檔案,這個檔案的內容類似如下形式:
02b50b05283e98dd0fd71db496ef01e8,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
在配合 RBAC 授權模型下的工作流程大致如下:
二:TLS bootstrapping 相關術語
1.kubernet相關埠
kubelet 元件在工作時,採用主動的查詢機制,即定期請求 apiserver 獲取自己所應當處理的任務,如哪些 pod 分配到了自己身上,從而去處理這些任務;同時 kubelet 自己還會暴露出兩個本身 api 的埠,用於將自己本身的私有 api 暴露出去,這兩個埠分別是 10250 與 10255;對於 10250 埠,kubelet 會在其上採用 TLS 加密以提供適當的鑑權功能;對於 10255 埠,kubelet 會以只讀形式暴露元件本身的私有 api,並且不做鑑權處理
就是說 kubelet 上實際上有兩個地方用到證書,一個是用於與 API server 通訊所用到的證書,另一個是 kubelet 的 10250 私有 api 埠需要用到的證書
2.CSR請求型別
kubelet 發起的 CSR 請求都是由 controller manager 來做實際簽署的,對於 controller manager 來說,TLS bootstrapping 下 kubelet 發起的 CSR 請求大致分為以下三種:
1. nodeclient :使用者的客戶端認證請求 O=system:nodes ,CN=system:node:(node name) 。
2. selfnodeclient :更新具有相同 O 和 CN 的客戶端證書的節點。
3. selfnodeserver :更新服務證書的節點。
nodeclient 型別的 CSR 僅在第一次啟動時會產生,selfnodeclient 型別的 CSR 請求實際上就是 kubelet renew 自己作為 client 跟 apiserver 通訊時使用的證書產生的,selfnodeserver 型別的 CSR 請求則是 kubelet 首次申請或後續 renew 自己的 10250 api 埠證書時產生的
三、TLS bootstrapping 具體引導過程
1.TLS 作用眾所周知 TLS 的作用就是對通訊加密,防止中間人竊聽;同時如果證書不信任的話根本就無法與 apiserver 建立連線,更不用提有沒有許可權向 apiserver 請求指定內容。
2.RBAC 作用
當 TLS 解決了通訊問題後,那麼許可權問題就應由 RBAC 解決(可以使用其他許可權模型,如 ABAC);RBAC 中規定了一個使用者或者使用者組(subject)具有請求哪些 api 的許可權;在配合 TLS 加密的時候,實際上 apiserver 讀取客戶端證書的 CN 欄位作為使用者名稱,讀取 O 欄位作為使用者組.
以上說明:第一,想要與 apiserver 通訊就必須採用由 apiserver CA 簽發的證書,這樣才能形成信任關係,建立 TLS 連線;第二,可以通過證書的 CN、O 欄位來提供 RBAC 所需的使用者與使用者組。
3.kubelet 首次啟動流程
既然 TLS bootstrapping 功能是讓 kubelet 元件去 apiserver 申請證書,然後用於連線 apiserver;那麼第一次啟動時沒有證書如何連線 apiserver ?
在 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 請求
點選(此處)摺疊或開啟
-
cd /etc/kubernetes
-
kubectl create clusterrolebinding kubelet-bootstrap \
-
--clusterrole=system:node-bootstrapper \
- --user=kubelet-bootstrap
建立token.csv命令:
點選(此處)摺疊或開啟
-
export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x |
-
tr -d ' ')
-
cat > token.csv <<eof
</eof
-
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-boots
-
trap"
- EOF
kubelet 要向 kube-apiserver 請求客戶端證書,kubelet 首先需要一個包含 bootstrap 身份驗證 token 的 kubeconfig 檔案路徑。您可以使用 kubectl config set-cluster,set-credentials 和 set-context 來構建此 kubeconfig 檔案。為 kubectl config set-credentials 提供 kubelet-bootstrap 的名稱,幷包含 --token = <token-value>,
點選(此處)摺疊或開啟
-
cd /etc/kubernetes
-
export KUBE_APISERVER="https://x.x.x.x:6443"
-
# 設定叢集引數
-
kubectl config set-cluster kubernetes \
-
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
-
--embed-certs=true \
-
--server=${KUBE_APISERVER} \
- --kubeconfig=bootstrap.kubeconfig
-
# 設定客戶端認證引數
kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=bootstrap.kubeconfig
# 設定上下文引數
kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig
# 設定預設上下?
kubectl config use-context default --kubeconfig=bootstrap.kubeco
nfig
在 kubelet 首次啟動後,如果使用者 Token 沒問題,並且 RBAC 也做了相應的設定,那麼此時在叢集內應該能看到 kubelet 發起的 CSR 請求:
出現 CSR 請求後,可以使用 kubectl 手動簽發(允許) kubelet 的證書
kubectl certificate approve node-csr-ICyEqgl55a222oGUbA3U5CE22roAKo6AoGT6Eff_ehY
當成功簽發證書後,目標節點的 kubelet 會將證書寫入到 --cert-dir= 選項指定的目錄中
而 kubelet 與 apiserver 通訊所使用的證書為 kubelet-client.crt,剩下的 kubelet.crt 將會被用於 kubelet server(10250) 做鑑權使用;注意,此時 kubelet.crt 這個證書是個獨立於 apiserver CA 的自籤 CA,並且刪除後 kubelet 元件會重新生成它
四:證書及配置檔案
1.token.csv
該檔案為一個使用者的描述檔案,基本格式為 Token,使用者名稱,UID,使用者組;這個檔案在 apiserver 啟動時被 apiserver 載入,然後就相當於在叢集內建立了一個這個使用者;接下來就可以用 RBAC 給他授權;持有這個使用者 Token 的元件訪問 apiserver 的時候,apiserver 根據 RBAC 定義的該使用者應當具有的許可權來處理相應請求
2.bootstarp.kubeconfig
該檔案中內建了 token.csv 中使用者的 Token,以及 apiserver CA 證書;kubelet 首次啟動會載入此檔案,使用 apiserver CA 證書建立與 apiserver 的 TLS 通訊,使用其中的使用者 Token 作為身份標識像 apiserver 發起 CSR 請求
3.kubelet-client.crt
該檔案在 kubelet 完成 TLS bootstrapping 後生成,此證書是由 controller manager 簽署的,此後 kubelet 將會載入該證書,用於與 apiserver 建立 TLS 通訊,同時使用該證書的 CN 欄位作為使用者名稱,O 欄位作為使用者組向 apiserver 發起其他請求
4.kubelet.crt
該檔案在 kubelet 完成 TLS bootstrapping 後並且沒有配置 --feature-gates=RotateKubeletServerCertificate=true 時才會生成;這種情況下該檔案為一個獨立於 apiserver CA 的自籤 CA 證書,有效期為 1 年;被用作 kubelet 10250 api 埠
5.apiserver配置檔案
點選(此處)摺疊或開啟
-
###
-
## kubernetes system config
-
##
-
## The following values are used to configure the kube-apiserver
-
##
-
#
-
## The address on the local server to listen to.
-
KUBE_API_ADDRESS="--advertise-address=10.116.137.196 --bind-address=10.116.137.196 --insecure-bind-address=10.116.137.196"
-
#
-
## The port on the local server to listen on.
-
#KUBE_API_PORT="--port=8080"
-
#
-
## Port minions listen on
-
#KUBELET_PORT="--kubelet-port=10250"
-
#
-
## Comma separated list of nodes in the etcd cluster
-
KUBE_ETCD_SERVERS="--etcd-servers=https://10.116.137.196:2379,https://10.116.82.28:2379,https://10.116.36.57:2379"
-
#
-
## Address range to use for services
-
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
-
#
-
## default admission control policies
-
KUBE_ADMISSION_CONTROL="--admission-control=ServiceAccount,NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"
-
#
-
## Add your own!
- KUBE_API_ARGS="--authorization-mode=RBAC --runtime-config=rbac.authorization.k8s.io/v1beta1 --kubelet-https=true --experimental-bootstrap-token-auth --token-auth-file=/etc/kubernetes/token.csv --service-node-port-range=30000-32767 --tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem --tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem --client-ca-file=/etc/kubernetes/ssl/ca.pem --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem --etcd-cafile=/etc/kubernetes/ssl/ca.pem --etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem --etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem --enable-swagger-ui=true --apiserver-count=1 --audit-log-maxage=30 --audit-log-maxbackup=3 --audit-log-maxsize=100 --audit-log-path=/var/lib/audit.log --event-ttl=1h"
點選(此處)摺疊或開啟
-
## kubelet (minion) config
-
#
-
## The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
-
KUBELET_ADDRESS="--address=10.116.82.28"
-
#
-
## The port for the info server to serve on
-
#KUBELET_PORT="--port=10250"
-
#
-
## You may leave this blank to use the actual hostname
-
KUBELET_HOSTNAME="--hostname-override=10.116.82.28"
-
#
-
## location of the api-server
-
#KUBELET_API_SERVER="--api-servers=http://10.116.137.196:8080"
-
#
-
## pod infrastructure container
-
#KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=sz-pg-oam-docker-hub-001.tendcloud.com/library/pod-infrastructure:rhel7"
-
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure"
-
#
-
## Add your own!
- KUBELET_ARGS="--cgroup-driver=systemd --cluster-dns=10.254.0.2 --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig --kubeconfig=/etc/kubernetes/kubelet.kubeconfig --require-kubeconfig --cert-dir=/etc/kubernetes/ssl --cluster-domain=cluster.local. --hairpin-mode promiscuous-bridge --serialize-image-pulls=false --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28624388/viewspace-2152197/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- kubernetes實踐之二:建立TLS證書和金鑰TLS
- kubernetes實踐之三:ETCD TLS證書叢集安裝TLS
- kubernetes實踐之十一:EFK
- kubernetes實踐之六十:Cabin-Manage Kubernetes
- kubernetes實踐之五十七:PodPreset
- kubernetes實踐之五十八:CronJob
- kubernetes實踐之五十二:Helm
- kubernetes實踐之五十九:NetworkPolicy
- kubernetes實踐之十九:API概述API
- kubernetes實踐之十七:架構架構
- kubernetes實踐之十:Kubernetes-dashboard+Heapster+InfluxDB+GrafanaUXGrafana
- kubernetes實踐之四十二:StatefulSet
- kubernetes實踐之六十四:CoreDNSDNS
- kubernetes實踐之五十六:雲原生
- kubernetes實踐之五:網路模型模型
- kubernetes實踐之十二:部署Traefik Ingress
- kubernetes實踐之九:kube-dnsDNS
- GitOps實踐之kubernetes安裝argocdGitGo
- kubernetes實踐之五十五:kubectl之配置kubeconfig
- kubernetes實踐之十四:Service Account與Secret
- kubernetes實踐之四十七:ResourceQuota ControllerController
- kubernetes實踐之六十五:Service Mesh
- kubernetes實踐之六十二:Secret 使用
- kubernetes實踐之六十三:使用技巧
- kubernetes生產實踐之redis-clusterRedis
- Kubernetes安裝之八:配置master之schedulerAST
- kubernetes實踐之七十二:Istio之策略與遙測
- kubernetes實踐之七十三:Istio之配置請求路由路由
- kubernetes實踐之七十:Istio之流量管理(上)
- kubernetes實踐之十六:RBAC 角色訪問控制
- kubernetes實踐之四十九:Scheduler原理分析
- kubernetes實踐之四十四:Ingress詳解
- kubernetes實踐之四十三: Service詳解
- kubernetes實踐之五:Node節點安裝
- kubernetes實踐之五十四:垃圾回收機制
- kubernetes實踐之六十七:Istio介紹
- kubernetes實踐之六:CFSSL構建本地CA
- kubernetes實踐之十五:Kubernetes叢集主要啟動引數說明