動靜態遷移的原理
靜態遷移是指在虛擬機關閉或暫停的情況下,將源宿主機上虛擬機的磁盤文件和配置文件拷貝到目標宿主機上。這種方式需要顯式的停止虛擬機運行,對服務可用性要求高的需求不合適。
動態遷移無需拷貝虛擬機配置文件和磁盤文件,但是需要遷移的主機之間有相同的目錄結構放置虛擬機磁盤文件,可以通過多種方式實現,本例采用基於共享存儲動態遷移,通過NFS來實現。
實驗環境
源宿主機:Ubuntu17.10 Server版操作系統,4.10.0-38-generic內核。下文中以“Node1”表示,主機名為Service,IP地址為192.168.200.132,NFS掛載目錄/opt。
目標宿主機:Ubuntu17.10 Server版操作系統,4.10.0-38-generic內核。下文中以“Node2”表示,主機名為Service1,IP地址為192.168.200.131,NFS掛載目錄/opt。
基於QEMU的動態遷移虛擬機鏡像文件為ubuntu16server.img。
基於libvirt的靜態遷移測試虛擬機:demo1,IP為192.168.200.132,虛擬鏡像文件為ubuntu16.img。
基於libvirt的動態遷移測試虛擬機:demo2,IP為192.168.200.131,虛擬鏡像文件為ubuntu16.img。
NFS服務器:Ubuntu17.10 Server版,4.10.0-38-generic內核。IP地址為192.168.200.130,服務目錄為/opt/share。
配置步驟
NFS服務器的搭建
- KVM虛擬機動態遷移無需拷貝虛擬機配置文件和磁盤文件,但是需要遷移的主機之間有相同的目錄結構放置虛擬機磁盤文件(本例為“/opt/share”目錄),這里的動態遷移是基於共享存儲動態遷移,通過NFS來實現,需要QEMU 0.12.2以上版本支持。可以使用以下命令查看安裝的QEMU的版本號。
qemu-img --help|grep version
- 首先在NFS服務器上,下載安裝NFS,kernel-server相當於server端,common是client端,使用命令以下命令進行安裝NFS:
sudo apt-get install nfs-kernel-server nfs-common -y
- 配置NFS服務器,將NFS服務器上的“/opt/share”目錄設為服務目錄。首先使用以下命令創建目錄,然后修改創建的目錄權限,同時如果不放心是否權限修改了,可以查看下文件夾的權限,修改后為“drwxr-xr-x”
sudo mkdir /opt/share,
sudo chmod 777 /opt/share
sudo ll /opt
- 接下來使用vim修改“/etc/exports”:文件添加共享目錄,在該文件最后添加以下內容即可。/opt/share:表示要設置的共享目錄,*:表示允許所有的網段訪問,也可以使用具體的IP。rw:表示掛載此目錄的客戶端對該共享目錄具有讀寫權限。sync:表示資料同步寫入內存和硬盤。no_root_squash:表示root用戶具有對根目錄的完全管理訪問權限。no_subtree_check:表示不檢查父目錄的權限。修改完畢后保存退出。
/opt/share *(rw,sync,no_subtree_check,no_root_squash)
- _“/etc/exports”_文件修改后,使用命令然后進行刷新。最后啟動NFS服務,命令如下:
sudo exportfs –r
sudo /etc/init.d/rpcbind restart
sudo /etc/init.d/nfs-kernel-server restart
- NFS服務啟動后,在Node1上使用以下命令查看遠程主機的共享目錄,可以看到以下斜體內容
sudo showmount -e 192.168.200.130
root@Service:~# sudo showmount -e 192.168.200.130
Export list for 192.168.200.130:
/opt/share *
- 分別在Node1和Node2上分別掛載NFS服務器的共享文件夾到本地“/opt”目錄中,然后將Node1上的的虛擬磁盤文件ubuntu16server.img(前面實驗中制作的ubuntu的鏡像文件)拷貝到掛載NFS服務器共享目錄的文件夾“/opt”中(我制作好的鏡像文件在/root文件夾中),之后可以看到ubuntu16server.img鏡像文件。在節點2上執行同樣的操作,但在Node2中不用執行拷貝這一命令。
sudo mount -t nfs 192.168.200.130:/opt/share /opt -o rw
sudo cp /root/ubuntu16server.img /opt
- 掛載拷貝完成后兩節點都有相同的虛擬機磁盤文件存儲目錄
基於QEMU的虛擬機動態遷移
- 在Node1上使用如下命令啟動虛擬機,ubuntu16server.img為前面實驗制作的鏡像文件,-monitor stdio表示可以進入QEMU監控器,以便接下來執行遷移命令。
qemu-system-x86_64 -hda ubuntu16server.img -m 1024 -smp 1 -vnc :0 -monitor stdio
(qemu)
- 打開VNC界面,連接節點1上的QEMU虛擬機,登陸之后並執行“top”命令,可以看到界面一直在發生改變。
- 在Node2上使用以下命令啟動一個虛擬機,該虛擬機並沒有真實啟動,只是用於等待接收動態遷移過來的內存內容,使用VNC連接后顯示界面狀態為黑屏,或者是有一行提示。這里需要注意:在Node2上,NFS掛載目錄必須與源主機上保持一致;啟動客戶機命令也需一致,但是需要增加-incoming 選項。“-incoming tcp:0:6666” 這個參數表示在6666 端口建立一個tcp socket 連接用於接收來自於源宿主機的動態遷移的內容,其中“0”表示允許來自任何主機的連接,“-incoming”表示使QEMU進程進入到遷移監聽(migration-listen)模式,而不是真正以命令行中的鏡像文件運行客戶機。另外,這里是以NFS服務器上的鏡像文件作為虛擬機磁盤來啟動虛擬機,如果有多個用戶同時使用NFS服務器上的鏡像文件,請將鏡像文件在本地進行派生,使用派生后的鏡像文件啟動虛擬機,具體方式讀者可自行查閱相關資料
qemu-system-x86_64 -hda /opt/ubuntu16server.img -m 1024 -smp 1 -vnc :0 -incoming tcp:0:6666
- 在Node1源宿主機的qemu monitor 命令行中輸入以下命令遷移虛擬機,進入動態遷移的流程,其中“192.168.200.131”是目標宿主機IP,TCP協議和6666端口與目標宿主機上命令行的-incoming 參數保持一致
(qemu) migrate tcp:192.168.200.131:6666 //(qemu)為啟動鏡像時出現的qemu monitor
- 在Node1上執行"migrate"命令從開始到執行完成,大約十秒鍾(視網絡而定),在執行完成后遷移成功。遷移后在Node2上,也就是目標宿主機上,之前處於遷移監聽狀態的虛擬機開始運行,在該虛擬機中可以查看到,原來在Node1上運行的虛擬機上執行的top命令在遷移后仍在繼續在Node2上執行。
- 至此基於QEMU的虛擬機動態遷移完成
基於Libvirt的虛擬機靜態遷移
- 靜態遷移也叫做常規遷移、離線遷移(Offline Migration)。是在虛擬機關機或暫停的情況下,拷貝虛擬機磁盤文件與配置文件從源宿主機到目標宿主機中,實現的從一台物理機到另一台物理機的遷移。因為虛擬機的文件系統建立在虛擬機鏡像文件上面,所以在虛擬機關機的情況下,只需要簡單的遷移虛擬機鏡像和相應的配置文件到另外一台物理主機上即可。如果需要保存虛擬機遷移之前的狀態,那么應該在遷移之前將虛擬機暫停,然后拷貝狀態至目標宿主機,最后在目標宿主機重建虛擬機狀態,恢復執行。這種方式的遷移過程需要顯式的停止虛擬機的運行。從用戶角度看,有明確的一段停機時間,虛擬機上的服務不可用。這種遷移方式簡單易行,適用於對服務可用性要求不嚴格的場合。
- 為網絡添加br0網橋
sudo brctl addbr br0
sudo brctl addif br0 ens33
sudo brctl stp br0 on
sudo ifconfig ens33 0
sudo dhclient br0
- 在Node1上進行操作,首先確定demo虛擬機狀態為“shut off”,如果不是可以執行“destroy
” 進行關閉sudo virsh list --all
- 准備遷移demo虛擬機,查看demo虛擬機的磁盤文件
virsh domblklist
- 導出虛擬機配置文件demo.xml、ubuntu16.img,將其發送到Node2中與Node1中文件對應的文件夾(demo.xml文件在文章結尾會給出代碼)
sudo scp /root/demo.xml /root/ubuntu16.img 192.168.200.131:/root
- 之后開始在目標宿主機Node2上進行虛擬機的配置和啟動。
- 使用virsh的子命令define定義並注冊demo虛擬機
sudo virsh define /root/demo.xml
- 啟動遷移后的demo虛擬機,通過VNC查看,VNC端口查看
sudo virsh vncdisplay
- 然后通過VNC查看是否可以登陸和其他操作
基於Libvirt的虛擬機動態遷移
- 此處我說明下,這種遷移雖然為基於Libvirt的動態遷移,但是其遷移的只是虛擬機的狀態而不是虛擬機的狀態和文件,這一點我再次特別說明。
- 將Node1上的“ubuntu16.img”發送到Node2對應的文件夾,此時的demo狀態為“shut off”,發送后啟動demo虛擬機
sudo scp /root/ubuntu16.img 192.168.200.131:/root
- 查看Node1上虛擬機狀態,demo虛擬機保證處於“runing”(如果demo處於“shut off”,將其啟動運行“sudo virsh start demo”)
sudo virsh list --all
- 查看Node2上虛擬機狀態,確保無虛擬機運行,命令如上
- 通過VNC連接登陸,並執行"top"命令
- 在Node1上執行“virsh migrate”遷移命令,虛擬機demo在遷移出去的過程中,狀態有從“running”到“shut off”的一個改變。--verbose 指遷移demo虛擬機,192.168.200.131為節點2的IP地址,使用tcp協議連接,--unsafe參數表示跳過安全檢測, /system為以root身份進行狀態遷移,qemu+ssh表示為通過ssh通道連接到遠程節點的system實例,具有最大權限來管理遠程節點上的虛擬機資源
sudo virsh migrate --live --verbose demo qemu+ssh://192.168.200.131/system tcp://192.168.200.131 --unsafe
- 在Node2上,查看虛擬機demo虛擬機狀態為“runing”
sudo virsh list --all
- 在遷移過程中,可以通過另外一台客戶機一直ping虛擬機demo,查看demo遷移過程中的可連接性。實際上遷移過程除了偶爾有幾個包的中斷,基本上沒有太大影響
- 此時雖然demo虛擬機已經在Node2上啟動了,但是Node2上還沒有demo虛擬機的配置文件。這時需要創建配置文件並定義該虛擬機,可以通過遷移過來的虛擬機內存狀態創建虛擬機配置文件,然后通過xml配置文件定義虛擬機。
sudo virsh dumpxml demo > /etc/libvirt/qemu/demo1.xml //之所以命名為demo1.xml是因為,在libvirt靜態遷移過程中已經有個demo.xml文件,雖然不在同一個文件夾,為了避免搞混。
sudo virsh define /etc/libvirt/qemu/demo1.xml
- 通過VNC連接查看,VNC端口號查詢。
sudo virsh vncdisplay demo
- 在通過VNC連接上后發現遷移前的“top”命令依然在執行
- 至此,demo虛擬機遷移完成。
demo.xml文件中的內容
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
virsh edit demo
or other application using the libvirt API.
-->
<domain type='kvm'>
<name>demo</name>
<uuid>782ca9b9-8403-4fcd-979e-e4f038aaeb15</uuid>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-trusty'>hvm</type>
<boot dev='cdrom'/>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/ubuntu16.img'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:c0:a2:8a'/>
<source bridge='br0'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='en-us'/>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
</domain>
