Kubernetes集群通常使用 Kubeadm進(jìn)行版本升級,當(dāng)前支持跨一個大版本的升級,例如從 1.19.x 升級到 1.20.x,不支持一個大版本內(nèi)的不同小版本之間的升級,也不支持跨超過 1 個以上的大版本進(jìn)行升級。
在進(jìn)行一個Kubernetes 集群版本升級過程中,集群應(yīng)始終保持在可用狀態(tài),集群中已經(jīng)部署的業(yè)務(wù)對于升級過程也是無感知的 (如果要做到完全無感知,需要業(yè)務(wù)使用的存儲可以隨著 Pod 的驅(qū)逐實現(xiàn)跨節(jié)點遷移) 。
本文中以從1.19.0升級到1.20.0為例進(jìn)行說明,具體升級方法是針對不同類型的節(jié)點上的組件分別進(jìn)行升級。例中的升級步驟主要分為以下4 步:
集群預(yù)檢
升級控制平面
升級數(shù)據(jù)平面
升級其它組件
集群預(yù)檢
預(yù)檢這一步驟主要是為了在 Kubernetes 升級之前對集群的各個組件的狀態(tài)進(jìn)行檢測,以便提高集群升級的成功率,當(dāng)檢測出現(xiàn)異常時則停止后續(xù)的升級步驟。預(yù)檢的內(nèi)容主要包括兩大類:
集群節(jié)點環(huán)境的檢查:
虛機或者裸機節(jié)點的健康狀態(tài)檢查
節(jié)點內(nèi)部系統(tǒng)服務(wù)的檢查:例如NTP、防火墻、內(nèi)核配置等
多Master集群的控制平面和數(shù)據(jù)平面的高可用狀態(tài)的檢查
等等
集群K8s狀態(tài)的檢查:
控制面和數(shù)據(jù)面節(jié)點是否都處于 Ready 狀態(tài)。
Etcd 集群的可用狀態(tài)檢
負(fù)載和服務(wù)的可用狀態(tài)檢查
等等
注意:
面檢查的步驟都不是必須實現(xiàn)的,可以根據(jù)需要選擇一些來完成。
除了上述預(yù)檢之外,kubeadm在執(zhí)行升級步驟中也會進(jìn)行即時性的環(huán)境檢測,以保證升級的成功率。
升級控制平面(Master節(jié)點)
控制平面主要是指Master節(jié)點上的以下組件:
Kubernetes API Server
Kubernetes Scheduler
Kubernetes Controller Manager
Kubelet
Kubeadm
第一步、在 Master 節(jié)點上安裝新版本的 kubeadm
第二步、執(zhí)行以下命令進(jìn)行升級:
kubeadm upgrade apply v1.20.0
此升級過程會針對 Kubernetes API Server、Kubernetes Scheduler 和 Kubernetes Controller Manager 這三個組件生成新版本的配置文件覆蓋舊版本的,Master 節(jié)點上的 Kubelet 會 Watch 到這些改動,會重建對應(yīng)的 Pod。另外還會重新生成 Kube-Proxy DaemonSet 的配置,Node 節(jié)點上所有的 Kube-Proxy 相關(guān)的 Pod 會進(jìn)行重建。
第三步、騰空節(jié)點
通過將節(jié)點標(biāo)記為不可調(diào)度并騰空節(jié)點為節(jié)點作升級準(zhǔn)備:
kubectl drain node_name --ignore-daemonsets
第四步、升級 Kubelet
升級后需要重啟 Kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
第五步、解除節(jié)點的保護(hù)
通過將節(jié)點標(biāo)記為可調(diào)度,讓其重新上線:
kubectl uncordon node_name
如果集群的控制平面是 HA 的情況,在 API Server 前端應(yīng)該有類似 HAProxy的負(fù)載均衡軟件,高可用依賴 HAProxy 對于后端的 API Server 周期性的檢測機制,如果某個 Mater 正在升級,這時 HAProxy 會檢測到,然后后續(xù)的請求就不會轉(zhuǎn)發(fā)到這個 Master 節(jié)點。等升級完成后,狀態(tài)恢復(fù)正常,這時 HAProxy 將其作為正常的后端進(jìn)行請求轉(zhuǎn)發(fā)。
升級數(shù)據(jù)平面(Node 節(jié)點)
數(shù)據(jù)平面是指 Node節(jié)點上的Kubectl和Kubelet等組件。
如果用戶的某個應(yīng)用只有一個 Pod,這種情況下無法做到升級過程中業(yè)務(wù)不會中斷。另外,如果Kubernetes集群只有一個Node節(jié)點,在這升級這一個Node節(jié)點的過程中,這個Pod會被驅(qū)逐,并且由于沒有其它節(jié)點可以調(diào)度,因此會一直處于pending狀態(tài),在這段時間內(nèi)業(yè)務(wù)會完全中斷。
第一步、在 Node 節(jié)點上安裝新版本的kubectl。
第二步、騰空節(jié)點
通過將節(jié)點標(biāo)記為不可調(diào)度并騰空節(jié)點為節(jié)點作升級準(zhǔn)備:
kubectl drain node_name --ignore-daemonsets
注意,這一步需要保證業(yè)務(wù)流量不受到影響,如果某個業(yè)務(wù)有多個 Pod,則需要保證其它節(jié)點上的 Pod 處于正常運行狀態(tài)。
第三步、升級 Kubelet
升級后需要重啟 Kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
第四步、解除節(jié)點的保護(hù)
通過將節(jié)點標(biāo)記為可調(diào)度,讓其重新上線:
kubectl uncordon node_name
升級其它組件
其它組件不僅包括CNI Driver、CSI Driver等基礎(chǔ)能力組件,還包括Ingress Controller、Dashboard、Prometheus、Metric-Server 等用戶或管理員安裝的輔助組件。
當(dāng) Kubernetes 集群進(jìn)行版本升級時,這些組件是否需要升級或者變更需要參考各組件與 Kubernetes 的版本兼容性,本文不再進(jìn)行深入闡述。
幾點解釋
關(guān)于 "騰空節(jié)點"的操作
在升級控制平面和數(shù)據(jù)平面的時候都要先做一個"騰空節(jié)點"的操作,這個操作會首先驅(qū)逐當(dāng)前節(jié)點上的 Pod(不包含控制面Pod和DaemonSet的Pod),然后將當(dāng)前節(jié)點標(biāo)記為不可調(diào)度。待升級完成后,執(zhí)行 uncordon 命令將節(jié)點恢復(fù)正常狀態(tài)。這是 Kubernetes 官方推薦的維護(hù)某一個節(jié)點的標(biāo)準(zhǔn)流程。
如果一個節(jié)點同時作為 Master 和 Node 節(jié)點,如何處理?
按照正常的控制面升級流程即可。
API 轉(zhuǎn)換的問題
目前,整個升級過程,不會涉及到具體業(yè)務(wù)的 API 升級問題,比如從alpha升級到beta版本。用戶如果有這方面的需求,可以使用 kubectl convert 命令在不同 API 版本之間轉(zhuǎn)換清單。例如:kubectl convert -f pod.yaml --output-version v1 & kubectl apply -fpod.yaml 的內(nèi)容,在新的清單文件中,kind 被設(shè)置為 Pod(未變),但 apiVersion 則被修訂了。
升級后,負(fù)載是否需要手動重啟
升級后,因為容器的 spec 中的哈希值已更改,所有容器都會被重新啟動。由于在升級數(shù)據(jù)面的時候已經(jīng)對 Pod 做了驅(qū)逐操作,因此所有的Pod 都已經(jīng)完成了重建操作。