機、原理與實戰(zhàn))
做OpenStack運維的人遲早會跟Nova的幾十條命令打交道??刂乒?jié)點掛了可以重建網(wǎng)絡節(jié)點掛了可以恢復但計算節(jié)點上的每一臺實例出了問題以后能不能救、怎么救全靠Nova這一層的操作是否熟練。我剛上手OpenStack那會兒最頭疼的就是實例狀態(tài)和操作命令對不上號——明明想暫停卻執(zhí)行了掛起明明只是關(guān)機卻把實例數(shù)據(jù)弄丟了。后來把Nova的常見操作按“狀態(tài)-動作”畫成一張圖之后整個思路才清晰起來。這篇文章就把我整理過的Nova 16種核心操作完整拆一遍順便把每個操作背后的原理、適用場景和踩過的坑都交代清楚。無論你是剛接觸OpenStack的運維新人還是已經(jīng)扛著幾十臺計算節(jié)點的老兵這份清單都能幫你少走彎路。1. 先看全景Nova實例狀態(tài)機與16種操作的關(guān)系圖1.1 Nova實例的狀態(tài)先認識這幾個關(guān)鍵節(jié)點很多人用Nova的時候習慣直接敲命令根本不看實例當前處于什么狀態(tài)。這就是問題所在。Nova的每個操作幾乎都是“狀態(tài)依賴”的實例處于ACTIVE時你能做的大部分操作到了ERROR狀態(tài)就全被拒絕。想要真正理解這張操作圖必須先認識幾個核心狀態(tài)。BUILD實例正在創(chuàng)建調(diào)度器剛把它交給某個計算節(jié)點libvirt正在準備磁盤、網(wǎng)絡和CPU資源幾秒到幾十秒內(nèi)會轉(zhuǎn)到ACTIVE或ERROR。ACTIVE正常運行g(shù)uest OS已經(jīng)跑起來對外提供服務。這是實例一生中停留最久的狀態(tài)。SHUTOFF實例被關(guān)機stop或者剛從開機狀態(tài)關(guān)機。注意SHUTOFF不代表實例被刪除它的磁盤文件、內(nèi)存配置都還在計算節(jié)點上。PAUSED暫停虛機的CPU被凍結(jié)但內(nèi)存還在物理內(nèi)存里。這種狀態(tài)很少見一般只在排障或臨時騰資源時用。SUSPENDED掛起內(nèi)存已經(jīng)被寫到宿主機本地磁盤虛機完全凍結(jié)CPU和內(nèi)存資源全部釋放。SHELVED“擱置”虛機關(guān)機后把系統(tǒng)盤快照上傳到Glance計算節(jié)點上的本地文件會被清理實例幾乎不占用計算資源。RESCUED救援模式原來的系統(tǒng)盤被掛成數(shù)據(jù)盤虛機改用救援鏡像啟動。ERROR出錯了??赡苁钦{(diào)度失敗、鏡像拉取失敗、磁盤空間不足、網(wǎng)絡創(chuàng)建失敗等等一句話需要人工介入。VERIFY_RESIZE變配后的等待確認狀態(tài)需要執(zhí)行confirm或revert確認變更。MIGRATING遷移進行中虛機還在源節(jié)點或目標節(jié)點上運行但調(diào)度和復制流程已經(jīng)啟動。查看實例狀態(tài)最直接的方式就是openstack server show server_id里面會顯示OS-EXT-STS:vm_state和OS-EXT-STS:task_state兩個字段。vm_state是穩(wěn)定狀態(tài)task_state是當前正在執(zhí)行的操作這兩個字段配合status字段一起看才能判斷實例當前到底在干嘛。1.2 16種操作與狀態(tài)轉(zhuǎn)換對應總表我把最常見的Nova操作按照“操作目的”歸成16類每一類都對應一條或一組命令。下面的表格可以當作日常速查卡來用也是整篇文章的“地圖”。操作分類典型命令狀態(tài)遷移效果適用場景創(chuàng)建實例openstack server createBUILD → ACTIVE/ERROR上線新業(yè)務、擴容刪除實例openstack server delete任意狀態(tài) → 無釋放資源、下線業(yè)務開機openstack server startSHUTOFF → ACTIVE恢復關(guān)機實例關(guān)機openstack server stopACTIVE → SHUTOFF計劃維護、釋放CPU內(nèi)存軟重啟openstack server reboot --softACTIVE → REBOOT → ACTIVEguest OS可響應時的重啟硬重啟openstack server reboot --hardACTIVE → HARD_REBOOT → ACTIVE系統(tǒng)無響應、內(nèi)核卡死暫停/恢復openstack server pause/unpauseACTIVE ? PAUSED短時凍結(jié)不落盤掛起/恢復openstack server suspend/resumeACTIVE ? SUSPENDED宿主機休眠級維護擱置/恢復openstack server shelve/unshelveACTIVE ? SHELVED長期釋放計算資源鎖定/解鎖openstack server lock/unlock狀態(tài)不變防止誤操作創(chuàng)建快照openstack server image create狀態(tài)不變備份、模板復刻重建openstack server rebuildACTIVE/ERROR → REBUILD → ACTIVE系統(tǒng)盤被搞壞時恢復救援/取消救援openstack server rescue/unrescueACTIVE ? RESCUED進救援系統(tǒng)修配置變配openstack server resizeACTIVE → VERIFY_RESIZE調(diào)整CPU/內(nèi)存規(guī)格遷移openstack server migrateACTIVE/SHUTOFF → MIGRATING宿主機維護、負載均衡疏散openstack server evacuateERROR → ACTIVE計算節(jié)點故障時救命這16類操作基本覆蓋了日常運維90%以上的場景。下面我會按“存亡與電源管理”“凍結(jié)類操作”“恢復與重建”“遷移與變配”“外部資源聯(lián)動”五個維度逐個深入拆解。2. 實例的存亡與電源管理創(chuàng)建、刪除、開關(guān)機、重啟2.1 create與delete實例從哪來到哪去創(chuàng)建實例是所有操作的起點。執(zhí)行openstack server create --flavor flavor --image image --network net name后Nova會先把請求交給調(diào)度器Scheduler調(diào)度器根據(jù)flavor的資源約束、AZ可用域、宿主機負載等策略選出一個合適的計算節(jié)點然后通知該節(jié)點上的nova-compute去準備虛擬化資源。底層實際操作者是libvirt它根據(jù)鏡像和flavor配置生成域domain定義創(chuàng)建虛擬磁盤、虛擬網(wǎng)卡最后通過KVM/QEMU把虛機拉起來。創(chuàng)建實例時最容易踩的坑有三個。第一個是flavor的磁盤大小和鏡像實際大小不匹配如果系統(tǒng)盤是qcow2稀疏文件明明看鏡像只有幾百MB創(chuàng)建后卻可能膨脹到幾十GB磁盤配額不足就會導致創(chuàng)建卡在BUILD狀態(tài)。第二個是網(wǎng)絡選擇如果指定了錯誤的網(wǎng)絡虛機起來后網(wǎng)卡一直處于DOWN狀態(tài)業(yè)務根本無法訪問。第三個是忘記指定keypair或密碼注入方式導致創(chuàng)建完成后登不進去。刪除實例openstack server delete遠比創(chuàng)建看起來簡單但有幾個細節(jié)很容易被忽略。默認情況下刪除實例會連同它的系統(tǒng)盤一起清理如果系統(tǒng)盤是臨時盤ephemeral數(shù)據(jù)徹底丟失無法找回。Cinder數(shù)據(jù)卷不會自動刪除除非卷創(chuàng)建時設(shè)置了delete_on_terminationTrue。這個屬性在創(chuàng)建實例時指定很多運維習慣把所有數(shù)據(jù)都放到臨時盤上刪完才發(fā)現(xiàn)數(shù)據(jù)全沒了這種教訓我見過太多次。生產(chǎn)環(huán)境中刪除前一定要先確認是否需要保留系統(tǒng)盤快照不放心的話就先做個snapshot再刪。2.2 start與stop關(guān)機不等于刪除很多剛接觸OpenStack的人會把“關(guān)機”理解為“停止服務”但Nova里的stop操作實際是向?qū)嵗l(fā)送ACPI關(guān)機信號讓guest OS正常走系統(tǒng)關(guān)機流程。執(zhí)行openstack server stop后實例的vm_state會從ACTIVE變成SHUTOFFCPU和內(nèi)存資源被釋放宿主機可以騰出資源給其他實例。注意這只是釋放計算資源實例的磁盤文件仍然留在計算節(jié)點的/var/lib/nova/instances目錄下。start操作則是在同一個計算節(jié)點上基于原有的磁盤文件重新把虛機拉起來。它比創(chuàng)建新實例快得多因為不需要重新準備磁盤和網(wǎng)絡只需要啟動QEMU進程加載既有磁盤即可。這里有一個很容易被誤解的點關(guān)機再開機實例的IP地址會不會變正常情況下不會。因為實例的虛擬網(wǎng)卡信息和端口port是綁定在實例上的只要實例沒被刪除網(wǎng)卡端口就不會被釋放IP也就保持不變。但有一種情況例外如果實例所在的計算節(jié)點故障你通過evacuate把實例遷移到別的節(jié)點那IP地址雖然在OpenStack層面沒變但guest OS里的網(wǎng)絡配置可能對不上需要手工調(diào)整。關(guān)機雖然簡單但有個實際問題很多應用沒有優(yōu)雅處理ACPI關(guān)機的機制或者guest OS內(nèi)的acpid服務意外退出了這時候執(zhí)行stop狀態(tài)會長時間停留在ACTIVE或者任務超時。解決辦法是加--os-stop-hard強制關(guān)機或者到計算節(jié)點上直接執(zhí)行virsh destroy instance。但virsh destroy屬于“暴力斷電”客人機的文件系統(tǒng)可能損壞用之前一定要確認業(yè)務已經(jīng)停止。2.3 reboot軟硬之間怎么選重啟是運維用得最頻繁的操作。Nova的重啟分為軟重啟和硬重啟命令分別是openstack server reboot --soft和openstack server reboot --hard。軟重啟的本質(zhì)是讓guest OS走操作系統(tǒng)自身的重啟流程。實現(xiàn)上libvirt會向虛機發(fā)送ACPI reset信號內(nèi)核收到信號后正常關(guān)閉所有服務、卸載文件系統(tǒng)、然后重新啟動。整個過程和你在機器上執(zhí)行reboot命令幾乎一樣。它適合系統(tǒng)還能正常響應、需要清理內(nèi)存緩存或者應用狀態(tài)時使用。硬重啟則完全不同。它不等guest OS響應直接由hypervisor層把虛機電源切斷再重新通電。QEMU進程被強制重啟CPU狀態(tài)重新初始化guest OS會經(jīng)歷一次非正常的斷電-通電過程。這種模式適合guest OS完全卡死、網(wǎng)絡不可達、軟重啟一直超時的情況下應急。選擇軟硬重啟有個基本原則能軟不硬。硬重啟有極小概率導致文件系統(tǒng)損壞特別是在有大量未落盤寫入的時候。我遇到過幾次實例重啟后起不來最后檢查發(fā)現(xiàn)是mysql的binlog沒落盤硬重啟導致數(shù)據(jù)文件不一致只能做InnoDB恢復。所以如果你的實例跑的是數(shù)據(jù)庫這類對一致性敏感的服務盡量先軟重啟軟重啟超時后再考慮硬重啟。Nova默認的重啟策略是軟重啟如果你確實需要硬重啟記得顯式加--hard參數(shù)。3. 凍結(jié)類操作暫停、掛起、擱置、鎖定3.1 pause與unpause最輕量的凍結(jié)暫停pause是一個被很多人忽略但實際很有用的操作。執(zhí)行openstack server pause后libvirt調(diào)用QEMU的pause命令把虛機的vCPU停止調(diào)度但整個虛機的內(nèi)存仍然保留在物理內(nèi)存中。實例進入PAUSED狀態(tài)從guest OS的視角看就像時間被凍結(jié)了所有進程原地停滯。這種凍結(jié)非常輕量恢復也極快unpause之后虛機立刻從上次暫停的位置繼續(xù)執(zhí)行。它適合臨時讓一個高占CPU的服務讓出資源或者做短時間的計算資源騰挪。比如你有幾臺實例在跑跑批任務白天占用大量CPU但不希望直接關(guān)機因為任務進度還在內(nèi)存里這時候pause一下等夜間再恢復非常合適。但pause有一個必須注意的致命缺陷PAUSED狀態(tài)不會被持久化。如果計算節(jié)點突然斷電或者nova-compute服務重啟宿主機上的libvirt會重新接管虛機PAUSED狀態(tài)大概率會丟失虛機可能直接恢復運行也可能進入ERROR。一旦節(jié)點故障你甚至無法確定虛機現(xiàn)在處于什么狀態(tài)。所以涉及長時間凍結(jié)優(yōu)先考慮suspend而不是pause。另外pause不支持跨節(jié)點遷移它是純粹基于本機物理內(nèi)存的凍結(jié)。3.2 suspend與resume內(nèi)存寫到本地盤掛起suspend和暫停pause看起來很像但底層原理完全不同。執(zhí)行openstack server suspend后nova-compute會調(diào)用libvirt的save操作把虛機的完整內(nèi)存狀態(tài)寫入宿主機本地磁盤默認路徑通常是/var/lib/libvirt/qemu/save/寫入完成后虛機進程被終止資源完全釋放。實例狀態(tài)變?yōu)镾USPENDED。因為內(nèi)存鏡像寫到了磁盤上所以suspend狀態(tài)是持久的。只要宿主機磁盤沒壞不管nova-compute重啟多少次實例都能恢復?;謴蛣幼鱫penstack server resume直接讀取內(nèi)存鏡像文件加載到內(nèi)存后繼續(xù)運行?;謴退俣入m然比pause慢需要讀盤但比reboot快得多因為磁盤狀態(tài)完全不用重新初始化。suspend最適合的場景是宿主機計劃內(nèi)重啟。比如你要對某臺物理機做內(nèi)核升級、換硬件、調(diào)整BIOS先把上面所有實例suspend掉等機器重啟完成后再批量resume。我之前維護一批計算節(jié)點時就是用腳本批量遍歷實例執(zhí)行suspend節(jié)點重啟后再批量resume整個過程業(yè)務中斷時間只有幾分鐘遠比一臺臺關(guān)系統(tǒng)再開系統(tǒng)快。使用suspend有個隱藏成本內(nèi)存鏡像文件占的磁盤空間約等于實例的物理內(nèi)存大小。如果一臺宿主機上跑了20臺16GB內(nèi)存的虛機同時掛起的話宿主機本地磁盤會瞬間多出320GB的占用。所以批量掛起前一定要檢查宿主機磁盤余量否則掛了一半磁盤寫滿剩下的實例直接卡在SUSPENDING狀態(tài)。3.3 shelve與unshelve數(shù)據(jù)上傳Glance資源釋放擱置shelve是這三種凍結(jié)方式里最“狠”的。執(zhí)行openstack server shelve后Nova會把實例的系統(tǒng)盤做成鏡像上傳到Glance然后把計算節(jié)點上的實例文件清理掉虛機進程和本地磁盤全部消失只保留鏡像和實例元數(shù)據(jù)。如果還執(zhí)行了shelve_offload連計算節(jié)點上殘留的快照文件也會被清掉實例在計算節(jié)點上的占用量接近于零?;謴蛿R置實例要執(zhí)行openstack server unshelve。Nova會從Glance讀取shelve時創(chuàng)建的鏡像重新調(diào)度計算節(jié)點重新創(chuàng)建虛機。整個過程相當于用“備份鏡像”重新創(chuàng)建了一臺同名同ID的實例。shelve最大的價值在于長期釋放計算資源。比如一批測試機周末沒人用直接shelve掉等周一再unshelve回來能省下大量內(nèi)存和CPU資源。如果測試機很多這個操作可以顯著降低宿主機資源壓力。但shelve有個大坑實例的臨時盤ephemeral和本地數(shù)據(jù)盤不會保留。shelve時只上傳系統(tǒng)盤臨時盤的內(nèi)容會丟失。如果你的應用把數(shù)據(jù)寫在本地盤上shelve之后這些數(shù)據(jù)就沒了。因此生產(chǎn)實例除非確認所有數(shù)據(jù)都已經(jīng)落到Cinder卷或?qū)ο蟠鎯Ψ駝t不建議shelve。另外unshelve之后實例的IP地址在網(wǎng)絡層面會保留端口還在但guest OS的配置可能需要重新檢查特別是自定義了網(wǎng)卡配置的鏡像。3.4 lock與unlock防手滑的保險鎖定lock是一個很不起眼但非常實用的操作。執(zhí)行openstack server lock后實例處于LOCKED狀態(tài)所有修改型操作reboot、resize、delete、stop、start、rebuild等都會被Nova拒絕只有只讀操作和網(wǎng)絡查看操作可以執(zhí)行。這個操作特別適合生產(chǎn)環(huán)境。我見過不止一次因為誤操作把線上數(shù)據(jù)庫實例給刪了或者重啟了。在OpenStack里加上lock之后即使有人拿著管理員的OpenRC環(huán)境變量誤敲了deleteAPI也會直接返回錯誤相當于給實例上了一道保險。解鎖也很簡單openstack server unlock。如果你是管理員普通用戶鎖定的實例你也可以用openstack server unlock --force強制解鎖。但要注意lock保護的是OpenStack API層面的操作它擋不住管理員直接登錄計算節(jié)點執(zhí)行virsh destroy。換句話說lock是給“正常人”用的鎖不是給鐵了心想搞破壞的人用的。不過在常規(guī)運維流程中給核心數(shù)據(jù)庫、核心業(yè)務實例加上lock就是個好習慣成本幾乎為零。4. 恢復與重建類操作快照、重建、救援4.1 snapshot操作前先留后路創(chuàng)建快照snapshot是Nova里最值得養(yǎng)成的習慣之一。執(zhí)行openstack server image create --name snapshot_name server會把當前實例的系統(tǒng)盤制作成一個鏡像上傳到Glance之后可以用這個鏡像創(chuàng)建新實例也可以作為rebuild的底子??煺盏牡讓釉韺cow2系統(tǒng)盤來說是一個在線鏡像合并操作。libvirt會發(fā)起一個live snapshot先創(chuàng)建一個新的qcow2覆蓋層overlay然后把當前系統(tǒng)的所有寫入引導到新層同時后臺將舊層的所有數(shù)據(jù)合并上傳到Glance。這個過程對運行中的虛機影響很小業(yè)務基本無感知。但有一種情況需要注意如果你的系統(tǒng)盤數(shù)據(jù)量特別大比如200GB的數(shù)據(jù)庫系統(tǒng)盤快照過程會持續(xù)很久期間磁盤IO會明顯上升應用寫入性能可能受到影響。為了保證快照一致性數(shù)據(jù)庫類實例建議先短暫pause快照完成后再unpause。這樣能避免系統(tǒng)盤在快照過程中有未落盤的臟頁。當然pause會影響業(yè)務需要和業(yè)務方確認停機窗口。如果沒有停機窗口也建議在業(yè)務低峰期做快照??煺者€有一個非常常見的用途——成為“模板”。我經(jīng)常通過快照把一臺配置好的環(huán)境復制成多臺測試機比如初始化好的Web環(huán)境、裝好agent的監(jiān)控環(huán)境快照比從頭創(chuàng)建省時間得多??煺照加玫拇鎯臻g和系統(tǒng)盤實際使用量接近存儲不夠的話快照很容易失敗所以Glance存儲的容量規(guī)劃也要提前做好。4.2 rebuild保留實例身份的系統(tǒng)盤重置重建rebuild是Nova里最“神奇”的操作之一。執(zhí)行openstack server rebuild --image image server后實例會用指定的鏡像重新生成系統(tǒng)盤但實例的ID、IP地址、數(shù)據(jù)卷保持原樣guest OS收到“系統(tǒng)盤被整個替換”的處理方式。rebuild的本質(zhì)是Nova把實例的元數(shù)據(jù)保留重新創(chuàng)建一塊新的系統(tǒng)盤使用指定的鏡像然后把舊系統(tǒng)盤丟棄虛機用新盤重新啟動。這和刪除重建完全不同——刪除重建會換ID、換IP而rebuild不會所以對業(yè)務感知來說更像是一次“系統(tǒng)重裝”。很多運維會用rebuild來快速恢復被惡意篡改的系統(tǒng)、修復損壞的系統(tǒng)文件、解決啟動障礙。rebuild有一個很關(guān)鍵的參數(shù)--preserve-ephemeral。如果實例有ephemeral盤默認情況下rebuild會把臨時盤也一起清掉加上這個參數(shù)后臨時盤數(shù)據(jù)會保留。但即使加了保留臨時盤系統(tǒng)盤上所有改動也會丟失所以rebuild前確認系統(tǒng)盤上有沒有需要保留的文件如果沒有備份先做快照再rebuild。rebuild是最適合“系統(tǒng)盤中毒、配置全亂、內(nèi)核損壞”這類場景的武器。比如某個實例被勒索軟件加密了系統(tǒng)盤直接rebuild回鏡像初始化狀態(tài)比慢慢殺毒修復快得多。只要你的數(shù)據(jù)都在Cinder卷上rebuild就沒什么負擔。4.3 rescue進救援模式修系統(tǒng)救援rescue是Nova里最被低估的操作。執(zhí)行openstack server rescue后Nova會把當前實例關(guān)機然后用一個指定的救援鏡像默認使用實例原本的鏡像啟動一個“救援實例”原實例的系統(tǒng)盤作為數(shù)據(jù)盤掛載到救援實例上。此時原實例狀態(tài)變?yōu)镽ESCUED你可以通過VNC或者SSH登錄救援實例然后掛載原系統(tǒng)盤去修復里面的文件。這個場景太適合“啟動不了”的實例了。比如某個實例開機直接進入緊急模式grub損壞或者關(guān)鍵系統(tǒng)服務起不來你可以rescue進去mount原盤刪掉有問題的配置文件、修復fstab、重裝引導然后執(zhí)行openstack server unrescue原實例會恢復為ACTIVE狀態(tài)并再次嘗試啟動。rescue的默認行為有幾個細節(jié)需要注意。第一rescue后的救援實例和原實例共享同一個計算節(jié)點網(wǎng)卡是新建的IP會變你需要通過openstack server show查看救援實例的IP地址再去登錄。第二原實例的系統(tǒng)盤掛載為數(shù)據(jù)盤路徑通常是/dev/vdb或/dev/vdc具體可以執(zhí)行l(wèi)sblk查看。第三如果實例處于ERROR狀態(tài)有時無法直接rescue需要先確認是否能被nova-compute識別。救援模式是我在OpenStack排障里用得最多的功能之一。很多人遇到實例啟動失敗第一反應是刪了重建但這樣會丟失IP和本地配置。其實先用rescue進去看一眼十有八九能救回來。5. 遷移與疏散類操作migrate、evacuate、resize5.1 migrate冷遷移與熱遷移的取舍遷移migrate是OpenStack運維繞不開的話題。openstack server migrate默認執(zhí)行冷遷移它要求實例處于SHUTOFF狀態(tài)Nova會將實例的磁盤文件從源計算節(jié)點復制到目標計算節(jié)點然后在目標節(jié)點重新啟動。整個過程業(yè)務是中斷的但數(shù)據(jù)完整性最有保障。熱遷移live migrate則完全不同命令是openstack server migrate --live target-host或者通過nova live-migration操作。熱遷移基于KVM原生的live migration能力先把源節(jié)點的實例內(nèi)存狀態(tài)持續(xù)復制到目標節(jié)點當雙方內(nèi)存數(shù)據(jù)達到同步后瞬間切換網(wǎng)絡和磁盤IO業(yè)務幾乎無感知。整個過程中虛機不關(guān)機、不中斷非常適合數(shù)據(jù)庫、在線交易這類不能停的服務。熱遷移的工作機制是QEMU通過內(nèi)存預復制pre-copy流程循環(huán)迭代地把源節(jié)點虛機的內(nèi)存頁面復制到目標節(jié)點同時跟蹤臟頁直到剩余臟頁足夠小再執(zhí)行停機拷貝stop-and-copy最后在目標節(jié)點恢復運行。如果你的實例內(nèi)存寫入非常頻繁比如每分鐘幾百MB的寫入臟頁迭代可能永遠追不上熱遷移直接掛在MIGRATING狀態(tài)。熱遷移還有兩個關(guān)鍵前提。第一源節(jié)點和目標節(jié)點必須能訪問同一個系統(tǒng)盤文件最典型的就是共享存儲Shared Storage比如把系統(tǒng)盤放在Ceph或者NFS共享目錄上。沒有共享存儲時Nova會啟用塊遷移block migration把本地磁盤也一并復制過去復制大磁盤會讓遷移時間變得不可控。第二網(wǎng)絡必須互通虛機的虛擬網(wǎng)卡需要能在目標節(jié)點上正常掛載到同一張網(wǎng)橋或虛擬交換機。我做熱遷移時最深的體會是遷移前一定先壓測或觀察實例的內(nèi)存寫頻率。如果instance的臟頁率太高熱遷移很可能永遠完不成這時候?qū)幙赏C做冷遷移也別一個任務掛在MIGRATING上熬到半夜。另外熱遷移完成后記得檢查實例的新宿主有時因為目標節(jié)點資源不足虛機被調(diào)度到意料之外的節(jié)點業(yè)務架構(gòu)的拓撲就變了。5.2 evacuate計算節(jié)點宕機時的救命操作疏散evacuate是所有OpenStack運維最希望永遠用不上、但必須熟練掌握的操作。當某臺計算節(jié)點物理宕機或網(wǎng)絡隔離時它上面運行的所有實例都會進入ERROR狀態(tài)里面的虛機實際上已經(jīng)“死亡”了。普通Cold Migrate和熱遷移都要求源節(jié)點能正常通信一旦源節(jié)點失聯(lián)唯一恢復實例的方法就是evacuate。openstack server evacuate --host target-host server會通知nova-scheduler在其他可用計算節(jié)點上重新啟動該實例。注意evacuate不是遷移它默認不會保留原來的系統(tǒng)盤數(shù)據(jù)——除非你用了共享存儲。如果系統(tǒng)盤放在Ceph等共享存儲上新節(jié)點可以直接掛載同一份數(shù)據(jù)業(yè)務恢復后數(shù)據(jù)完好無損。如果系統(tǒng)盤是本地盤源節(jié)點都掛了本地數(shù)據(jù)根本讀不出來evacuate后實例會從鏡像重新創(chuàng)建系統(tǒng)盤本地數(shù)據(jù)等于全部丟失。這就是OpenStack架構(gòu)設(shè)計里一個非常重要的取舍生產(chǎn)環(huán)境的系統(tǒng)盤和數(shù)據(jù)盤到底放本地還是共享存儲。我的建議是核心業(yè)務一定要走共享存儲在Ceph上因為只有這樣才能在計算節(jié)點故障時做到快速恢復。如果為了省錢把系統(tǒng)盤全放本地一旦宿主機壞了只能和不完整的數(shù)據(jù)說再見。evacuate的恢復時間取決于鏡像大小、目標節(jié)點資源、網(wǎng)絡復制速度但一般來說比重建快得多操作得當幾分鐘內(nèi)就能恢復服務。evacuate有一個常見的坑如果實例配置了admin_pass或者自定義了密碼注入evacuate后可能需要重新通過VNC設(shè)置密碼新節(jié)點上的實例可能和舊實例的guest OS狀態(tài)不一致。所以每次evacuate后建議第一時間檢查實例的啟動日志console log和網(wǎng)絡連通性確認服務真正恢復再切換流量。5.3 resize變配不只是改flavor變配resize是Nova里最容易出問題的操作之一。openstack server resize --flavor new_flavor server會把實例遷移到能承載新flavor的計算節(jié)點也可能是同一臺節(jié)點然后重新定義虛機的CPU、內(nèi)存和磁盤大小。如果新flavor的磁盤比原來大系統(tǒng)盤會被擴容如果比原來小系統(tǒng)盤文件不變但可能會有多余空間無法利用。resize完成后實例會進入VERIFY_RESIZE狀態(tài)你需要手動執(zhí)行openstack server resize confirm確認變更或者openstack server resize revert回滾到原來的flavor。這里有個非常關(guān)鍵的時間窗口如果設(shè)置了resize_confirm_window比如24小時超過該時間后Nova會自動confirm如果沒有設(shè)置實例可能一直停留在VERIFY_RESIZE狀態(tài)直到你手動確認。resize最坑的一點是默認情況下resize會執(zhí)行冷遷移意味著實例會關(guān)機業(yè)務中斷時間可能在幾分鐘到幾十分鐘不等。你需要在變配窗口內(nèi)完成全部操作。如果業(yè)務不允許中斷可以考慮支持在線變配的版本或使用專門的縮擴容方案但OpenStack社區(qū)版本默認不提供CPU/內(nèi)存熱插拔。變配之前強烈建議先做快照因為resize過程如果失敗原實例的磁盤文件可能被重新調(diào)度到別的節(jié)點恢復起來非常麻煩。我在生產(chǎn)環(huán)境變配時有一個固定流程先看新flavor的磁盤大小是否足夠再看實例當前所在宿主機的資源是否滿足新flavor有時候Nova不會遷移直接原地調(diào)整最后執(zhí)行resize等VERIFY_RESIZE狀態(tài)后檢查虛機狀態(tài)和業(yè)務確認無誤再confirm。如果resize后業(yè)務異常就revert回滾。這個流程雖然保守但從來沒出過事故。6. 與外部資源聯(lián)動的操作卷掛載與浮動IP6.1 attach與detach volume數(shù)據(jù)盤怎么接實例只有一塊系統(tǒng)盤很多時候不夠用Cinder卷云硬盤就派上用場了。Nova這里對應的操作是attach和detach。命令分別是openstack server add volume server volume和openstack server remove volume server volume。把Cinder卷掛到實例上之后它在guest OS里的表現(xiàn)就是一塊新的塊設(shè)備比如/dev/vdb或/dev/vdc。系統(tǒng)不會自動分區(qū)、不會自動格式化、也不會自動掛載到某個目錄這一切都需要你進入實例手動完成。很多新手掛載完卷之后以為直接就能用了結(jié)果lsblk一查發(fā)現(xiàn)根本沒出現(xiàn)這是因為塊設(shè)備需要在系統(tǒng)層面做分區(qū)、格式化、掛載。我會在卷掛載完成后用lsblk確認設(shè)備已識別然后mkfs.ext4 /dev/vdb格式化如果新卷再mkdir /data mount /dev/vdb /data如果需要開機自動掛載還要配置 /etc/fstab。如果掛載的是啟動卷bootable volume你可以直接用這個卷作為實例的系統(tǒng)盤啟動。這種情況在需要從快照卷恢復數(shù)據(jù)或者更換系統(tǒng)盤時特別有用。detach操作看起來簡單其實是個危險動作。如果guest OS還在讀寫這個卷直接detach會導致文件系統(tǒng)損壞或者IO錯誤。正確的流程是先登錄實例執(zhí)行umount卸載掛載點確認沒有進程占用該設(shè)備然后再在OpenStack側(cè)執(zhí)行remove volume。如果實在無法登錄實例但又要強制下線數(shù)據(jù)盤需要在Nova側(cè)強制解綁這種做法有數(shù)據(jù)損壞風險不到萬不得已不要用。卷掛載還有一個常見問題掛載了多塊卷之后設(shè)備名在重啟后可能發(fā)生漂移。比如 /dev/vdb 重啟后變成了 /dev/vdc。這是因為Linux內(nèi)核枚舉設(shè)備的順序不完全固定。生產(chǎn)環(huán)境我建議通過UUID或者標簽LABEL來掛載設(shè)備不要直接寫死/dev/vdb這樣可以避免啟動后掛載失敗的尷尬。6.2 浮動IP的關(guān)聯(lián)與解綁浮動IPFloating IP是OpenStack里讓外部網(wǎng)絡訪問實例的標準方式。實例默認可能只有內(nèi)網(wǎng)IP外部無法直接訪問。執(zhí)行openstack server add floating ip server floating_ip就把一個公網(wǎng)IP綁定到實例上解綁是openstack server remove floating ip server floating_ip。浮動IP的本質(zhì)是iptables的DNAT規(guī)則在Neutron的路由節(jié)點或虛擬路由器上把浮動IP的流量映射到實例的內(nèi)網(wǎng)IP。實例自身感知不到浮動IP的存在它的網(wǎng)卡配置依然是內(nèi)網(wǎng)IP。所以解綁浮動IP后實例的內(nèi)部網(wǎng)絡、內(nèi)網(wǎng)服務完全不受影響只是外部無法再通過那個公網(wǎng)IP訪問它。浮動IP關(guān)聯(lián)和云主機本身的“多網(wǎng)卡配置”不要混淆。如果你需要多塊網(wǎng)卡、多個內(nèi)網(wǎng)IP應該創(chuàng)建多個端口port然后附加到實例上。浮動IP只是外網(wǎng)出入口的映射和網(wǎng)卡數(shù)量無關(guān)。實際運維中我經(jīng)常用浮動IP做“故障切換”。比如一臺Web實例掛了我可以先把浮動IP從故障實例解綁再綁定到備用實例上實現(xiàn)秒級切換。這個操作比改DNS快得多非常適合對中斷時間敏感的場景。要注意的是浮動IP解綁后原來實例的外網(wǎng)連接會立即斷開如果業(yè)務里有長連接比如數(shù)據(jù)庫的外網(wǎng)連接池全部重連的成本也要考慮到。7. 實戰(zhàn)速查故障場景操作組合與高頻坑位7.1 典型運維場景的操作組合Nova的16種操作很少單獨使用實際運維中經(jīng)常是組合拳。我挑幾個高頻場景把操作串聯(lián)起來講一遍。場景一宿主機計劃維護。比如要對計算節(jié)點做內(nèi)核升級。正確做法是先把該節(jié)點上所有實例都執(zhí)行openstack server migrate --live熱遷移出去如果熱遷移條件不滿足或者實例狀態(tài)不健康就改成suspend等節(jié)點維護完再批量resume。這里的決策順序是先看共享存儲是否可用再看實例是否允許短時間暫停。熱遷移最推薦因為它對業(yè)務影響最小沒有共享存儲時才退而求其次用suspend。場景二實例系統(tǒng)盤被入侵或損壞嚴重。首先執(zhí)行openstack server image create創(chuàng)建快照留作證據(jù)或后續(xù)分析然后執(zhí)行openstack server rebuild --image 原鏡像快速恢復。如果rebuild后還是起不來再考慮openstack server rescue進入救援模式修復。這個順序比較重要先保存現(xiàn)場再快速恢復最后才深入修復。場景三實例負載持續(xù)增長需要擴大規(guī)格。執(zhí)行openstack server resize --flavor 大規(guī)格實例進入VERIFY_RESIZE狀態(tài)后檢查業(yè)務是否正常確認無誤再執(zhí)行openstack server resize confirm。如果異常執(zhí)行openstack server resize revert回滾。變配之前先做snapshot整個過程避免在業(yè)務高峰期進行。場景四計算節(jié)點宕機。先確認節(jié)點確實失聯(lián)然后用openstack server evacuate --host 其他節(jié)點 server把實例一一疏散。如果系統(tǒng)盤在共享存儲上數(shù)據(jù)不會丟如果系統(tǒng)盤在本地要有數(shù)據(jù)丟失的心理準備。疏散完成后檢查實例的console log和網(wǎng)絡連通性確認服務恢復后再把流量切回。整個過程中可以利用浮動IP解綁/綁定做流量切換。7.2 高頻問題排查速查表故障現(xiàn)象可能原因排查與解決辦法實例一直停留在BUILD狀態(tài)鏡像過大、資源不足、調(diào)度失敗檢查計算節(jié)點的可用內(nèi)存/CPU查看nova-compute日志確認鏡像下載是否完成關(guān)機stop后狀態(tài)仍為ACTIVEguest OS沒有響應ACPI關(guān)機信號檢查guest內(nèi)acpid服務或者用--os-stop-hard強制關(guān)機實例狀態(tài)為ERROR但task_state為空磁盤空間不足、鏡像損壞、網(wǎng)絡插件失敗查看nova-compute和neutron日志確認是否磁盤滿清理空間后重置狀態(tài)pause之后計算節(jié)點重啟實例狀態(tài)異常PAUSED狀態(tài)不持久化之后盡量用suspend替代pause做長時間凍結(jié)resize后忘記confirm實例卡在VERIFY_RESIZEresize_confirm_window未設(shè)置或還沒到超時手動執(zhí)行openstack server resize confirm或者根據(jù)業(yè)務情況revert熱遷移長時間卡在MIGRATING內(nèi)存臟頁率過高迭代無法收斂停止高寫入負載等待遷移完成或者取消遷移改為冷遷移evacuate后實例數(shù)據(jù)丟失系統(tǒng)盤放在本地盤而非共享存儲排查源節(jié)點是否能恢復數(shù)據(jù)不能恢復只能從鏡像重建后續(xù)建議系統(tǒng)盤遷移到共享存儲掛載卷后實例內(nèi)看不到設(shè)備卷掛載成功但guest OS未識別或未分區(qū)進入實例執(zhí)行l(wèi)sblk檢查新卷需要分區(qū)、格式化、掛載快照成功但新實例創(chuàng)建失敗快照時系統(tǒng)盤不一致或鏡像元數(shù)據(jù)損壞檢查Glance鏡像狀態(tài)嘗試重新創(chuàng)建快照或者基于快照做rebuild驗證lock之后還能被強制刪除管理員用了--force解鎖生產(chǎn)環(huán)境通過RBAC權(quán)限控制限制普通用戶對核心實例的管理權(quán)限7.3 最后再分享兩個經(jīng)驗寫到這里收尾之前我還是想多說幾句個人體會。第一個是關(guān)于操作習慣。我見過太多人在OpenStack上直接敲命令完全不管當前實例狀態(tài)結(jié)果就是各種奇奇怪怪的操作沖突。其實Nova的命令設(shè)計得很“講道理”大多數(shù)操作都有前置狀態(tài)要求你只要在操作前執(zhí)行openstack server show看一眼狀態(tài)絕大多數(shù)事故都能避免。我自己現(xiàn)在養(yǎng)成了習慣凡是生產(chǎn)實例操作前必看狀態(tài)和task_state寧可多花五秒查看也不愿花五小時處理誤操作。第二個是關(guān)于鏡像和備份的執(zhí)念。Nova再強大也擋不住存儲層面的物理故障和邏輯錯誤。我的原則是所有核心實例至少保留最近一份快照所有數(shù)據(jù)卷定期做Cinder備份所有配置變更前先出快照。這個習慣救了我太多次甚至有一次整臺計算節(jié)點的磁盤陣列故障我硬是靠前一天晚上的快照把十幾臺實例全部恢復到了可用狀態(tài)。Nova的16種操作只是工具集真正的安全墊永遠是備份意識和紀律性。希望這篇整理能幫你把工具用熟也把備份的習慣刻進肌肉記憶里。