UCloud首爾機房總體熱遷移是這樣煉成的

2018年下半年,UCloud首爾數據中心因外部緣由沒法繼續使用,須要在很短期內將機房所有遷走。爲了避免影響用戶現網業務,咱們放棄了離線遷移方案,選擇了很是有挑戰的機房總體熱遷移。通過5個月的多部門協做,終於完成了既定目標,在用戶無感知下,將全部業務完整遷移到一樣位於首爾的新機房內。算法

本文將詳述這個大項目中最有難度的工做之一:公共組件與核心管理模塊遷移的方案設計和實踐歷程。數據庫

計劃後端

整個項目劃分爲四個大階段(準備階段、新機房建設、新舊遷移、舊機房裁撤下線)。正如一位同事的比喻,機房的熱遷移,至關於把一輛高速行駛高鐵上的用戶遷移到另外一輛高速行駛的高鐵上,高鐵是咱們的機房,高鐵上的用戶是咱們的業務。要讓遷移可行須要兩輛高鐵相對靜止,一個方法是把兩輛高鐵變成一輛,如此二者速度就一致了。UCloud機房熱遷移採用相似方案,把兩個機房在邏輯上變成一個機房。爲此,上層的業務邏輯要在新老機房間無縫遷移,下面的管理系統也要統一成一套。安全

其中,咱們SRE和應用運維團隊主要負責如下幾個工做:1)機房核心zookeeper服務的擴縮容服務;2)核心數據庫中間層udatabase服務的部署和擴容;3)大部分管理服務的部署和遷移;4)核心數據庫的部署和遷移。以上涉及到前期規劃、方案設計、項目實施、穩定性保證、變動校驗等全部方面。服務器

挑戰網絡

咱們剛接到機房總體熱遷移需求時,着實有些頭疼,首爾機房屬於較早期部署的機房之一,相關的技術架構比較老舊。而核心數據庫、核心配置服務(zookeeper)、核心數據庫中間層(udatabase)等幾個服務都是比較重要的基礎組件,老舊架構可能會由於基礎層面的變更發生複雜的大範圍異常,從而影響到存量用戶的平常使用。架構

幸虧SRE團隊在過去一年裏,針對各類服務的資源數據進行了全面的梳理,咱們開發了一套集羣資源管理系統(Mafia-RMS) ,該系統經過動態服務發現、靜態註冊等多種手段,對存量和增量的服務資源進行了整理,每個機房有哪些服務、集羣,某個集羣有哪些服務器,每個實例的端口、狀態、配置等信息,都記錄到了咱們的資源管理系統中,以下圖所示:負載均衡

圖1: UCloud SRE資源管理系統-集羣管理功能框架

經過SRE資源管理系統,能夠清楚地知道首爾機房存量內部服務的集羣信息、每一個實例的狀態。咱們基於SRE資源系統還構建了基於Prometheus的SRE監控體系,經過上圖右側Monitor按鈕就能夠跳轉到監控頁面,獲取整個業務的實時運行情況。運維

有了這些資源數據以後,剩下的就是考慮怎麼進行這些服務的擴容和遷移工做。

ZooKeeper服務的擴縮容

首先是內部服務註冊中心zookeeper的擴縮容。

UCloud內部大規模使用zookeeper做爲內部服務註冊和服務發現中心,大部分服務的互訪都是經過使用zookeeper獲取服務註冊地址,UCloud內部使用較多的wiwo框架(C++) 和 uframework (Golang) 都是基於主動狀態機定時將本身的Endpoint信息註冊到zookeeper中,相同Endpoint前綴的服務屬於同一個集羣,所以對於某些服務的擴容,新節點使用相同的Endpoint前綴便可。wiwo和uframework兩個框架的客戶端具有了解析zookeeper配置的能力,能夠經過對Endpoint的解析獲取到真實的IP和端口信息。而後經過客戶端負載均衡的方式,將請求發送到真實的業務服務實例上去,從而完成服務間的相互調用。以下圖所示:

圖2:UCloud 首爾機房部署調用及服務註冊/發現路徑圖

首爾老機房的zookeeper集羣是一個具備3個節點的普通集羣(當時規模相對較小,3個節點足夠)。 然而首爾新機房的規模要大不少,所以新機房zookeeper的集羣規模也要擴充,通過咱們的評估,將新機房的zookeeper集羣擴充到5個節點,基本上能夠知足所需。

其實,一個理想的遷移架構應該是如圖3所示,整個新機房使用和老機房相同的技術架構(架構和版本統一),新架構徹底獨立部署,與老機房並無數據交互工做,而用戶的業務服務(如UHost/UDB/EIP/VPC等)經過某種方式平滑的實現控制和管理面的遷移,以及物理位置的遷移工做。

圖3:理想狀態下的老舊機房服務遷移示意圖

可是理想狀態在現實中沒法達到,內部架構和代碼邏輯的限制,致使業務實例沒法平滑實現邏輯和控制層面的遷移,更況且物理層面的遷移。新部署的管理服務須要和老機房的管理服務進行通訊,所以,咱們調整了新機房服務的部署架構,並適配實際狀況分別使用兩種部署模式,如圖4和圖5所示:

圖4: 同集羣擴容模式的跨機房服務部署

圖5: 新建集羣灰度遷移模式的跨機房服務部署

不管是圖4的同集羣擴容模式,仍是圖5的新建集羣灰度遷移模式,在zookeeper層面必須讓新舊機房的zookeeper集羣處於一體的狀態,須要兩個集羣的數據一致、實時同步。所以在zookeeper的技術層面,必須將這兩個集羣變成一個集羣,將原有的3節點的zookeeper集羣,通過異地機房擴容的方式擴充到8個節點(1個leader,7個follower),只有這種模式下數據纔可以保持一致性和實時性。

而對於新機房新部署的須要註冊的服務來講,他們的配置文件中對於zookeeper地址的配置,卻不是新建的8個ip的列表,而是隻配置新機房5個IP的列表。這樣新老機房的後端服務使用同一套zookeeper,可是配置的倒是不一樣的IP,這樣作的目的,是爲了後續老機房下線裁撤時,全部新機房的服務不須要由於zookeeper集羣的縮容而重啓更新配置,只要將集羣中老機房所在的3個節點下線,剩餘5個節點的配置更新從新選主便可。

所以在zookeeper的機房擴容方案上,咱們採用了先同集羣擴容後拆分的模式。zookeeper的擴容是整個機房擴建的第一步,後續全部的服務都會依託於該操做新建的5個節點的zookeeper配置;而zookeeper集羣的縮容是最後的操做,待全部的服務都擴容完成,全部業務實例遷移完成以後,將zookeeper集羣進行縮容從新選主,這樣便可完成整個機房的裁撤。

數據庫中間層udatabase的遷移

接下來是數據庫中間層udatabase的遷移工做。

圖4和圖5兩種模式對於zookeeper的處理方式是相同的,不一樣點在於後端對於內部管理和控制面服務的擴容遷移方式。udatabase遷移使用圖4模式,這種模式下至關於在原有的集羣進行異地機房擴容,擴容的新實例使用和原有集羣相同的Endpoint前綴,也就是說它們是屬於同一個集羣,當服務啓動後,新擴容的實例的狀態會與原有集羣的實例相同,框架(wiwo或uframework)層會經過客戶端方式從zookeeper中發現到該集羣節點的變化(新增),同時使用某種負載均衡算法將請求流量路由到新的節點上。這樣屬於同一個集羣,但卻處於兩個地址位置的實例都有部分流量,而進行縮容的方式就是直接將老機房同集羣的服務下線便可,這樣客戶端就會將全部該集羣的流量都轉發到新機房擴容的節點上,從而完成平滑的服務擴容。udatabase經過這樣的方式完成了集羣的遷移過程。

新建集羣灰度遷移模式

其實圖4模式對於大部分服務來講都是可行的,但爲何還出現了圖5所示的新建集羣灰度遷移模式呢?由於某些場景下圖4會有必定的不可控性。假如新建的實例(如圖4中Service A Instance 2)存在軟件穩定性和可靠性的問題,好比配置異常、軟件版本異常、網絡異常,可能致使路由到新節點的請求出現問題,會直接影響在線業務,影響的規模由擴容的節點佔集羣總節點的比例決定,像咱們這種1:1的擴容方式,若是服務有問題可能50%的請求就直接異常了。udatabase使用圖4方案,是由於其代碼的穩定性比較高,功能和配置比較簡單,主要依託於其高性能的轉發能力。

而對於某些功能邏輯都比較複雜的業務來講(如ULB/CNAT),就使用了更穩妥的圖5模式,因爲業務層面支持跨集羣遷移,所以能夠新建一個全新的無業務流量的集羣,該集羣在zookeeper中的Endpoint路徑前綴和原有的集羣不相同,使用一個全新的路徑,而後在業務層面,經過遷移平臺或工具,將後端服務或實例按需遷移,整個過程可控,出現問題馬上回滾,是最安全的遷移方案。咱們通用的灰度遷移平臺SRE-Migrate如圖6所示。

圖6:UCloud內部通用業務遷移系統SRE-Migrate

機房部署平臺SRE-Asteroid

UCloud產品線和產品名下服務數量繁多,不管是圖4仍是圖5的方案,都須要大量的服務部署工做。SRE團隊在2018年中推動的機房部署優化項目,意在解決UCloud新機房建設(國內及海外數據中心、專有云、私有云等)交付時間長和人力成本巨大的問題,2018年末該項目成功產品化落地,覆蓋主機、網絡等核心業務近百餘服務的部署管理,解決了配置管理、部署規範、軟件版本等一系列問題。首爾機房遷移也正是利用了這一成果,纔可以在很短的時間內完成近百個新集羣的部署或擴容工做,圖7所示就是咱們的新機房部署平臺 SRE-Asteroid。

圖7:UCloud內部機房部署平臺SRE-Asteroid

核心數據庫的部署和遷移

最後,是核心數據庫層面的部署和遷移工做如何進行。UCloud內部服務所使用的數據庫服務爲MySQL, 內部MySQL集羣採用物理機/虛擬機在管理網絡內自行建設,以一個主庫、一個高可用從庫、兩個只讀從庫和一個備份庫的方式部署,使用MHA+VIP的方式解決主庫的高可用問題,使用BGP/ECMP+VIP的方式解決從庫的負載均衡和高可用問題,大致的架構如圖8所示:

圖8:UCloud內部MySQL服務架構圖

首爾新老機房使用的內部MySQL數據庫集羣的架構跟上圖相似,爲了進行新老機房的集羣切換,咱們設計了以下的方案,如圖9所示:

圖9:首爾集羣內部數據庫集羣遷移示意圖

總體來講,爲了保證核心數據庫集羣可以穩定完成遷移工做,咱們拋棄了雙主庫、雙寫的切換方案,防止由於網絡或其餘因素致使新老集羣的數據不一致、同步異常等問題。咱們採用了最簡單的解決方案,在業務低峯期中止console服務,直接修改數據庫中間層配置切換的方案。

在部署階段,咱們在首爾新機房部署了相同高可用架構的MySQL集羣,老機房的數據庫邏輯備份導入,將新老機房的集羣作成級聯模式(圖9中綠色虛線),新機房的主庫做爲老機房的從庫,經過MySQL異步同步的方式(binlog)進行數據同步。咱們使用pt-table-checksum工具,按期對兩個集羣的數據一致性進行校驗,以保證新老機房的數據徹底一致。與此同時使用內部開發的拓撲分析工具,將全部調用老集羣數據庫主從庫的業務狀況確認清楚(主要是哪些udatabase集羣)。

部署完成後,數據一致性和實時性經過級聯獲得保障,udatabase仍然訪問老機房的MySQL主庫的VIP(圖9藍色虛線),此時並無業務經過直連的方式寫入新機房的主庫(爲保證數據的一致性,新機房的主庫暫時設置成只讀模式)。

在肯定遷移時間和遷移方案以後,在某個業務低峯期的時間點,公告用戶後,首爾機房整個console的操做中止一段時間(期間首爾機房的API請求可能會失敗),在肯定流量很低的前提下,經過修改數據庫中間層(udatabase cluster)中數據庫主從庫VIP的配置,將業務從老機房MySQL集羣切換到新機房MySQL集羣,此時該業務全部的請求都會流入到新集羣(圖9紅色虛線)。爲了防止老集羣仍然有業務寫入或讀取,咱們將老集羣主庫設置爲只讀,而後繼續經過tcpdump抓包分析老集羣上可能存在的請求並手動處理,最終保證全部業務都使用新的MySQL集羣。

因爲須要對主機、網絡、存儲和監控等幾個業務都進行集羣切換,爲保證不互相影響,使用逐個集羣處理的方式,總體切換加檢測的時間耗時近1個小時。

在整個機房切換的過程當中,只有數據庫集羣是有狀態的業務,所以重要性和危險性也比較高,該服務切換完成後,最重要的一個環節也宣告完成,剩下的業務層面(UHost/UDB/EIP等)的遷移工做由各個業務團隊自行完成便可。

收尾

最終全部業務實例完成遷移後,理論上就能夠完成本次機房遷移工做了,不過仍是要對老機房仍然運行的實例進行流量監測,確認沒有流量後進行下線,中止服務。最後對老機房的zookeeper集羣(老機房的3個zookeeper節點)進行請求監測和鏈接監測,確認沒有本機房以及新機房發來的請求(排除zookeeper集羣自主同步的狀況),在完成確認後,進行最後的zookeeper集羣變動,將整個集羣(8個節點)拆分紅老機房(3個節點)和新機房(5個節點),老機房的集羣直接中止服務,而新機房的新的zookeeper集羣完成新的選主操做,確認同步正常和服務正常。

寫在最後

經歷了上文所述的一切操做後,整個首爾機房的遷移工做就完成了,整個項目歷經5個月,其中大部分時間用於業務實例的遷移過程,主要是針對不一樣的用戶要肯定不一樣的遷移策略和遷移時間;內部管理服務的遷移和部署所花費的時間仍是比較少的。UCloud內部針對本次遷移的每個步驟都制定了詳細的方案規劃,包括服務依賴分析、操做步驟、驗證方式、切換風險、回滾方案等,爲了完成如此巨大的新機房熱遷移工做,團隊投入了充足的人力和時間。首爾新機房具備更好的建設規劃、硬件配置和軟件架構,可以爲用戶提供更好的服務,咱們相信這一切都是頗有價值的。

相關文章
相關標籤/搜索