在雲端運算中,一個關鍵功能是將運行中的虛擬機實例撤離或遷移到同一叢集的其他節點,這樣就可以在不影響服務的情況下進行硬體/軟體升級或維護操作(包括關機)。那些使用 OpenStack + Nova 的用戶可以在各種情況下擁有精細的虛擬機遷移能力,例如當計算節點故障時、當一個或多個實例處於停止狀態時,或者當實例仍然在運行時。詳細的解釋可以參見 Nova 的手冊頁:
- host-evacuate
- host-evacuate-live
- host-server-migrate
- live-migration
- migrate
如標題所示,我們主要關注的是 host-evacuate-live,它會將所有運行中的實例遷移到其他計算節點。這個操作要求較高,所以如果它能成功,其他類似的操作也應該沒有問題。我們來看看一個遷移失敗的範例以及如何修復它。
我們從一個由 3 個控制與計算節點(cc1、cc2 和 cc3)組成的叢集開始,所有的虛擬機實例都處於運行狀態。
圖片來源:Bigstack CubeCOS
我們嘗試將所有在 cc2 上運行的實例遷移到 cc3。
# nova host-evacuate-live cc2
注意,狀態已經從 ACTIVE 變為 MIGRATING。
圖片來源:Bigstack CubeCOS
幾秒鐘過去後,我們收到了好消息,兩個實例成功地遷移到了 cc3。
圖片來源:Bigstack CubeCOS
經過足夠長的等待後,我們發現其中一個實例處於 ERROR 狀態。值得注意的是,大多數情況下所有實例都能成功遷移。
圖片來源:Bigstack CubeCOS
此錯誤可以從 Horizon UI 中確認。
圖片來源:Bigstack CubeCOS
為了診斷問題,我首先檢查了日誌(logs)。在 cc2 節點的 nova-compute.log 中檢查了遷移的相關日誌,並發現了以下內容。
Live migration failed.: libvirt.libvirtError: Timed out during operation: cannot acquire state change lock (held by monitor=remoteDispatchDomainGetobStats)
同樣,檢查了目標節點 cc3 上的 libvirtd 日誌,並發現了類似的錯誤。
cc3 libvirtd[39220]: Timed out during operation: cannot acquire state change lock (held by monitor=remoteDispatchDomainMigratePrepare3Params)
由於 CubeOS 是基於 Linux 的,且底層的虛擬化技術是 KVM hypervisor,進一步調查意味著要檢查 qemu 進程。在 cc2 節點上,確實有一個正在運行的 qemu 進程,與我們的錯誤實例完全吻合。
# ps awx | grep qemu
635175 ? Sl 51:20 /usr/libexec/qemu-kvm -name guest=instance-00000007,debug-threads=on -S
# virsh list
Id Name State
----------------------------------
2 instance-00000007 paused
Paused 狀態並不是預期的狀態,所以我想連接到 qemu 監控器進一步了解。
# virsh qemu-monitor-command --hmp 2 info status
有趣的是,這個命令一直掛起,這也解釋了為什麼日誌顯示操作超時,VNC 控制台也沒有回應。該進程顯示為運行狀態,但由於某些原因處於無反應狀態。一些舊的網絡文章暗示了 qemu 線程之間的競爭條件。通過 gdb/gstack 傾印的堆疊追蹤,結果與其他人觀察到的情況相似。感謝 libvirt 及其搭檔 virsh,虛擬機的配置在 xml 文件中有良好的追蹤。這意味著我們可以安全地終止無響應的進程,並使用相同配置創建一個全新的進程。
# virsh destroy 2
Domain '2' destroyed
# virsh list --all
Id Name State
------------------------------------
- instance-00000007 shut off
確實,舊的 qemu 進程被終止。
# ps awx | grep qemu
3633296 pts/2 S+ 0:00 grep --color=auto qemu
# virsh start instance-00000007
Domain 'instance-00000007' started
# virsh list
Id Name State
-----------------------------------
4 instance-00000007 running
# virsh qemu-monitor-command --hmp 4 info status
VM status: running
# virsh console 4
Connected to domain 'instance-00000007'
Escape character is ^] (Ctrl + ])
login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
cirros-hotstorage-1a0e login: cirros
cirros
Password:
$ hostname
hostname
cirros-hotstorage-1a0e
$ uptime
uptime
19:25:08 up 12:03, 1 users, load average: 0.00, 0.00, 0.00
$
這幾乎是結束了,除了有一步是通知 OpenStack 實例的狀態其實是健康的。
# openstack server set --state active 198e7b81-8267-44dc-a061-0cf63a970e57
圖片來源:Bigstack CubeCOS
一切又回到了正常狀態,但我還需要再執行一次撤離命令,將復原過的實例(仍然在 cc2 上)遷移到 cc3。
# nova host-evacuate-live cc2
我們也可以連接到更友善的 UI 控制台,與新遷移的虛擬機進行互動。
圖片來源:Bigstack CubeCOS
經過所有這些操作後,cc2 節點變得空曠(沒有虛擬機實例),並準備進行維護操作。