【智簡聯接,萬物互聯】華為云·云享專家董昕:Serverless和微服務下, IoT的變革蓄勢待發
1094
2025-04-02
kubeadm創建的Kubernetes集群證書續期
Kubernetes cluster certificate created by kubeadm expires renewal
以1.9版本為例
編譯kubeadm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# wget https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz
# tar -C /usr/local -xzf go1.11.5.linux-amd64.tar.gz
# export PATH=$PATH:/usr/local/go/bin
# go get -d k8s.io/kubernetes??#下載kubernetes源碼,500多M
# cd go/src/k8s.io/kubernetes/ #進入kubernetes源碼目錄
# git branch???????????????? #查看當前分支
* master
# git tag -l???????????????? #查看所有分支
# git checkout v1.9.4????????#切換到指定分支
HEAD is now at bee2d15... Merge pull request #61045 from liggitt/subpath-1.9
# git branch
* (detached from v1.9.4)
master
# vim vendor/k8s.io/client-go/util/cert/cert.go??#修改107行、152行
107???????????????? NotAfter:???? time.Now().Add(duration365d * 10).UTC(),
152???????????????? NotAfter:??time.Now().Add(time.Hour * 24 * 3650),
如上,kubeadm生成的證書時間由一年變更為10年,其他版本編譯過程差不多
源碼在這里
https://github.com/kubernetes/kubernetes/blob/release-1.9/staging/src/k8s.io/client-go/util/cert/cert.go#L107
如果修改錯誤,編譯完成的話,先清理,再次編譯即可
1
2
3
4
5
6
7
# ./build/make-clean.sh
# make all WHAT=cmd/kubeadm GOFLAGS=-v
# ls _output/local/bin/linux/amd64/
conversion-gen??deepcopy-gen??defaulter-gen??go-bindata??kubeadm??openapi-gen??teststale
# _output/local/bin/linux/amd64/kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"9+", GitVersion:"v1.9.4-dirty", GitCommit:"bee2d1505c4fe820744d26d41ecd3fdd4a3d6546", GitTreeState:"dirty", BuildDate:"2019-01-29T08:45:42Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"}
如果是新的集群,直接用此kubeadm創建集群好了,以下忽略。如果是正在運行的集群快要到期,用下面方式.
以下步驟已在我的生產環境驗證
當前配置
以2臺主機舉例,1 master節點,1 node節點
1
2
3
4
5
[root@master ~]# cat /etc/hosts
127.0.0.1?? localhost localhost.localdomain localhost4 localhost4.localdomain4
::1???????? localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.12.40 master
192.168.12.18 node
當前狀態
1
2
3
4
[root@master ~]# kubectl get no
NAME??????STATUS????ROLES???? AGE?????? VERSION
master????Ready???? master????20d?????? v1.9.4
node??????Ready????
查詢現在證書時間
1
2
3
4
5
6
7
8
9
10
11
[root@master ~]# openssl x509 -in /etc/kubernetes/pki/apiserver-kubelet-client.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1200214740602462488 (0x10a804f293cc2118)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Jan 29 06:34:48 2019 GMT
Not After : Jan 29 06:34:49 2020 GMT
Subject: O=system:masters, CN=kube-apiserver-kubelet-client
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
[root@master ~]# cat /etc/kubernetes/config.yaml
apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
etcd:
endpoints:
- https://192.168.12.40:2379????#three master node
- https://192.168.12.18:2379
caFile: /etc/etcd/ssl/ca.pem??#same as etcd ca
certFile: /etc/etcd/ssl/etcd.pem
keyFile: /etc/etcd/ssl/etcd-key.pem
dataDir: /var/lib/etcd
networking:
podSubnet: 20.244.0.0/21
kubernetesVersion: 1.9.4
api:
advertiseAddress: "192.168.12.40"?? #kube-api VIP
token: "f6a0d5.ecf8a4377dc9dbae"
tokenTTL: "0s"
apiServerCertSANs:
- master
- 192.168.12.40
- 192.168.12.18
- 127.0.0.1
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- kubernetes.default.svc.cluster
- kubernetes.default.svc.cluster.local
- 10.96.0.1
- 20.244.0.1
featureGates:
CoreDNS: true
更換kubeadm
替換編譯后的kubeadm
1
2
3
[root@master ~]# mv /usr/bin/kubeadm{,.bak}
[root@master ~]# cp _output/local/bin/linux/amd64/kubeadm /usr/bin/kubeadm
[root@master ~]# scp kubeadm node:/usr/bin/
更改配置
kubelet配置和kube-controller-manager配置更改
kubelet配置
增加feature-gates
1
--feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true
1
2
3
# vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true"
kube-controller-manager配置
增加feature-gates和experimental-cluster-signing-duration
1
2
--feature-gates=RotateKubeletServerCertificate=true
--experimental-cluster-signing-duration=87600h0m0s
1
2
3
4
5
# vim /etc/kubernetes/manifests/kube-controller-manager.yaml
- --node-cidr-mask-size=24
- --feature-gates=RotateKubeletServerCertificate=true
- --experimental-cluster-signing-duration=87600h0m0s
image: gcr.io/google_containers/kube-controller-manager-amd64:v1.9.4
添加ClusterRoleBinding綁定
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
# cat >> update.yaml < apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver rules: - apiGroups: - certificates.k8s.io resources: - certificatesigningrequests/selfnodeserver verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kubeadm:node-autoapprove-certificate-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:nodes EOF [root@master ~]# kubectl apply -f update.yaml clusterrole "system:certificates.k8s.io:certificatesigningrequests:selfnodeserver" created clusterrolebinding "kubeadm:node-autoapprove-certificate-server" created 查看當前系統配置 1 2 3 4 5 6 7 8 9 [root@master ~]# ls /etc/kubernetes/ admin.conf?????????????? kubelet.conf???????????? scheduler.conf config.yaml??????????????manifests/?????????????? ssl/ controller-manager.conf??pki/ [root@master ~]# ls /etc/kubernetes/pki/ apiserver.crt???????????????? ca.crt??????????????front-proxy-client.crt apiserver.key???????????????? ca.key??????????????front-proxy-client.key apiserver-kubelet-client.crt??front-proxy-ca.crt??sa.key apiserver-kubelet-client.key??front-proxy-ca.key??sa.pub 更新證書 重新初始化kubernetes集群 備份,并使用更改時間的kubeadm重新初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@master ~]# cp -r /etc/kubernetes/ /tmp/ [root@master ~]# rm -f /etc/kubernetes/pki/apiserver* /etc/kubernetes/pki/front-proxy-client.* [root@master ~]# kubeadm alpha phase certs apiserver --config /etc/kubernetes/config.yaml [certificates] Generated apiserver certificate and key. [certificates] apiserver serving cert is signed for DNS names [master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.12.40 192.168.12.40 192.168.12.18 127.0.0.1 10.96.0.1 20.244.0.1] [root@master ~]# kubeadm alpha phase certs apiserver-kubelet-client --config /etc/kubernetes/config.yaml [certificates] Generated apiserver-kubelet-client certificate and key. [root@master ~]# kubeadm alpha phase certs front-proxy-client --config /etc/kubernetes/config.yaml [certificates] Generated front-proxy-client certificate and key. [root@master ~]# kubeadm alpha phase kubeconfig all --config /etc/kubernetes/config.yaml [kubeconfig] Using existing up-to-date KubeConfig file: "admin.conf" [kubeconfig] Using existing up-to-date KubeConfig file: "kubelet.conf" [kubeconfig] Using existing up-to-date KubeConfig file: "controller-manager.conf" [kubeconfig] Using existing up-to-date KubeConfig file: "scheduler.conf" [root@master ~]# reboot [root@master ~]# /bin/cp /etc/kubernetes/admin.conf .kube/config 1 2 3 4 5 6 7 8 9 10 11 [root@master ~]# openssl x509 -in /etc/kubernetes/pki/apiserver-kubelet-client.crt -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 296656465301295716 (0x41def7bc29b5264) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=kubernetes Validity Not Before: Jan 29 06:34:48 2019 GMT Not After : Feb 16 02:48:51 2029 GMT Subject: O=system:masters, CN=kube-apiserver-kubelet-client node節點操作 更改kubelet配置后重新加入集群 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@node ~]# vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf [root@node ~]# cp -r /etc/kubernetes/ /tmp/ [root@node ~]# rm -f /etc/kubernetes/pki/ca.crt /etc/kubernetes/kubelet.conf [root@node ~]# systemctl daemon-reload [root@node ~]# systemctl stop kubelet [root@node ~]# kubeadm join --token f6a0d5.ecf8a4377dc9dbae?192.168.12.40:6443 --discovery-token-ca-cert-hash sha256:51a0d767b6be6db863a7087fa1c872c45dcd7eeed3cf0eeeb88ca69df474fc45 [preflight] Running pre-flight checks. [WARNING FileExisting-crictl]: crictl not found in system path [preflight] Starting the kubelet service [discovery] Trying to connect to API Server "192.168.12.40:6443" [discovery] Created cluster-info discovery client, requesting info from "https://192.168.12.40:6443" [discovery] Requesting info from "https://192.168.12.40:6443" again to validate TLS against the pinned public key [discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "192.168.12.40:6443" [discovery] Successfully established connection with API Server "192.168.12.40:6443" This node has joined the cluster: * Certificate signing request was sent to master and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the master to see this node join the cluster. [root@node ~]# tail -f /var/log/messages discovery-token 不記得? 1 [root@node ~]# grep token\: /etc/kubernetes/bootstrap-kubelet.conf discovery-token-ca-cert-hash 忘了的話 1 [root@master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@master ~]# kubectl get no NAME??????STATUS????ROLES???? AGE?????? VERSION master????Ready???? master????20d?????? v1.9.4 node??????Ready???? [root@master ~]# kubectl get csr NAME?????????????????????????????????????????????????? AGE?????? REQUESTOR???????????????? CONDITION csr-bd9q4??????????????????????????????????????????????2m????????system:node:master????????Approved,Issued csr-fvjpv??????????????????????????????????????????????38s?????? system:node:node??????????Approved,Issued node-csr-wiBwE2ZfO6brsCjPrgEqid4oSiUBGIeAyv0g3IZkur8?? 20d?????? system:bootstrap:f6a0d5?? Approved,Issued [root@node ~]# ll /var/lib/kubelet/pki/ total 20 -rw-r--r-- 1 root root??883 Feb 19 10:52 kubelet-client.crt -rw------- 1 root root??227 Jan 29 14:44 kubelet-client.key -rw-r--r-- 1 root root 1090 Jan 29 14:44 kubelet.crt -rw------- 1 root root 1675 Jan 29 14:44 kubelet.key -rw------- 1 root root 1220 Feb 19 10:52 kubelet-server-2019-02-19-10-52-26.pem lrwxrwxrwx 1 root root?? 59 Feb 19 10:52 kubelet-server-current.pem -> /var/lib/kubelet/pki/kubelet-server-2019-02-19-10-52-26.pem 至此,證書更新完成 設計理論 kubelet服務證書引導和自動更新過程說明 當kubelet首次啟動時,它會生成一個自簽名證書/密鑰對,用于接受傳入的TLS連接。 此過程涵蓋了在本地生成密鑰,然后向集群API服務器發出證書簽名請求以獲取由集群證書頒發機構簽名的關聯證書的過程等。此外,當證書接近過期時,將使用相同的機制來請求更新的證書。 1,查看本機現有的證書/密鑰對,如果存在就使用 2,如果不存在,在kubelet當前生成密鑰和證書的位置,生成一個密鑰,創建證書簽名請求,從API服務器請求簽名證書,等待回應,將新證書/密鑰對存儲在–cert-dir指定的目錄中 自動更新Kubelet服務器證書過程:通過生成新的私鑰,向API服務器發出新的證書簽名請求(CSR/Certificate Signing Request),安全地更新磁盤上的證書/密鑰對,開始使用新的證書/密鑰對 1,將新的證書/密鑰對存儲在–cert-dir指定的目錄中,如果未指定,則將其存儲在默認值中。 需允許kubelet有一個位置,用于存儲在任何給定時刻可能具有的多個證書/密鑰對(因為正在進行輪換) 2,將有一個特定功能來啟用證書引導和輪轉,RotateKubeletServerCertificate 3,將kubelet代碼中的證書訪問集中到CertificateManager。 CertificateManager將負責: ※ 提供用于建立TLS連接的正確證書。 ※ 當前證書即將到期時生成新私鑰并請求新證書。 ※ 由于證書可以隨時輪換,因此每次使用證書時,kubelet的所有其他部分都應向CertificateManager詢問正確的證書。 除CertificateManager外沒有證書緩存。 ※ 在證書輪轉正在進行中發生的kubelet崩潰或重新啟動恢復(請求已發出但尚未簽名等) 4,將更新節點的RBAC角色,以允許節點請求新證書。 5,讓CertificateManager在證書過期時重復CSR過程。 ※ 超過配置的持續時間閾值時,將請求新證書。 ※ 確保正確安全的文件結構,包含下面5點 僅存在于內存中的私鑰,如果中斷就被放棄 當接收到相應的簽名證書時,證書/密鑰對將被寫入單個文件,例如kubelet-server-.pem 將kubelet-server-updated.pem文件軟連接到新的證書/秘鑰對 刪除kubelet-server-current.pem 將kubelet-server-updated.pem移動到kubelet-server-current.pem 6,證書請求簽名(Certificate Request Signing)API被硬編碼為頒發證書1年 實際過程 kubelet 進程接收 –rotate-certificates 參數,該參數決定 kubelet 在當前使用的證書即將到期時, 是否會自動申請新的證書。 由于證書輪換是 beta 特性,必須通過參數 –feature-gates=RotateKubeletClientCertificate=true 進行啟用。 kube-controller-manager 進程接收 –experimental-cluster-signing-duration 參數,該參數控制證書簽發的有效期限。 當 kubelet 啟動時,如被配置為自舉(使用–bootstrap-kubeconfig 參數),kubelet 會使用其初始證書連接到 ,并發送證書簽名的請求。 可以通過以下方式查看證書簽名請求的狀態: 1 kubectl get csr 最初,來自節點上 kubelet 的證書簽名請求處于 Pending 狀態。 如果證書簽名請求滿足特定條件, 控制管理器會自動批準,此時請求會處于 Approved 狀態。 接下來,控制器管理器會簽署證書, 證書的有效期限由 –experimental-cluster-signing-duration 參數指定,簽署的證書會被附加到證書簽名請求中。 Kubelet 會從 Kubernetes API 取回簽署的證書,并將其寫入磁盤,存儲位置通過 –cert-dir 參數指定。 然后 kubelet 會使用新的證書連接到 Kubernetes API。 當簽署的證書即將到期時,kubelet 會使用 Kubernetes API,發起新的證書簽名請求。 同樣地,控制管理器會自動批準證書請求,并將簽署的證書附加到證書簽名請求中。 Kubelet 會從 Kubernetes API 取回簽署的證書,并將其寫入磁盤。 然后它會更新與 Kubernetes API 的連接,使用新的證書重新連接到 Kubernetes API。 詳細過程 當調用kubeadm init時,kubelet配置將在/var/lib/kubelet/config.yaml中寫入到磁盤,并上載到群集中的ConfigMap(kubectl describe configmap -n kube-system kubeadm-config 查看)。ConfigMap名為kubelet-config-1.X,其中.X是您正在初始化的Kubernetes版本的次要版本。還將kubelet配置文件寫入/etc/kubernetes/kubelet.conf,并為群集中的所有kubelet提供基線群集(baseline cluster-wide)范圍配置。此配置文件指向允許kubelet與API服務器通信的客戶端證書。這解決了將群集級配置傳播到每個kubelet的需要。 初始化集群的時候已經指定了token( kubeadm token generate) ,node節點 join master節點也寫明了此token。kubelet要向 kube-apiserver 請求客戶端證書,kubelet 首先需要一個包含 bootstrap 身份驗證 token 的 kubeconfig 文件路徑。啟動 kubelet 時,如果 –kubeconfig 指定的文件不存在,則使用 bootstrap kubeconfig 向 API server 請求客戶端證書。在批準 kubelet 的證書請求和回執時,將包含了生成的密鑰和證書的 kubeconfig 文件寫入由 -kubeconfig 指定的路徑。證書和密鑰文件將被放置在由 –cert-dir 指定的目錄中。 API服務器中的Bootstrap Authenticator會讀取由token信息組成的Secrets。node節點執行 kubeadm join 時,kubeadm使用Bootstrap Token憑據執行TLS引導程序,該引導程序獲取下載kubelet-config-1.X ConfigMap所需的憑據并將其寫入/var/lib/kubelet/config.yaml。動態環境文件的生成方式與kubeadm init完全相同。在kubelet加載新配置之后,kubeadm會寫入/etc/kubernetes/bootstrap-kubelet.conf KubeConfig文件,該文件包含CA證書和Bootstrap Token。這些由kubelet用于執行TLS Bootstrap并獲得唯一的憑證,該憑證存儲在/etc/kubernetes/kubelet.conf中。寫入此文件后,kubelet已完成執行TLS Bootstrap kubelet 使用的 bootstrap.kubeconfig 配置文件中包含apiserver的ca證書和此token,與 apiserver 建立 TLS 通訊,使用 bootstrap.kubeconfig 中的用戶 Token等信息組成的secret 來向 apiserver 聲明自己的 RBAC 授權身份 在默認情況下,kubelet 通過 bootstrap.kubeconfig 中的預設用戶 Token 聲明了自己的身份,然后創建 CSR 請求,1.9版本中默認是允許的。用于TLS Bootstrap的KubeConfig文件是/etc/kubernetes/bootstrap-kubelet.conf,但僅在/etc/kubernetes/kubelet.conf不存在時使用。 kube-controller-manager為了批準CSR,您需要告訴控制器管理員批準它們是可以接受的。這是通過向正確的組授予RBAC權限來完成的。有兩組不同的權限: ※ nodeclient:如果節點正在為節點創建新證書,則它還沒有證書。它使用上面列出的一個令牌進行身份驗證,因此是該群組的一部分system:bootstrappers。 ※ selfnodeclient:如果某個節點正在續訂其證書,那么它已經擁有一個證書(根據定義),它會連續使用該證書作為該組的一部分進行身份驗證system:nodes。 要使kubelet能夠請求和接收新證書,請創建一個ClusterRoleBinding將引導節點所屬的組綁定system:bootstrappers到ClusterRole授予其權限的組,即system:certificates.k8s.io:certificatesigningrequests:nodeclient。即上面配置的update.yaml kube-controller-manager 默認簽發證書時間是1年,所以要更改時間,對 kubelet 發起的特定 CSR 請求自動批準即可,TLS bootstrapping 時的證書實際是由 kube-controller-manager 組件來簽署的 1. kubelet 讀取 bootstrap.kubeconfig,使用其 CA 與 Token 向 apiserver 發起第一次 CSR 請求(nodeclient) 2. apiserver 根據 RBAC 規則自動批準首次 CSR 請求(approve-node-client-csr),并下發證書(kubelet-client.crt) 3. kubelet 使用剛剛簽發的證書(O=system:nodes, CN=system:node:NODE_NAME)與 apiserver 通訊,并發起申請kubelet(10250端口) 所使用證書的 CSR 請求 4. apiserver 根據 RBAC 規則自動批準 kubelet 為其 10250 端口申請的證書(kubelet-server-current.crt) 證書即將到期時,kubelet 自動向 apiserver 發起用于與 apiserver 通訊所用證書的 renew CSR 請求和 renew 本身 kubelet(10250端口) 端口所用證書的 CSR 請求 5. apiserver 根據 RBAC 規則自動批準兩個證書 6. kubelet 拿到新證書后關閉所有連接,reload 新證書,以后便一直如此 參考 https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/ https://k8smeetup.github.io/docs/tasks/tls/certificate-rotation/ https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init-phase/ https://sealyun.com/post/kubeadm-dev/ https://github.com/kubernetes/kubeadm/issues/581 https://k8smeetup.github.io/docs/tasks/administer-cluster/kubeadm-upgrade-ha/ https://k8smeetup.github.io/docs/admin/kubelet-tls-bootstrapping/ https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/ 1.13的版本準備拿來用,把1.9改為1.13版本 支持外部自簽名的證書(避免更換一次證書) 支持自定義鏡像倉庫(避免從谷歌拉取不到鏡像) 華為云APP Kubernetes
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。