幫你降低成本的不停機實時遷移,技術上到底是怎么做到的?
云計算幫助用戶降低成本的方法有很多,不過有一點可能被很多人忽略了,那就是不停機實時遷移(Live Migration)。
延伸閱讀,點擊鏈接了解Akamai Cloud Computing
實時遷移如何幫助我們降低成本?那花樣可就多了:
- 資源動態調整:借助實時遷移功能,在不中斷服務的情況下將工作負載從一個實例遷移到另一個實例,從而根據需求動態調整資源。例如,在低峰期間,可以將工作負載從高性能實例遷移到低成本實例,以節省成本;在高峰期間則可以遷移回高性能實例以應對需求。
- 故障恢復和容災:實時遷移功能可以幫我們快速將工作負載遷移到備用實例,以應對主機故障或區域性故障。通過實時遷移,可以確保服務的持續可用性,減少停機時間和業務影響,同時降低成本,因為備用實例通常會配置為低成本的冷備份。
- 定期維護:云服務提供商會定期進行基礎設施維護和更新,這可能會導致一些短暫的服務中斷。通過實時遷移功能,我們可以在維護期間將工作負載遷移到其他實例,以確保服務的連續性,并避免因維護活動而導致的潛在損失。
- 按需資源使用:實時遷移功能使我們能更靈活地管理資源使用情況,根據需要隨時調整實例規格和數量。根據實際需求動態調整資源,可以避免過度配置實例,從而降低不必要的成本。
總的來說,通過云實例的實時遷移功能,用戶可以更靈活地管理和優化資源使用,根據需求動態調整實例配置,從而降低成本并提高服務的可用性和性能。
那么正在使用Linode云服務的你,是否考慮過:這種聽起來很方便的實時遷移功能,從底層的技術上來看,到底是怎么實現的?本文我們將深入了解這項技術背后的細節。
實時遷移的工作原理
在開發這項功能時,我們的第一步是調查QEMU如何處理實時遷移。QEMU是Linode使用的一種虛擬化技術,而實時遷移也是QEUM的一項功能。因此我們的重點是將這項技術引入Linode,而非重新發明一個類似的技術。
那么實時遷移技術到底是如何以QEMU的方式實現的?整個過程分為以下四步:
1.啟動目標QEUM實例,該實例的各項參數與需要遷移的源QEUM實例完全相同。
2.對磁盤進行實時遷移。數據傳輸過程中,對磁盤內容進行的任何更改也會提交至目標磁盤。
3.對內存數據進行實時遷移。遷移過程中,內存內容的任何變化也會提交至目標內存。如果這一過程中磁盤內容也出現了變化,相關變化同樣會被提交至目標QEUM實例的磁盤中
4.執行割接點。當QEMU確認有足夠多的內存頁可以放心進行割接后,源和目標QEMU實例將會暫停。QEMU會復制最后幾頁內存數據和機器狀態,機器狀態包括CPU緩存和下一條CPU指令。隨后,QEMU會讓目標開始運行,這樣目標實例就可以從源實例停止時的狀態恢復運行了。
這些步驟概括介紹了QEMU實時遷移的執行過程。然而依然需要通過包含很多手工操作的方式來精確指定目標QEMU實例的啟動方式。此外,上述過程中的每個操作都必須在正確的時間執行。
Linode實現實時遷移的方式
在分析過QEMU已經實現的技術后,我們該考慮具體用怎樣的方式將其實施到Linode平臺上。
在實時遷移工作流程的第1步,需要啟動目標QEMU實例以接受傳入的實施遷移連接。在實現這一步時,我們最初的想法是拿到當前Linode實例的配置文件,隨后將其應用到目標計算機。理論上這應該很簡單,但進一步思考就會發現,實際情況要復雜很多。尤其是,配置文件雖然可以告訴我們Linode實例是如何啟動的,但并不一定可以完整描述啟動后的Linode實例的完整狀態。例如,用戶可以在Linode實例啟動完畢后通過熱插拔的方式連接塊存儲設沒備,但這種情況并不會記錄到配置文件中。
為了在目標主機上創建QEMU實例,必須對當前運行的QEMU實例進行剖析。我們通過檢查QMP接口的方式對運行中的QEMU實例進行剖析,該接口為我們提供了與QEMU實例布局情況有關的豐富信息,但它無法幫助我們從來賓系統的視角了解實例內部正在發生的事情。例如,對于本地SSD和塊存儲,它只能告訴我們磁盤鏈接到哪里,以及虛擬磁盤連接到哪個虛擬化PCI插槽上。在查詢QMP以及檢查并分析了QEMU接口后,可以構建一個Profile來描述如何在目標位置創建一個完全相同的實例。
在目標計算機上,我們將收到完整的描述信息,借此了解源實例到底是什么樣,隨后就可以在目標位置忠實重建這個實例,但此時還有一個差異。這個差別主要在于,目標QEMU實例在啟動時使用了一個選項,該選項可以讓QEMU接受傳入的遷移。
至此,實時遷移的記錄過程已經基本結束,接下來需要看看QEMU是如何實現這些操作的。QEMU進程樹由一個控制進程和多個工作進程組成,其中一個工作進程負責返回QMP調用或處理實時遷移等任務,其他進程需要一對一映射至來賓CPU。來賓環境與QEMU端的功能相互隔離,具體行為類似于獨立的系統。
從這個意義來看,我們需要處理三層內容:
第1層是管理層;
第2層是QEMU進程的一部分,負責處理所有操作;
第3層是實際的來賓層,負責與Linode用戶進行交互。
目標實例啟動并準備好接受傳入的遷移后,目標硬件會告知原硬件開始發送數據。源端會在收到這個信號后開始進行處理,并會在軟件中告知QEMU開始傳輸磁盤內容。軟件會自主監控磁盤傳輸進度,借此檢查傳輸操作是否完成,并會在磁盤傳輸完成后自動開始遷移內存內容。此時軟件依然會自主監控內存遷移進度,并在內存遷移完畢后自動切換至割接模式。上述全過程都是通過Linode的40Gbps網絡進行的,因此網絡方面的操作都可以快速完成。
割接:關鍵環節
割接操作是實時遷移過程中最重要的一環,只有理解了它,才能完全理解實時遷移操作。
在割接點狀態下,QEMU已經確認做好了所有準備,可以進行割接并在目標計算機上運行。源QEMU實例會讓兩端暫停運行,這意味著:
1. 來賓系統被"時停"。如果來賓系統正在運行時間同步服務(如NTP)NTP會在遷移完成后自動重新同步時間。這是因為系統時鐘會產生幾秒鐘的落后。
2. 網絡請求停止。如果網絡請求是TCP請求(如SSH或HTTP),基本上不會產生可感知的連接中斷; 如果網絡請求是UDP請求(如流媒體視頻),可能會導致少量丟幀。
由于時間和網絡請求均已停止,我們希望割接能盡量快速完成。然而為保證成功割接,還需要進行一些檢查:
- 確保實時遷移順利完成不出錯。如果出錯則要進行回滾,解除源Linode實例的暫停狀態,不再進一步執行其他操作。開發過程中,我們在這方面進行了大量實驗并解決了很多錯誤,雖然這為我們造成了很多頭疼的問題,但最終都順利解決了。
- 確保關閉源實例的網絡,并在目標實例上正確連接。
- 讓我們的其余基礎設施清楚得知遷移后的Linode實例是通過哪臺物理計算機運行的。
由于割接過程時間有限,我們希望能盡快完成上述操作。解決了這些問題后,即可繼續進行割接了。源Linode實例會自動收到"割接完成"信號并讓目標實例運行起來。目標Linode實例會從源實例暫停時的狀態恢復運行。源和目標實例上的其余內容則會被清理。如果目標Linode實例在未來某個時間需要再次進行實時遷移,則會重復執行上述步驟。
CPU標記
在向來賓操作系統呈現CPU方面,QEMU有不同的選項。其中一個選項可將主機CPU的型號和功能(即CPU標記)直接傳遞給來賓系統。通過使用該選項,來賓即可不受約束地使用KVM虛擬化系統所支持的全部能力。當Linode首次采用KVM時(當時還沒有實時遷移功能),為了實現最大化性能,我們就使用了該選項。然而在開發實時遷移功能的過程中,該選項為我們造成了很多挑戰。
在實時遷移的測試環境中,源和目標主機是兩臺完全相同的計算機。但在現實世界中,我們的硬件集群并非100%完全相同的,計算機之間的某些配置差異可能能導致產生不同的CPU標記。這很重要,因為當一個程序被載入Linode的操作系統后,Linode會向該程序呈現CPU標記,為了充分利用這些標記,程序可以將軟件中的特定部分載入內存。如果一個Linode實例被實時遷移到不支持該CPU標記的目標計算機,程序將會崩潰。這可能導致來賓操作系統崩潰,甚至導致Linode重啟動。
因此在實現實時遷移時,我們必須設法防止程序因為CPU標記的不匹配而崩潰。可行的選項有兩個:
- 讓QEMU模擬CPU標記。但這可能導致原本快速運行的軟件運行速度變慢,并且完全無法調查原因。
- 收集源計算機的CPU標記列表,確保目標計算機具備完全相同的標記,隨后再進行遷移。這種方式更復雜,但不會影響用戶程序的運行速度。我們最終選擇了這種方式。
在決定對源和目標的CPU標記進行匹配后,我們使用下列兩種方法的組合最終實現了目標:
- 第一種方法更簡單。將源硬件的所有CPU標記發送給目標硬件,當目標硬件設置新的QEMU實例時,會通過檢查來確保自己至少擁有和源Linode實例相同的標記。如果不匹配,將不進行實時遷移。
- 第二種方法更復雜,但可以避免因為CPU標記不匹配導致的遷移失敗。在發起實施遷移前,我們會對具備可兼容CPU標記的硬件創建一個列表,隨后從該列表中選擇硬件來創建目標計算機。
第二種方法必須能快速執行,并且讓我們的工作變得更復雜。某些情況下,我們需要針對超過900臺計算機檢查最多226個CPU標記。為所有這226個CPU標記編寫檢查代碼本就很困難,而這些代碼還需要不斷進行維護。但Linode的創始人Chris Aker提出的一個驚人想法最終解決了這個問題。方法的關鍵在于為所有CPU標記創建一個列表,并將其表示為一個二進制字符串。隨后,可以使用Bitwise and("按位與")運算來對比字符串。
對于實時遷移,CPU標記完整列表會表示為一個二進制字符串,其中每一位都代表一個標記。如果一個位為"0",代表對應的標記不存在; 如果某個位為"1",則代表標記存在。例如,一個位可以代表AES標記,另一個位可以代表MMX標記。這些標記己在二進制字符串中的位置會維護并記錄在案,隨后用于我們數據中心內的所有計算機。
相比維護一組if語句來檢查某個CPU標記是否存在,這種列表的維護工作無疑更簡單也更高效。例如,假設總共需要追蹤并檢查7個CPU標記,這些標記可以存儲在一個8位數字中(多出的一位供未來進行擴展)。例如這樣的字符串可能類似于00111011,最右側的一位代表AES已啟用,右數第二位代表MMX已啟用,右數第三位代表其他標記已啟用,以此類推。
實時遷移操作會在源和目標計算機上針對CPU標記字符串執行"按位與"操作。如果兩個計算機的CPU標記字符串運算結果相等,意味著目標計算機是兼容的。我們的內部工具可以使用上述算法得到的結果為可兼容的硬件構建一個列表。該列表會展示給我們的客戶支持和硬件運維團隊,這些團隊可以使用我們的內部工具來編排不同的運維任務。
緊跟技術變化的步伐
隨著時間推移,Linode會增加新的功能,我們也許要繼續努力保證實時遷移可以兼容這些功能。引入某些新功能時,可能無需圍繞實時遷移執行新的開發工作,但我們可能依然需要測試該功能是否可以按照預期正常工作。對于某些功能,則可能需要在開發的早期階段,針對實時遷移進行必要的兼容性測試和相關工作。
和其他幾乎所有軟件類似,對于同一件事,通過不斷研究,總能發現更好的實現方法。例如,從長遠來看,為實時遷移功能開發更多模塊化的集成方法,無疑可以降低維護負擔。或者我們甚至可能將實時遷移的相關功能納入到底層代碼中,從而使其成為Linode一項拆箱即用的功能。
歡迎點擊這里注冊Linode免費試用賬戶,并通過強大高效的實時遷移功能,體驗一下靈活性和可擴展性更高的云平臺是如何幫你保障業務連續性、優化資源使用和負載均衡、改善容災和故障恢復能力。同時,也可以借此機會了解Linode云服務怎樣幫你降低云計算使用成本,觸達全球更廣泛的客戶群體。
如您所在的企業也在考慮采購云服務或進行云遷移,
點擊鏈接了解Akamai Linode的解決方案