[Kubernetes] Update Kubernetes APIServer certSANs
0x01 Overview
Kubernetes安裝時,如果沒在kubeadm init時額外設定 --apiserver-cert-extra-sans
,或者kubeadm配置檔中設定certSANs,則 APIServer 所使用的 TLS憑證中的SAN清單,僅會有一些預設值,可以透過openssl指令查看當前的SAN包含哪些DNS與IP。
~$ openssl x509 -in apiserver.crt -text
....
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:master-node, IP Address:10.96.0.1, IP Address:10.2.0.11
當一些原因需要額外增加DNS或IP時,就必須先更新APIServer的TLS憑證,否則嘗試連線時就會出現類似以下的錯誤訊息:
Unable to connect to the server: x509: certificate is valid for kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local, master-node, not 10–2–0–11.nip.io
底下主要針對如何更新APIServer certSANs流程做說明,操作的Kubernetes版本為 v1.24.1
。
0x02 更新流程
1.修改kubeadm-config
首先將kube-system/kubeadm-config cm給dump出來。
~$ kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm.yaml
內容大概如下:
接著,將要新增的DNS或IP加上certSANs清單中。
apiServer:
certSANs:
- 10-2-0-11.nip.io
- 10.2.0.11
- 10.96.0.1
2. 產生新的tls憑證
要產生新的tls憑證前,必須先刪除或將舊有的tls憑證移到他處。
~$ mkdir cert_backup
~$ sudo mv /etc/kubernetes/pki/apiserver.{crt,key} cert_backup
接著執行以下指令,產生新的tls憑證。
~$ sudo kubeadm init phase certs apiserver --config kubeadm.yaml
[certs] Generating "apiserver" certificate and key[certs] apiserver serving cert is signed for DNS names [10-2-0-11.nip.io kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local master-node] and IPs [10.96.0.1 10.2.0.11]
如果沒先刪除舊的tls憑證,就執行以上指令的話,會直接使用舊有的憑證,而不會產生新的。
[certs] Using existing apiserver certificate and key on disk
新的tls憑證產生後,可以用文章開頭的openssl指令確認Subject Alternative Name欄位中是否正確。
PS:其實如果單純要產生新的tls憑證,也可以透過以下指令直接產生,不需要產生一個kubeadm.yaml
~$ sudo kubeadm init phase certs apiserver --apiserver-cert-extra-sans=10–2–0–11.nip.io
不過,因為後續還需要將設定寫回kubeadm-config,因此還是得修改kubeadm-config配置檔。
3. 重啟Kubernetes API Server
Kubernetes 1.24後,已經不在支援dockershim,因此這裡使用的是cri-o runtime,可以透過crictl指令查詢apiserver的id,然後刪掉container等待kubelet自動將apiserver重啟。
~$ sudo crictl pods | grep kube-apiserver | cut -d' ' -f1
~$ sudo crictl stopp <pod-id>
~$ sudo crictl rmp <pod-id>
其實直接delete API Server的Pod,好像也是一樣的意思….
4. 更新kubeadm-config
API Server重啟後,可以直接修改 ~/.kube/config
中的server address,然後透過kubectl指令測試是否正常。
如果操作都正常,需將先前第一步修改好的kubeadm-config更新到configmap中。
~$ sudo kubeadm init phase upload-config kubeadm --config kubeadm.yaml
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
更新後,可以也可以透過以下指令確認是否真的更新到configmap上。
~$ kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}'
0x03 結論
本文主要紀錄一下之前更新Kubernetes certSANs的過程,省的每次有需要時都要額外去找資料。
0x04 參考資料
https://blog.scottlowe.org/2019/07/30/adding-a-name-to-kubernetes-api-server-certificate/