更新 Kubernetes APIServer 證書
本文我們將了解如何將一個新的 DNS 名稱或者 IP 地址添加到 Kubernetes APIServer 使用的 TLS 證書中。在某些情況下默認的證書包含的名稱可能不能滿足我們的要求,又或者是 APIServer 地址有所變化,都需要重新更新證書。

我們這里的集群是使用 kubeadm 搭建的單 master 集群,使用的也是 kubeadm 在啟動集群時創(chuàng)建的默認證書授權(quán) CA,對于其他環(huán)境的集群不保證本文也同樣適用。
介紹
Kubernetes APIServer 使用數(shù)字證書來加密 APIServer 的相關(guān)流量以及驗證到 APIServer 的連接。所以如果我們想使用命令行客戶端(比如 kubectl)連接到 APIServer,并且使用的主機名或者 IP 地址不包括在證書的 subject 的備選名稱(SAN)列表中的話,訪問的時候可能會出錯,會提示對指定的 IP 地址或者主機名訪問證書無效。要解決這個問題就需要更新證書,使 SAN 列表中包含所有你將用來訪問 APIServer 的 IP 地址或者主機名。
更新 APIServer 證書
因為集群是使用 kubeadm 搭建的,所以我們可以直接使用 kubeadm 來更新 APIServer 的證書,來保證在 SAN 列表中包含額外的名稱。
首頁我們一個 kubeadm 的配置文件,如果一開始安裝集群的時候你就是使用的配置文件,那么我們可以直接更新這個配置文件,但是如果你沒有使用配置文件,直接使用的 kubeadm init 來安裝的集群,那么我們可以從集群中獲取 kubeadm 的配置信息來創(chuàng)建一個配置文件,因為 kubeadm 會將其配置寫入到 kube-system 命名空間下面一個名為 kubeadm-config 的 ConfigMap 中??梢灾苯訄?zhí)行如下所示的命令將該配置導(dǎo)出:
$?kubectl?-n?kube-system?get?configmap?kubeadm-config?-o?jsonpath='{.data.ClusterConfiguration}'?>?kubeadm.yaml
上面的命令會導(dǎo)出一個名為 kubeadm.yaml 的配置文件,內(nèi)容如下所示:
apiServer:
??extraArgs:
????authorization-mode:?Node,RBAC
??timeoutForControlPlane:?4m0s
apiVersion:?kubeadm.k8s.io/v1beta2
certificatesDir:?/etc/kubernetes/pki
clusterName:?kubernetes
controllerManager:?{}
dns:
??type:?CoreDNS
etcd:
??local:
????dataDir:?/var/lib/etcd
imageRepository:?registry.aliyuncs.com/k8sxio
kind:?ClusterConfiguration
kubernetesVersion:?v1.17.11
networking:
??dnsDomain:?cluster.local
??podSubnet:?10.244.0.0/16
??serviceSubnet:?10.96.0.0/12
scheduler:?{}
上面的配置中并沒有列出額外的 SAN 信息,我們要添加一個新的數(shù)據(jù),需要在 apiServer 屬性下面添加一個 certsSANs 的列表。如果你在啟動集群的使用就使用的了 kubeadm 的配置文件,可能里面就已經(jīng)包含 certSANs 列表了,如果沒有我們就需要添加它,比如我們這里要添加一個新的域名 api.k8s.local 以及 ydzs-master2 和 ydzs-master3 這兩個主機名和 10.151.30.70、10.151.30.71 這兩個新的 IP 地址,那么我們需要在 apiServer 下面添加如下所示的數(shù)據(jù):
apiServer:
??certSANs:
??-?api.k8s.local
??-?ydzs-master2
??-?ydzs-master3
??-?10.151.30.11
??-?10.151.30.70
??-?10.151.30.71
??extraArgs:
????authorization-mode:?Node,RBAC
??timeoutForControlPlane:?4m0s
上面我只列出了 apiServer 下面新增的 certSANs 信息,這些信息是包括在標準的 SAN 列表之外的,所以不用擔(dān)心這里沒有添加 kubernetes、kubernetes.default 等等這些信息,因為這些都是標準的 SAN 列表中的。
更新完 kubeadm 配置文件后我們就可以更新證書了,首先我們移動現(xiàn)有的 APIServer 的證書和密鑰,因為 kubeadm 檢測到他們已經(jīng)存在于指定的位置,它就不會創(chuàng)建新的了。
$?mv?/etc/kubernetes/pki/apiserver.{crt,key}?~
然后直接使用 kubeadm 命令生成一個新的證書:
$?kubeadm?init?phase?certs?apiserver?--config?kubeadm2.yaml
W0902?10:05:28.006627?????832?validation.go:28]?Cannot?validate?kubelet?config?-?no?validator?is?available
W0902?10:05:28.006754?????832?validation.go:28]?Cannot?validate?kube-proxy?config?-?no?validator?is?available
[certs]?Generating?"apiserver"?certificate?and?key
[certs]?apiserver?serving?cert?is?signed?for?DNS?names?[ydzs-master?kubernetes?kubernetes.default?kubernetes.default.svc?kubernetes.default.svc.cluster.local?api.k8s.local?ydzs-master2?ydzs-master3]?and?IPs?[10.96.0.1?123.59.188.12?10.151.30.11?10.151.30.70?10.151.30.71]
通過上面的命令可以查看到 APIServer 簽名的 DNS 和 IP 地址信息,一定要和自己的目標簽名信息進行對比,如果缺失了數(shù)據(jù)就需要在上面的 certSANs 中補齊,重新生成證書。
該命令會使用上面指定的 kubeadm 配置文件為 APIServer 生成一個新的證書和密鑰,由于指定的配置文件中包含了 certSANs 列表,那么 kubeadm 會在創(chuàng)建新證書的時候自動添加這些 SANs。
最后一步是重啟 APIServer 來接收新的證書,最簡單的方法是直接殺死 APIServer 的容器:
$?docker?ps?|?grep?kube-apiserver?|?grep?-v?pause
7fe227a5dd3c????????aa63290ccd50???????????????????????????????"kube-apiserver?--ad…"???14?hours?ago????????Up?14?hours?????????????????????????????k8s_kube-apiserver_kube-apiserver-ydzs-master_kube-system_6aa38ee2d66b7d9b6660a88700d00581_0
$?docker?kill?7fe227a5dd3c
7fe227a5dd3c
容器被殺掉后,kubelet 會自動重啟容器,然后容器將接收新的證書,一旦 APIServer 重啟后,我們就可以使用新添加的 IP 地址或者主機名來連接它了,比如我們新添加的 api.k8s.local。
驗證
要驗證證書是否更新我們可以直接去編輯 kubeconfig 文件中的 APIServer 地址,將其更換為新添加的 IP 地址或者主機名,然后去使用 kubectl 操作集群,查看是否可以正常工作。
當然我們可以使用 openssl 命令去查看生成的證書信息是否包含我們新添加的 SAN 列表數(shù)據(jù):
$?openssl?x509?-in?/etc/kubernetes/pki/apiserver.crt?-text
Certificate:
??????......
????????Subject:?CN=kube-apiserver
????????......
????????????X509v3?Subject?Alternative?Name:
????????????????DNS:ydzs-master,?DNS:kubernetes,?DNS:kubernetes.default,?DNS:kubernetes.default.svc,?DNS:kubernetes.default.svc.cluster.local,?DNS:api.k8s.local,?DNS:ydzs-master2,?DNS:ydzs-master3,?IP?Address:10.96.0.1,?IP?Address:123.59.188.12,?IP?Address:10.151.30.11,?IP?Address:10.151.30.70,?IP?Address:10.151.30.71
......
更新集群配置
如果上面的操作都一切順利,最后一步是將上面的集群配置信息保存到集群的 kubeadm-config 這個 ConfigMap 中去,這一點非常重要,這樣以后當我們使用 kubeadm 來操作集群的時候,相關(guān)的數(shù)據(jù)不會丟失,比如升級的時候還是會帶上 ?certSANs 中的數(shù)據(jù)進行簽名的。
$?kubeadm?config?upload?from-file?--config?kubeadm.yaml
使用上面的命令保存配置后,我們同樣可以用下面的命令來驗證是否保存成功了:
$?kubectl?-n?kube-system?get?configmap?kubeadm-config?-o?yaml
更新 APIServer 證書的名稱在很多場景下都會使用到,比如在控制平面前面添加一個負載均衡器,或者添加新的 DNS 名稱或 IP 地址來使用控制平面的端點,所以掌握更新集群證書的方法也是非常有必要的。
K8S進階訓(xùn)練營,點擊下方圖片了解詳情

