近年來,Linux 操作系統(tǒng)在技術、社區(qū)和商業(yè)化方案均取得了快速發(fā)展,移動云先后發(fā)布了新一代天元操作系統(tǒng)和易行遷移工具,保障了移動云全場景業(yè)務高效遷移。在移動云 CentOS 遷移實踐過程中,跨操作系統(tǒng)虛機遷移是改造中的一個重要環(huán)節(jié),現(xiàn)網(wǎng)環(huán)境錯綜復雜,如何保證客戶業(yè)務在虛機遷移過程不中斷,確保遷移后的虛機在 Linux 操作系統(tǒng)上平穩(wěn)運行,在底層虛擬化側面臨諸多技術挑戰(zhàn)。
關鍵挑戰(zhàn)
虛擬化組件同源異構
新的虛擬化組件需要在多款 Linux 操作系統(tǒng)上穩(wěn)定運行,在不同操作系統(tǒng)和 CPU 架構上共用同一份源碼,因此首先需要解決同源異構難題。
OS 兼容適配
計算、存儲、SDN 等核心業(yè)務需要在 OS 之上相互兼容,在新的平臺上需要在中間層即虛擬化層解決一些業(yè)務兼容適配問題。
跨 OS 不停服熱遷移
跨操作系統(tǒng)、跨虛擬化組件大版本的遷移,可能因虛機 cpu 能力、內存布局、設備結構體等差異,導致遷移失敗影響業(yè)務連續(xù)性,這是虛機跨操作系統(tǒng)遷移過程中的一大難題。
虛擬化組件同源異構
同源異構可以屏蔽不同系統(tǒng)、不同架構的差異,收縮現(xiàn)網(wǎng)版本,減小代碼維護的壓力。實現(xiàn)“一份代碼,一次編譯,處處運行”。
在同源異構改造過程中我們解決了諸多問題,如:不同系統(tǒng)、不同架構其編譯安裝依賴包會有差異,需要在 spec 文件中根據(jù)不同系統(tǒng)、架構指定相應的依賴。新舊虛擬化組件軟件包安裝時存在沖突,需利用 rpm 的 Obsoletes 機制刪除對應安裝包,實現(xiàn)組件的平滑升級。另外由于新舊虛擬化組件差異大,導致舊版補丁回合后函數(shù)調用失敗,需要根據(jù)代碼差異重新設計實現(xiàn)部分功能。
OS 兼容適配
為了保證虛機能在 OS 上平穩(wěn)運行,需要解決一些計算、存儲、SDN 同虛擬化組件在平臺上適配存在的問題,并做一些優(yōu)化。
Python2 版本的兼容
隨著 Python2 的生命周期結束,libvirt-python 自 6.0.0 就停止了對 Python2 的支持,但由于部分產品改造周期長,需要暫時維持使用 Python2 環(huán)境作為過渡,虛擬化作為底層組件,需要構建一個基于 Python2 的 libvirt-python 組件包。 我們從 Python3 和 Python2 間語法差異、接口改變、模塊變化等方面入手,對適配 OS 上的 libvirt-python 代碼做了修改,包括:
針對數(shù)據(jù)類型、類的定義等語法差異上做了對應修改。
針對異常捕獲、輸入輸出、迭代器等 API 使用差異部分做了對應修改。
針對 Python3 和 Python2 間名稱變化或廢棄的模塊做了對應修改。
在修改了 50 多個文件,上千行代碼后,最終得到了一個基于 Python2 的穩(wěn)定可靠的 libvirt-python。
OVS-dpdk 與 QEMU 的適配
SDN 的穩(wěn)定性和可靠性直接影響到用戶虛機的網(wǎng)絡服務質量,為了保證 SDN 能在新平臺上平穩(wěn)運行,我們積極推動各 SDN 廠商在 OS 上的適配工作,解決了多個適配問題。
SDN 適配時發(fā)現(xiàn)當 QEMU 作為 server 時,重啟 ovs,虛機可能會 crash。查看 QEMU 的 coredump 文件,定位到如下代碼觸發(fā)了 crash。
當 QEMU 作為 server 端時,一旦 ovs 重啟,按照上面代碼邏輯 QEMU 會主動嘗試進行 reconnect,過程中會改變網(wǎng)卡設備 tcp 狀態(tài)字為 TCP_CHARDEV_STATE_DISCONNECTED,此時會造成處理邏輯 bug,使得 QEMU 發(fā)生 crash(實際上 QEMU 作為 server 端時,不應進行 reconnect 操作,而是由作為 client 端的 ovs 進行 reconnect)。具體觸發(fā) crash 的流程如下:
解決方案是只有當 QEMU 作為 client,重啟 ovs,QEMU 才做 reconnect,問題得到修復。 除上述問題外,我們還解決了一些其他問題,包括 ovs 熱升級后 windows 虛機網(wǎng)絡不通、海光平臺執(zhí)行 testpmd 測試程序虛機卡住等多個問題。
卷遷移操作的效率優(yōu)化
分布式存儲為云平臺提供基礎存儲服務,在使用中往往伴隨著一些卷遷移和容量查詢的操作,但這些操作實際執(zhí)行效率并不高,需要做一些優(yōu)化。
在 QEMU 原生版本實現(xiàn) Ceph 卷遷移功能時,遷移前將 bitmap 每位都置臟,首輪遷移時會將源盤所有數(shù)據(jù)遷往目的盤(未寫入數(shù)據(jù)的部分以 0 寫入),導致遷移數(shù)據(jù)量增多,時間變長。 我們對 ceph 卷遷移做了優(yōu)化,減少了首輪遷移的數(shù)據(jù)量,效率得到大幅提升(尤其是源盤空間較大數(shù)據(jù)量較少時),具體步驟:
修改 QEMU 組件的 rbd 驅動,增加獲取后端集群 Ceph 卷已使用空間分布的接口。
遷移開始時,利用接口初始化卷遷移的 dirty bitmap。
遷移過程中,如果虛機新增 IO,將對應 dirty bitmap 置臟。不斷迭代清理 dirty bitmap,只對有數(shù)據(jù)的存儲塊進行遷移拷貝,無數(shù)據(jù)的塊直接跳過。
當 dirty bitmap 全部清理時卷熱遷移完成。
此外還有一些其他優(yōu)化:
優(yōu)化 ceph 卷容量查詢,調用新的接口,其查詢效率提升 30%+。
QEMU 支持 ceph 卷 snapshot 遷移功能,遷移后依然保有源卷的快照信息。
跨 OS 不停服熱遷移
解決了同其他核心產品適配的各種問題后,我們工作重點轉向了跨 OS 的遷移適配上來。我們與 openEuler 社區(qū)的 Virt SIG 成員進行了深度協(xié)同聯(lián)創(chuàng),解決了跨 OS 遷移需要考慮 Guest 的 CPU 能力、設備狀態(tài)等多個方面的問題。
目的端主板類型不兼容遷移失敗
從 BC-Linux7 系列系統(tǒng)往 BC-Linux For Euler 系列系統(tǒng)遷移時會有“unsupported machine type”的報錯,對比兩個操作系統(tǒng) QEMU 組件支持的 machine type,發(fā)現(xiàn) BC-Linux7 的虛擬化組件裁剪了 QEMU 社區(qū)原生的 Machine Type,完全自定義了私有的主板類型,無法正常熱遷移到 openEuler 上。
由于 machine type 在遷移時不能被改變,要想遷移成功,就必須在 BC-Linux For Euler 系統(tǒng)上的高版本 QEMU 兼容低版本的 machine type。為此,我們梳理低版本 QEMU 中每種 machine type 支持的設備,并在高版本 QEMU 上移植相應的 machine type,這樣遷移時便不會出現(xiàn)主板類型不支持的問題。
設備結構體差異引起遷移失敗
QEMU 使用 VMStateDescription(VMSD)數(shù)據(jù)結構來對設備狀態(tài)進行描述和管理,遷移時 VMSD 的 fields 和 subsections 會被發(fā)送到目的端。 要想虛機遷移成功,如果源端設備結構體字段多于目的端,則目的端 vmstate_load_state 加載設備狀態(tài)時,需要將多出來的字段 disable 掉,反之則需將缺少的字段跳過加載。
測試時我們發(fā)下虛機從 BC-Linux For Euler 系列系統(tǒng)往 BC-Linux7 系列系統(tǒng)回遷時,對端無法成功接收鍵盤的設備狀態(tài)。對比鍵盤的 VMSD,高版 QEMU 增加了 kbd_extended_state 字段的發(fā)送,目的端因缺失該字段導致遷移失敗。
kbd_extended_state_needed 是判斷是否將 kbd_extended_state 字段發(fā)送的函數(shù)(默認 True)。為了保證虛機不會因為 kbd_extended_state 而導致回遷失敗,回遷時須將多出的 kbd_extended_state 字段不發(fā)送。
此外我們還比較了其他設備,尤其是 virtio 和 vhost_user 設備的 VMSD 在高低 QEMU 版本間的差異,對有差異的地方做了修改。
cpu feature 不兼容熱遷移失敗
虛機 CPU 有 3 種模式:custom(指令集最少但熱遷移兼容性最好)、host-passthrough(指令集最多但熱遷移兼容性最差)和 host-model(介于兩者之間),但虛機 cpu features 不僅和虛擬化配置有關,還與宿主機的 CPU 型號、操作系統(tǒng)內核等有關。即使是在 custom 或 host-model 模式下,我們也遇到一些因目的端缺失 cpu features 而導致的遷移失敗的問題。
case1:目的端缺失 arch-facilities 特性
由于高版本 libvirt 將同一 cpu feature 名稱由 arch-facilities 變?yōu)榱?arch-capabilities,目的端不識別 arch-facilities,導致熱遷移失敗。需要在源端的 cpu_map.xml 中將其修改為 arch-capabilities 才能通過 cpu feature 兼容性檢查。
case2:目的端缺失 spec_ctrl 特性
BC-Linux7 系列系統(tǒng)上使用的 3.10 內核需要使能 spec_ctrl 來避免“幽靈漏洞”,但 BC-Linux For Euler 系列系統(tǒng)使用的 4.19 內核通過其他方式避免了該漏洞,關閉了 spec_ctrl,需要更新微碼才能在目的端使能 spec_ctrl 特性。
case3:目的端缺失 hle/rtm 特性
配置 host-model 的模式虛機因目的端缺失 hle/rtm 特性導致熱遷移失敗。需要在目的節(jié)點的內核的啟動參數(shù)增加“tsx=on”來使能相關指令集。
總結
我們做了虛擬化組件的同源異構、對 OS 兼容適配,并與 openEuler 社區(qū)進行深度聯(lián)創(chuàng),實現(xiàn)跨 OS 不停服熱遷移優(yōu)化,從原理和實踐兩個方面,保障了 CentOS 的遷移改造任務得以高效進行。 然而移動云現(xiàn)網(wǎng)有海量的節(jié)點需要做遷移,這對遷移的效率與成功率有了更高的要求,在下期的分享中,我們將帶來對熱遷移性能提升優(yōu)化做的技術分享,敬請期待! ?
評論