OpenStack虛擬機狀態
OpenStack創建一個虛擬機,涉及到三種狀態,vm_state,task_state和power_state。
先總結幾點:
- 電源狀態(power_state):是hypervisor的狀態,從計算節點”由下而上“加載。
- 虛擬機狀態(vm_state):反應基於API調用的一種穩定狀態,符合用戶體驗,從上而下的API實現。
- 任務狀態(task_state):代表API調用過程的過渡狀態。
- 只要數據庫可用,就可以強刪虛擬機。(”hard“ delete of VM)
- 電源狀態和虛擬機狀態會彼此沖突,需具體情況具體分析。
Power_state
Power_state是我們調用虛擬機中驅動獲得的一個狀態,事實上hypervisor的狀態才是權威的。數據庫中power_state只是之前狀態的一個快照,
會被周期性更新,並且在有任務改變了power_state後要更新數據庫。
1、怎樣更新?
通常是”自下而上“,由計算節點產生,重寫數據庫。這個更新過程可能引起和vm_state的一致性沖突,如下。
2、power_state命名慣例
取決於ibvirt返回的狀態。
廢棄的狀態:
BLOCKED,本質上應該是RUNNING;
SHUTOFF,現在是SHUTDOWN;
FAILED,現在是NOSTATE。
vm_state
vm_sate描述虛擬機當前穩定狀態,而非過渡狀態。如果沒有running_tasks,虛擬機就應該是用戶期待的狀態,比如active。ACTIVE是一個vm_state,因為它代表虛擬機正常運行;而SUSPENDING是一個過渡狀態,代表n秒後虛擬機將被掛起,所以應該屬於task_state。
1、vm_stae怎樣更新
vm_state僅在任務結束後更新,即當一個任務成功結束並且設置task_state狀態為None。
當有API調用時,vm_state永遠不能改變。如果任務失敗,並且合適的清理後(比如live遷移失敗,任務回滾,虛擬機在源節點正常運行),虛擬機狀態不變。如果任務失敗並且不能回滾,vm_state狀態被置為ERROR。
2、vm_state命名慣例:使用一個形容詞
3、vm_state和power_state關系?
二者不是一一映射,代表的側重點不同,不能通過推理從一個得到另一個,所以都是需要的。
比如,當你去修復一個虛擬機,虛擬機從一個rescue鏡像啟動,此時power_state狀態為RUNNING,但是vm_state狀態只能是RESCUED。單單靠power_state是不能確定vm_state是ACTIVE還是RESCUED。
4、power_state和vm_state狀態不一致,如何修正?
首先,有正在運行的任務時,vm_state和power_state極有可能不同,因為vm_state代表一個穩定狀態,在任務運行期間,狀態是過度狀態,vm_state本來就是過期的。
當沒有任務運行時,power_state和vm_state應該保持一致,除非出錯或者失敗,這種情況,要具體分析。
a、如果power_state=SHUTOFF,但是vm_state=ACTIVE,極有可能是虛擬機內部shotdown命令出錯,所以power_state正確。一個粗暴但等價的方法,手動調用一個內部方法stop()API,虛擬機應該被修正為STOPPED。
b、如果power_state=BLOCKED,vm_state=HARD_DELETED,代表用戶已經要求刪除虛擬機但是過程失敗了。所以嘗試再次刪除。
c、如果power_state=BLOCKED,vm_state=PAUSED,代表可能是pause()方法調用前出了不可預料的問題。此時修正方法就看怎樣對用戶最友好了,maybe設置vm_state為ERROR。
到此,會發現 _sync_power_states (同步電源狀態)不鳥正在執行的任務,可能導致奇怪的錯誤。
5、如何從vm_state中獲得和EC2等價的狀態?
ec2狀態包含穩定狀態和過渡狀態。所以需要同時根據task_state和vm_state來推斷ec2狀態。
vm_state如下:
- INITIALIZED:虛擬機僅僅在數據庫創建(應該是說表結構建好了),但是還沒開始創建。(狀態是BUILDING)
- ACTIVE:虛擬機正在運行,使用特定的鏡像。
- RESCUED:虛擬機正在運行,但使用rescue鏡像。
- PAUSED:虛擬機暫停,使用特定鏡像。依然占用計算和內存資源。
- SUSPENDED:虛擬機掛起,使用的是特定的鏡像,但是不占用計算和內存資源。
- STOPPED:虛擬機停止,但是鏡像依然在磁盤上。
- SOFT_DELETED:虛擬機不再計算節點運行了,但是磁盤鏡像依然保存,可以恢復。
- HARD_DELETED:從配額和計費角度看,虛擬機不存在了。最終虛擬機和磁盤被銷毀。
- RESIZED:虛擬機在源節點停止,在目標節點運行。虛擬機鏡像在源節點和目標節點都有,但是參數不同。用於需要確認resize(調整參數)或者恢復虛擬機。(廢棄的的task_state RESIZE_VERIFY和vm_state RESIZED功能一樣。)
- ERROR:發生了無法恢復的錯誤,唯一的可執行的操作就是刪除虛擬機。
vm_state中廢棄的狀態REBUILDING,MIGRATING,RESIZING都放在了task_state中。而SHUTOFF不用了,因為這個狀態很費解,應該根據shutdown_terminate標記被劃分到STOPPED或者DELETED。
task_state
task_state代表過渡狀態,和一個computeAPI緊密相關,表明虛擬機當前執行哪個任務。處於vm_state的虛擬機是不會有task_state,只有正在運行的進程有task_state。
1、特定任務:force_delete(或者hard delete)
虛擬機什麽時候都能成功刪除。用戶刪除虛擬機可以釋放配額裏更多資源,不再被收費。不幸的是,可能出現這種情況,一個前置任務卡住了所以task_state永遠不能到None,或者虛擬驅動在銷毀虛擬機時卡住了,再或者計算節點因為網絡/硬件的原因不可用而無法執行銷毀虛擬機操作。所以,不應該等到force_delete() 任務獲得計算節點然後更新虛擬機狀態為HARD_DELETED。而應該是說,vm_state立馬更新而不去檢查計算節點。換句話說,force_delete() 任務是一個純粹的數據庫操作。一些善後工作(真正的清除工作)隨後進行,也不需要power_state和vm_state之間的一致性操作,因為它們會被定期觸發。
2、如何更新?
task_state被設置當確認它是虛擬機上唯一執行的任務時。要做到原子更新,任務開始會生成一個獨一無二的task_id(uuid格式)和虛擬機id關聯。如果虛擬機已經有一個VM id,說明已經有別的任務在運行。在任務執行過程中,task_id通過RequestContext數據格式傳播。在任務執行中途如果要更新ask_state,必須確認虛擬機的task_id匹配當前執行任務的id,否則新任務搶占當前任務(目前只有force_delete)。當任務成,task_state置為None,同時task_id置為None。
因為hard delete是唯一一個可以搶占其他任務的任務,我們沒必要立即設置task_id,但是需要檢查vm_state以確認它不是HARD_DELETE而不是去檢查task_id是否匹配。
3、真的要分開vm_state和task_state嗎?
從技術上講,虛擬機狀態(穩定)和任務狀態(過渡)沒有交集,可以組合使用。分開最大的好處就是狀態轉換圖簡單得多——只要考慮vm_state之間的DFA。如果需要增加一個新task_state,狀態轉換圖保持不變。
4、命名變化
最好用動詞+”ing“來描述task_state,且這個動詞是compute API方法。任務執行期間,task_state不變。要表述任務的進展,應該使用一個單獨的領域,而不是簡化狀態機。
- None:沒有正在執行的任務
- BUDILDING
- IMAGE_SNAPSHOTTING
- IMAGE_BACKINGUP
- UPDATING_PASSWORD
- PAUSING
- UNPAUSING
- SUSPENDING
- RESUMING
- DELETING
- STOPPING
- STARTING
- RESCUING
- UNRESCUING
- REBOOTING
- REBUILDING
- POWERING_ON
- POWERING_OFF
- RESIZING
- RESIZE_REVERTING
- RESIZE_CONFIRMING
- SCHEDULING
- BLOCK_DEVICE_MAPPING
- NETWORKING
- SPAWNING
- RESIZE_PREP
- RESIZE_MIGRATING
- RESIZE_MIGRATED
- RESIZE_FINISH
廢棄的狀態:
RESIZE_VERIFY不是一個過渡狀態,而是穩定狀態。變成了vm_state中的新狀態RESIZED。
參考:
https://wiki.openstack.org/wiki/VMState
http://docs.openstack.org/developer/nova/devref/vmstates.html#preconditions-for-commands
OpenStack虛擬機狀態