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