如何在零停機的情況下遷移 Kubernetes 叢集

語言: CN / TW / HK

作者:顧靜(子白)|阿里雲高階研發工程師;謝瑤瑤(初揚)|阿里雲技術專家

導語: 隨著雲原生理念在企業中的深入和踐行,應用容器化的比例大幅提升。是否可以保證應用容器化遷移過程中的平穩切換,保證應用不停機遷移,成為影響使用者業務雲化的一個重要條件。本文整理自阿里云云原生團隊在 KubeCon China 2021 線上峰會的分享實錄,將通過叢集遷移的需求、場景以及實踐方式,介紹如何基於阿里雲容器服務 ACK,在零停機的情況下遷移 Kubernetes 叢集。

大家好,我是謝瑤瑤,來自阿里雲,目前是 Cloud-provider 開源子專案 cloud-provider-alibaba-cloud 專案的 Maintainer。今天由我和我的同事顧靜一起為大家分享如何不停機的遷移 Kubernetes 叢集。顧靜同學也是 cloud-provider-alibaba-cloud 專案的 Maintainer。

我們將從上圖幾個方面來分享如何不停機的遷移 Kubernetes 叢集。首先我們會為大家介紹一下叢集遷移的需求以及應用場景;接著我們會著重介紹如何實現不停機地 Kubernetes 叢集遷移,包括如何進行遷移前的前置檢查,如何做應用的資料遷移與流量遷移等等。

為什麼要遷移 Kubernetes 叢集?

下面簡單介紹下叢集遷移的應用場景。

容器化的應用遷雲

首先我們來看一下容器化的應用遷移場景。近年來雲原生理念已經逐漸深入到了各大公司中。據相關調查統計,將近有 65% 的應用已經實現了容器化,並逐步從線下的資料中心遷移到了雲上,以便充分利用雲的彈性來實現企業的降本增效。是否可以保證應用容器化遷移過程中的平穩切換,保證應用不停機遷移,成為影響使用者業務雲化的一個重要條件。

跨雲同步與遷移 

其次是混合雲場景下的跨雲流量遷移。對使用者來講,如果雲是一個極具價效比的選擇的話,那麼混合雲和多雲的架構進一步為使用者提供了一個低成本全球可達的應用釋出平臺。多雲可以讓使用者的應用部署到多個雲廠商,避免廠商鎖定。同時它能夠提供更高的議價能力、更強的備份、災難恢復能力和更強的穩定性。同時還可以為全球使用者提供基於地理位置的就近服務體驗。如何進行不停機跨雲同步機遷移是部署跨雲/多雲應用的前提。

叢集新特性與 BreakingChange 場景

更高的 Kubernetes 版本往往會具有更多的新特性,但是使用這些新特性並不是沒有代價的。如果你需要使用新特性,那就必須升級 Kubernetes 到對應的新版本。這通常不是一件容易的事情。如果你的叢集版本太低,那麼你需要多次升級叢集才能到達預期的版本。比如從 1.14 依次升級到 1.16,然後是 1.18,然後才是 1.20,這樣來避免單次升級叢集版本過大造成的相容性問題。並且這些新特性所引入的相容性問題還可能造成服務中斷。

除了升級困難以及版本相容性問題,升級已有叢集無法實現一些配置變更類的需求。比如你無法直接變更一個已有叢集的網路模式,比如從 IPTables 切換到 IPVS,Flannel 到 Terway,更改 Cluster CIDR 等。這些變更會造成整個叢集已有節點及 Pod 的重建,造成服務不可用,甚至是整個叢集配置被汙染。因此不停止遷移 Kubernetes 叢集應用在這種情況下可能是一個更好的選擇。

接下來我們介紹一下如何進行不停機遷移。不停機遷移總體上分為 3 個階段。

第一階段:前置檢查,提前暴露遷移可能存在的潛在風險;第二階段是應用遷移,這一階段需要新建一個目標版本的叢集,並將應用及其資料遷移到新的叢集中;第三階段是流量遷移,這一階段至關重要,他決定了如何不停機地將線上流量匯入到新建的叢集中,並使用新建的叢集為使用者提供服務。

首先在前置檢查階段,我們需要儘早的暴露遷移風險,因此我們開發了一套前置檢查框架,用來檢查叢集是否做好了遷移準備。比如不同版本的叢集會有 API groups 相容性,需要提前處理 Label 的相容性,不同版本的元件的行為差異等,如 kubeproxy 處理 SLB 流量轉發的行為差異,會直接影響流量遷移的成功。因此前置檢查是一項非常重要的步驟。

前置檢查項都通過後,接下來就是應用的遷移與流量遷移。

圖片 8.png

應用的遷移可以通過開源元件 Velero 進行,官方有詳細的文件來說明應用的遷移,阿里雲也專門為其提交了阿里雲相關驅動。這裡我們主要介紹一下如何做資料遷移,資料遷移是實現不停機遷移的重要一環,我們會以磁碟儲存和有狀態應用 MySQL/ETCD 的遷移為例,來說明如何進行資料的遷移。

通常雲上的儲存主要有 NFS、OSS 物件儲存、CloudDisk 雲盤等,通常各大雲廠商都為磁碟型別的儲存提供了完善的快照方法及恢復方法。上圖展示瞭如何將上海 Region 的應用資料遷移到杭州 Region 的方法,對於磁碟儲存型別,首先在上海 Region 構建磁碟快照,然後將快照通過雲廠商的網路同步到待恢復的地域杭州,然後通過快照恢復功能建立一塊磁碟,然後掛在到節點上後應用即可隨時使用。

對於自建 MySQL/ ETCD 一類的應用資料,由於其持續讀寫可能造成潛在的資料不一致的情況,我們可以通過為該應用在目標 Region 構建多個 Slave 副本(或者 quorum 副本),用來進行實時資料同步,當流量低峰期到來的時候,執行主從切換,或者強制選主流程。一旦目標 Region 選主完成,則代表切換完成,可以逐步下線原 Region 的 MySQL 或 ETCD 副本。這就是一個簡單的資料遷移流程。

接下來介紹一下流量遷移部分。流量遷移是叢集遷移中十分重要的環節。流量遷移是指在業務流量無中斷的前提下,將業務流量從一個叢集遷移到另一個叢集中去。客戶端對流量遷移應當完全無感。

DNS 是實現無損流量遷移的一種方式。分別在兩個叢集中建立兩個 LoadBalancer 型別 Service,然後將兩個 SLB 新增到 DNS 後端,基於 DNS 的灰度能力實現流量分發到兩個不同的叢集中。這種方式較為簡單,但是有一個比較大的缺陷,DNS 快取有過期時間,流量切換後需要等待 30 分鐘左右才能生效。當在新叢集中進行業務回滾時,這個延遲不可接受的。

另外一種流量遷移方式是基於 Istio 實現的。Istio 方式比較複雜,學習成本比較高。需要新建一個 Istio 叢集,並且更改已有的應用部署方式,然後基於 Istio 的灰度能力進行流量遷移。

圖片 11.png

那麼有沒有一種方式,操作簡單又可以實現實時無損流量遷移呢?

如何在零停機的情況下遷移 Kubernetes 叢集

為了解決這個問題,我們還得從服務暴露方式入手。LoadBalancer 型別的 Service 實際是通過雲上負載均衡器對外部暴露服務的。負載均衡器是由各雲服務提供商通過部署在叢集中的 controller 建立的,創建出來的負載均衡器的資訊會顯示在 Service 的 status.loadBalancer 欄位中。請求訪問雲上負載均衡器時,由各雲廠商負責將流量重定向到後端 Pod 上。

圖片 12.png

Cloud Controller Manager(CCM)就是阿里雲容器服務部署在 Kubernetes 叢集中的 controller,負責對接 Kubernetes 資源及雲上基礎產品,如 SLB、VPC、DNS 等。對於 SLB,CCM 支援兩種流量轉發方式,一種是 ECS 模式,一種是 ENI 模式。ECS 模式將 Node IP 和 NodePort 掛載到 SLB 後端,流量經由 SLB 轉向 Node,然後經過節點的 kube-proxy 轉發至 Pod 上。ENI 模式將 PodIP 及 TargetPort 掛載到 SLB 後端,流量經由 SLB 直接轉發到 Pod 上。與 ECS 模式相比,ENI 模式少了一層網路轉發,網路效能更好。流量轉發模式與 Kubernetes 中網路外掛有關,Flannel 網路外掛預設為 ECS 模式,Terway 網路外掛預設為 ENI 模式。

那麼 CCM 是如何管理 SLB 的呢?

對於 LoadBalancer 型別的 Service,CCM 會為該 Service 建立或配置阿里雲負載均衡 SLB。CCM 首先會查詢 Kubernetes Service 資訊,構建 Local model,然後查詢 SLB 資訊,構建 Remote model。對比兩個 model 的差別,根據 Local model 更新 Remote model,直到兩個 model 一致。當 Service 對應的 Endpoint 或者叢集節點發生變化時,CCM 會自動更新 SLB 的虛擬伺服器組中的後端。此外,CCM 還提供了許多阿里雲特定註解,支援豐富的負載均衡能力。

當用戶訪問 service 時,如果在叢集內部,經由 service 轉發至 Node,經過 kube-proxy 轉發到 Pod。如果訪問負載均衡 ip 時,則通過 SLB 後轉發至節點 Node 或者 Pod上。

瞭解 LoadBalancer service 工作原理後,能不能通過 CCM 實現實時無損流量遷移呢?答案是可以的。將兩個叢集的節點加入到同一個 SLB 的同一個埠中,然後通過修改兩個叢集所佔權重即可實現流量遷移。對於客戶端來講,訪問的仍然是以前的 SLB ip 和 port,完全無感。

圖片 15.png

具體操作如下:首先在 1.14 叢集中建立一個 Service,指定已有 SLB 及埠,以及埠關聯的虛擬伺服器組。然後在 1.20 叢集中建立一個 Service,指定同樣的 SLB、埠及虛擬伺服器組。通過 weight annotation 為兩個叢集設定權重。

配置完成後,流量轉發方式如上圖所示。有 80% 的流量轉發到 1.14 叢集中,20% 的流量轉發到 1.20 叢集中。

兩個叢集共用 SLB 的同一個埠。通過修改 Service 中的 weight annotation 可以動態實時修改流向兩個叢集的流量比例,實現灰度流量遷移。當遷移完成後,從 1.14 叢集中刪除 Service 即可。

設定權重 annotation 後,如何保證叢集內 Pod 負載均衡呢?

圖片 20.png

對於 externalTrafficPolicy 為 Cluster 的 service,CCM 會將所有節點加入到 SLB 後端。每個節點的權重為 weight/NodeNum。此時,Node1,Node2,Node3 權重均為 27,但是三個節點上的 Pod 數量並不均衡,那麼如何實現 Pod 負載均衡呢?Cluster 模式是依賴 kube-proxy 實現的。在 cluster 模式下,kube-proxy 會將所有 Pod 資訊寫入到本地的轉發規則中,並以輪訓的方式向這些 Pod 轉發請求。以 Node3 為例,該節點上沒有 Pod,當請求傳送到 Node3 節點後,kube-proxy 會將請求轉發給 Node1 或者 Node2。

對於 externalTrafficPolicy 為 Local 的 service,CCM 僅會將 Pod 所在節點加入到 SLB 後端。因為如果節點沒有 Pod,當請求轉發至該節點時,請求會被直接丟棄。Local 模式下,需要先計算每個 Pod 的權重,即 PerPodWeight=Weight/TotalPodNum。節點權重為 NodePodNum*PerPodWeight。Node1 為 50,Node2 為 30。由於每個 Pod 的權重都為 10,因此 Pod 間可以實現負載均衡。

圖片 21.png

基於 CCM 的流量遷移方案不僅適用於雲上叢集遷移,還適用於混合雲、跨 Region 遷移及跨雲遷移場景。以混合雲場景為例,客戶可以將線下 ECS 加入到 SLB 後端,然後通過設定權重逐步將流量從線下叢集遷移到線上叢集中,無需進行業務改造,客戶端也是完全無感的。

在新叢集中測試時不可避免的會遇到應用更新的場景。如果保證應用更新的過程中流量無損呢?

應用更新分為兩個步驟,建立新的 Pod,等待 Pod running 後,刪除舊的 Pod。新的 Pod 建立成功後,CCM 會將其掛在到 SLB 後端,如果新建的 Pod 無法提供服務,那麼請求就會失敗。因此,需要為 Pod 新增就緒檢測。僅當 Pod 可以對外服務時,才將其加入到 SLB 後端。在刪除 Pod 時也會遇到同樣的場景。因為 Pod 刪除和從 SLB 後端移除 Pod 是非同步進行的,如果 Pod 以及刪除,但是還未從 SLB 後端移除,就會出現請求轉發到後端,但是無 Pod 處理導致請求失敗的情況。因此需要為 Pod 新增 prestop hook。

Pod 優雅退出過程如上圖所示。首先 kubelet delete pod,然後 endpoint controller 更新 endpoint。更新完畢後,kube-proxy 移除節點轉發規則。CCM 檢測到 endpoint 更新事件後,從 SLB 後端移除 Pod。在apiserver 刪除 Pod 時,kubelet 同時開始刪除 Pod 邏輯,觸發 Pod prestop。在 prestop 結束後傳送 sigterm 資訊。在整個 Pod 優雅退出過程中,直到 CCM 從 SLB 後端移除 Pod 之前一直會有新的流量進入。

由於 CCM 與 kube-proxy 是非同步進行的,因此會出現 SLB 還未移除 Pod,kubeproxy 已經將節點轉發規則清理的情況。此時,請求進入 SLB 後,轉發至 Node上,由於 kube-proxy 已經將路由規則清理了,所以該請求無法處理。將 service 改為 cluster 模式可以解決這一問題。如果 Service 一定需要為 local 模式,那麼需要保證一個節點上有多個 Pod。也可以通過設定 Service 為 eni 模式解決這一問題。

總結來說,叢集遷移可以分為如下三個步驟,前置檢查、應用遷移及流量遷移三個步驟。前置檢查需要檢查不同叢集間 api/Node label 等相容性,應用遷移可以使用開源工具進行,基於 CCM 則可以實現實時無損流量遷移。

本次分享到此結束,謝謝。

近期熱門

1 月成都連連看:

阿里雲容器實踐營 & KubeMeet 技術沙龍限額報名中!

阿里雲容器服務實踐營和 KubeMeet 開源技術沙龍將分別於 2022 年 1 月 13 日 和 1 月 15 日在成都阿里中心天府長島舉辦,為你帶來容器技術產品實踐、開源技術應用案例一站式學習。每場限額 50 人,掃描圖片二維碼火速報名!

點選​此處​,瞭解阿里雲容器服務 ACK 更多詳情: