KVM 介紹(8):使用 libvirt 遷移 QEMU/KVM 虛機和 Nova 虛機 [Nova Libvirt QEMU/KVM Live Migration]


 學習 KVM 的系列文章:

 

1. QEMU/KVM 遷移的概念

     遷移(migration)包括系統整體的遷移和某個工作負載的遷移。系統整理遷移,是將系統上所有軟件包括操作系統完全復制到另一個物理機硬件機器上。虛擬化環境中的遷移,可分為靜態遷移(static migration,或者 冷遷移 cold migration,或者離線遷移 offline migration) 和 動態遷移 (live migration,或者 熱遷移 hot migration 或者 在線遷移 online migration)。靜態遷移和動態遷移的最大區別是,靜態遷移有明顯一段時間客戶機中的服務不可用,而動態遷移則沒有明顯的服務暫停時間。

    虛擬化環境中的靜態遷移也可以分為兩種,一種是關閉客戶機后,將其硬盤鏡像復制到另一台宿主機上然后恢復啟動起來,這種遷移不能保留客戶機中運行的工作負載;另一種是兩台宿主機共享存儲系統,這時候的遷移可以保持客戶機遷移前的內存狀態和系統運行的工作負載。

    動態遷移,是指在保證客戶機上應用服務正常運行的同時,讓客戶機在不同的宿主機之間進行遷移,其邏輯步驟和前面的靜態遷移幾乎一直,有硬盤存儲和內存都復制的動態遷移,也有僅復制內存鏡像的動態遷移。不同的是,為了保證遷移過程中客戶機服務的可用性,遷移過程只能有非常短暫的停機時間。動態遷移允許系統管理員將客戶機在不同物理機上遷移,同時不會斷開訪問客戶機中服務的客戶端或者應用程序的連接。一個成功的遷移,需要保證客戶機的內存、硬盤存儲和網絡連接在遷移到目的主機后任然保持不變,而且遷移的過程的服務暫停時間較短。

1.1 遷移效率的衡量

(1)整體遷移時間

(2)服務器停機時間:這時間是指源主機上的客戶機已經暫停服務,而目的主機上客戶機尚未恢復服務的時間。

(3)對服務性能的影響:客戶機遷移前后性能的影響,以及目的主機上其它服務的性能影響。

  其中,整體遷移時間受很多因素的影響,比如 Hypervisor 和遷移工具的種類、磁盤存儲的大小(是否需要復制磁盤鏡像)、內存大小及使用率、CPU 的性能和利用率、網絡帶寬大小及是否擁塞等,整體遷移時間一般分為幾秒鍾到幾十分鍾不等。動態遷移的服務停機時間,也有這些因素的影響,往往在幾毫秒到幾百毫秒。而靜態遷移,其暫停時間較長。因此,靜態遷移一般適合於對服務可用性要求不高的場景,而動態遷移適合於對可用性要求高的場景。

動態遷移的應用場景包括:負載均衡、解除硬件依賴、節約能源 和異地遷移。

1.2 KVM 遷移的原理

1.2.1 靜態遷移

    對於靜態遷移,你可以在宿主機上某客戶機的 QEMU monitor 中,用 savevm my_tag 命令保存一個完整的客戶機鏡像快照,然后在宿主機中關閉或者暫停該客戶機,然后將該客戶機的鏡像文件復制到另一台宿主機中,使用在源主機中啟動該客戶機時的命令來啟動復制過來的鏡像,在其 QEMU monitor 中 loadvm my_tag 命令恢復剛才保存的快照即可完全加載保存快照時的客戶機狀態。savevm 命令可以保證完整的客戶機狀態,包括 CPU 狀態、內存、設備狀態、科協磁盤中的內存等。注意,這種方式需要 qcow2、qed 等格式的磁盤鏡像文件的支持。

1.2.2 動態遷移

    如果源宿主機和目的宿主機共享存儲系統,則只需要通過網絡發送客戶機的 vCPU 執行狀態、內存中的內容、虛機設備的狀態到目的主機上。否則,還需要將客戶機的磁盤存儲發到目的主機上。共享存儲系統指的是源和目的虛機的鏡像文件目錄是在一個共享的存儲上的。

    在基於共享存儲系統時,KVM 動態遷移的具體過程為:

  1. 遷移開始時,客戶機依然在宿主機上運行,與此同時,客戶機的內存頁被傳輸到目的主機上。
  2. QEMU/KVM 會監控並記錄下遷移過程中所有已被傳輸的內存頁的任何修改,並在所有內存頁都傳輸完成后即開始傳輸在前面過程中內存頁的更改內容。
  3. QEMU/KVM 會估計遷移過程中的傳輸速度,當剩余的內存數據量能夠在一個可以設定的時間周期(默認 30 毫秒)內傳輸完成時,QEMU/KVM 會關閉源宿主機上的客戶機,再將剩余的數據量傳輸到目的主機上,最后傳輸過來的內存內容在目的宿主機上恢復客戶機的運行狀態。
  4. 至此,KVM 的動態遷移操作就完成了。遷移后的客戶機盡可能與遷移前一直,除非目的主機上缺少一些配置,比如網橋等。

注意,當客戶機中內存使用率非常大而且修改頻繁時,內存中數據不斷被修改的速度大於KVM能夠傳輸的內存速度時,動態遷移的過程是完成不了的,這時候只能靜態遷移。

關於實時遷移的效率,業界不少人提出了改進的建議,比如通過使用內存壓縮技術,減少需要傳輸的內存的大小。這篇文章比較了各種方法,還是值得一讀。

1.3 使用命令行的方式做動態遷移

1.3.1 使用 NFS 共享存儲

(1)在源宿主機上掛載 NFS 上的客戶機鏡像,並啟動客戶機

mount my-nfs:/raw-images/ /mnt/

kvm /mnt/rh1.img -smp 2 -m 2048 -net nic -net tap

(2)在目的宿主機上也掛載鏡像目錄,並啟動一個客戶機用於接收動態遷移過來的內存內容

mount my-nfs:/raw-images/ /mnt/

kvm /mnt/rh1.img -smp 2 -m 2048 -net nic -net tap -incoming tcp:0:6666

注意:(1)NFS 掛載目錄必須一致 (2)“-incoming tcp:0:6666” 參數表示在 6666 端口建立一個 TCP socket 連接用於接收來自源主機的動態遷移的內容,其中 0 表示運行來自任何主機的連接。“-incoming“ 使 qemu-kvm 進程進入到監聽模式,而不是真正以命令行中的文件運行客戶機。

(3)在源宿主機的客戶機的 QEMU monitor 中,使用命令 ” migrate tcp:host2:6666" 即可進入動態遷移的流程。

1.3.2 不使用共享存儲的動態遷移

過程類似,包括使用相同backing file 的鏡像的客戶機遷移,以及完全不同鏡像文件的客戶機的遷移。唯一的區別是,migrate 命令中添加 “-b” 參數,它意味着傳輸塊設備。

1.3.3 其它 QEMU monitor migrate 命令

  • migrate_cancel:取消遷移
  • migrate_set_speed:設置最大遷移速度,單位是 bytes
  • migrate_set_downtime:設置最大允許的服務暫停時間,單位是 秒
  • info migrate:顯示遷移進度

2. OpenStack Nova QEMU/KVM 實例動態遷移的環境配置

除了直接拷貝磁盤鏡像文件的冷遷移,OpenStack 還支持下面幾種虛機熱遷移模式:

  • 不使用共享存儲時的塊實時遷移(Block live migration without shared storage)。這種模式不支持使用只讀設備比如 CD-ROM 和 Config Drive。塊實時遷移不需要 nova compute 節點都使用共享存儲。它使用 TCP 來將虛機的鏡像文件通過網絡拷貝到目的主機上,因此和共享存儲式的實時遷移相比,這種方式需要更長的時間。而且在遷移過程中,主機的性能包括網絡和 CPU 會下降。
  • 基於共享存儲的實時遷移 (Shared storage based live migration):兩個主機可以訪問共享的存儲。
  • 從卷啟動的虛機的實時遷移(Volume backed VM live migration)。這種遷移也是一種塊拷貝遷移。

實時遷移的過程並不復雜,復雜在於環境配置。

2.1 基礎環境配置

2.1.1 SSH 權限配置

這種方式需要配置源(compute1)和目的主機(compute2)之間能夠通過 SSH 相互訪問,以確保能通過 TCP 拷貝文件,已經可以通過 SSH 在目的主機建立目錄。

使用 nova 用戶在compute1 上執行操作:

usermod -s /bin/bash nova
su nova
mkdir -p -m 700 .ssh

#創建 config 文件如下
nova@compute2:~/.ssh$ cat config
Host *
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null

#產生 key
ssh-keygen -f id_rsa -b 1024 -P ""
cat id_rsa.pub >> authorized_keys

#將 id_rsa id_rsa.pub 拷貝到 compute2 上面
cat id_rsa.pub >> authorized_keys

使用 root 用戶在每個主機上進行操作:

root@compute1:/var/lib/nova/.ssh# chown -R nova:nova /var/lib/nova
root@compute1:/var/lib/nova/.ssh# chmod 700 /var/lib/nova/.ssh
root@compute1:/var/lib/nova/.ssh# chmod 600 /var/lib/nova/.ssh/authorized_keys

測試 SSH 無密碼訪問:

nova@compute1:~/.ssh$ ssh nova@compute2 ls
Warning: Permanently added 'compute2,192.168.1.29' (ECDSA) to the list of known hosts.
...

nova@compute2:~/.ssh$ ssh nova@compute1 ls
Warning: Permanently added 'compute1,192.168.1.15' (ECDSA) to the list of known hosts.
...

2.1.2 其它配置

 每個node 上的 DNS 或者 /etc/hosts,確保互聯互通。

2.2 Live migration 環境配置

2.2.1 libvirtd 配置

在 compute1 和 compute2 上做如下配置:

->Edit /etc/libvirt/libvirtd.conf
listen_tls = 0
listen_tcp = 1
auth_tcp = “none”

->Edit /etc/init/libvirt-bin.conf
env libvirtd_opts="-d -l"
->Edit /etc/default/libvirt-bin

  # options passed to libvirtd, add "-l" to listen on tcp
  libvirtd_opts="-d -l"

->Restart libvirtd
service libvirt-bin restart

root     12088     1  2 07:48 ?        00:00:00 /usr/sbin/libvirtd -d -l

做完上述操作后,可以使用如下命令來檢查是否設置正確:

root@compute2:~# virsh -c qemu+tcp://compute1/system list  --all
 Id    Name                           State
----------------------------------------------------
 4     instance-0000000d              running
 5     instance-00000006              running
 -     instance-00000005              shut off

root@compute1:~# virsh -c qemu+tcp://compute2/system list  --all
 Id    Name                           State
----------------------------------------------------

Nova 設置:

->Edit /etc/nova/nova.conf, add following line:  
  [libvirt]
  block_migration_flag = VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE,VIR_MIGRATE_TUNNELLED,VIR_MIGRATE_NON_SHARED_INC
  live_migration_flag = VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE,VIR_MIGRATE_TUNNELLED
  live_migration_uri = qemu+tcp://%s/system

2.2.2 共享存儲 Live migration 環境配置

其實共享存儲的實時遷移配置的要求和塊拷貝的實時遷移的配置差不多,除了下面幾點:

  1. Hypervisor 要求:目前只有部分 Hypervisor 支持 live migraiton,可查詢該表
  2. 共享存儲:存放虛機文件的文件夾 NOVA-INST-DIR/instances/ (比如 /var/lib/nova/instances,該路徑可以由 state_path 配置變量來配置) 必須是掛載到共享存儲上的。當Nova 使用 RBD 作為鏡像的backend時,這個要求不是必須的,具體見下面的說明。
  3. 必須在 nova.conf 中配置 vncserver_listen=0.0.0.0 (關於這個,社區認為這個配置具有安全風險,會通過這個 ticket 來解決)
  4. 不使用默認配置的話,必須在每個 nova compute 上的 nova.conf 中配置相同的 instances_path 和 state_path 。
  5. 在 Kilo 版本之前,Nova 是默認不支持 live migriation 的。在做實時遷移之前,需要在 nova.conf 中做如下配置
live_migration_flag=VIR_MIGRATE_UNDEFINE_SOURCE,VIR_MIGRATE_PEER2PEER,VIR_MIGRATE_LIVE,VIR_MIGRATE_TUNNELLED

 注意:對於上面第二點,在 Kilo 版本中(前面版本的情況未知),當 Nova 使用 RBD 作為 image backend 時,Nova 會認為是在共享存儲上:

def check_instance_shared_storage_local(self, context, instance):
        """Check if instance files located on shared storage."""
        if self.image_backend.backend().is_shared_block_storage():
            return None

在 class Rbd(Image): 類中:

 @staticmethod
    def is_shared_block_storage():
"""True if the backend puts images on a shared block storage."""
return True

目前,只有 RBD 作為 image backend 時,該函數才返回 true。對於其它類型的 backend,Nova 會在目的 host 上的 instance folder 創建一個臨時文件,再在源 host 上查看該文件,通過判斷是否該文件在共享存儲上來判斷是否在使用共享存儲。

常見問題:

(1)在源 host 上,出現  ”live Migration failure: operation failed: Failed to connect to remote libvirt URI qemu+tcp://compute2/system: unable to connect to server at 'compute2:16509': Connection refused“

其原因是 2.1.1 部分的 libvirt 設置不正確。

(2)在目的 host 上,出現 ”libvirtError: internal error: process exited while connecting to monitor: 2015-09-21T14:17:31.840109Z qemu-system-x86_64: -drive file=rbd:vms/6bef8898-85f9-429d-9250-9291a2e4e5ac_disk:id=cinder:key=AQDaoPpVEDJZHhAAu8fuMR/OxHUV90Fm1MhONQ==:auth_supported=cephx\;none:mon_host=9.115.251.194\:6789\;9.115.251.195\:6789\;9.115.251.218\:6789,if=none,id=drive-virtio-disk0,format=raw,cache=writeback,discard=unmap: could not open disk image rbd:vms/6bef8898-85f9-429d-9250-9291a2e4e5ac_disk:id=cinder:key=AQDaoPpVEDJZHhAAu8fuMR/OxHUV90Fm1MhONQ==:auth_supported=cephx\;none:mon_host=9.115.251.194\:6789\;9.115.251.195\:6789\;9.115.251.218\:6789: Could not open 'rbd:vms/6bef8898-85f9-429d-9250-9291a2e4e5ac_disk:id=cinder:key=AQDaoPpVEDJZHhAAu8fuMR/OxHUV90Fm1MhONQ==:auth_supported=cephx\;none:mon_host=9.115.251.194\:6789\;9.115.251.195\:6789\;9.115.251.218\:6789': Operation not permitted“

原因:目的 host 上的用戶操作 RBD 的權限設置不正確,檢查 secret 設置。

3. 遷移過程

3.0 Nova 有關遷移的命令

Nova 有三個與遷移有關的命令:migrate,live-migrate 和 resize。

Nova CLI REST API Action 行為
nova live-migration  --block-migrate  --disk_over_commit 8352e969-0a25-4abf-978f-d9d0ec4de0cd compute2 os-migrateLive 塊拷貝動態遷移
nova live-migration  8352e969-0a25-4abf-978f-d9d0ec4de0cd compute2 os-migrateLive 共享存儲動態遷移
nova migrate  8352e969-0a25-4abf-978f-d9d0ec4de0cd migrate 靜態遷移
nova resize --poll 8352e969-0a25-4abf-978f-d9d0ec4de0cd 1 resize 靜態遷移並且改變 flavor
nova resize --poll 8352e969-0a25-4abf-978f-d9d0ec4de0cd resize 靜態遷移
nova resize-confirm 9eee079e-0353-44cb-b76c-ecf9be61890d confirmResize 確認 resize 使得完整操作得以完成 
nova resize-revert 9eee079e-0353-44cb-b76c-ecf9be61890d revertResize 取消 resize 使得操作被取消虛機回到原始狀態 

 

3.1 靜態遷移(migrate 或者 resize 不使用新的 flavor)

s1@controller:~$ nova migrate --poll 9eee079e-0353-44cb-b76c-ecf9be61890d

Server migrating... 100% complete Finished s1@controller:~$ nova list +--------------------------------------+-------+---------------+------------+-------------+------------------------------------------+ | ID | Name | Status | Task State | Power State | Networks | +--------------------------------------+-------+---------------+------------+-------------+------------------------------------------+ | 02699155-940f-4401-bc01-36220db80639 | vm10 | ACTIVE | - | Running | demo-net2=10.0.10.17; demo-net=10.0.0.39 | | 9eee079e-0353-44cb-b76c-ecf9be61890d | vm100 | VERIFY_RESIZE | - | Running | demo-net2=10.0.10.20 | +--------------------------------------+-------+---------------+------------+-------------+------------------------------------------+ s1@controller:~$ nova resize-confirm 9eee079e-0353-44cb-b76c-ecf9be61890d s1@controller:~$ nova list +--------------------------------------+-------+--------+------------+-------------+------------------------------------------+ | ID | Name | Status | Task State | Power State | Networks | +--------------------------------------+-------+--------+------------+-------------+------------------------------------------+ | 02699155-940f-4401-bc01-36220db80639 | vm10 | ACTIVE | - | Running | demo-net2=10.0.10.17; demo-net=10.0.0.39 | | 9eee079e-0353-44cb-b76c-ecf9be61890d | vm100 | ACTIVE | - | Running | demo-net2=10.0.10.20 | +--------------------------------------+-------+--------+------------+-------------+------------------------------------------+ 

 

3.1.1 遷移過程

 直接使用流程圖來說明:

1. migrate 和 resize 都是執行靜態遷移。

2. 靜態遷移分為三個階段:

(1)調用 Scheduler 算法選擇目的 node(步驟5),並通過 RPC 遠程調用 prep_resize 做些遷移前的准備工作

(2)在源主機上,調用 libvirt driver 做一系列操作:

  1. 使用 ssh 在目的 node 上建立虛機的鏡像文件的目錄
  2. 將虛機關機
  3. 斷開所有 volume connections
  4. 針對每一個非 swap 分區的磁盤,如果是 qcow2 格式,則執行 qemu-img merge 操作將稀疏文件和backing 文件合並成單個文件,並通過 “rysnc” 或者 “scp”命令將文件拷貝到目的 node 上
  5. 開始遷移需要的網絡工作

(3)通過 RPC,調用目的 node 上的 Nova 的 finish_resize 方法。該方法會在自己本機上設置網絡、結束網絡設置工作,並調用 libvirt driver 來:

  1. 創建 image
  2. 獲取 guest xml
  3. 創建 domain 和 network
  4. 需要的話啟動虛機

至此,虛機已經被拷貝到目的主機上了。接下來,用戶有兩個選擇:resize_confirm 和 resize_revert。

3.1.2 確認遷移 (resize_confirm)

遷移確認后,在源主機上,虛機的文件會被刪除,虛機被 undefine,虛機的 VIF 被從 OVS 上拔出,network filters 也會被刪除。

3.1.3 取消遷移 (resize_revert)

取消遷移的命令首先發到目的 node 上,依次 tear down network,刪除 domain,斷掉 volume connections,然后調用源主機上的方法來重建 network,刪除臨時文件,啟動 domain。這樣,虛機就會需要到 resize 之前的狀態。

 3.2 實時遷移 (Live migration)

可以 Nova client 的 live-migration 命令來做實時遷移,除了要被遷移的 虛機 和 目的 node 外,它可以帶兩個額外的參數:

  • “block-migrate“:使用的話,做 block copy live migration;不使用的話,做共享存儲的 live migration;
  • ”disk_over_commit“:使用的話,計算所有磁盤的 disk_size 來計算目的 node 上所需空間的大小;不使用的話,則計算磁盤的 virtual size。在下面的例子中,如果使用 disk_over_commit,那么計算在目的主機上需要的空間的時候,該 disk 的 size 為 324k,否則為 1G:
root@compute1:/home/s1# qemu-img info /var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk.local
image: /var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk.local
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 324K
cluster_size: 65536
backing file: /var/lib/nova/instances/_base/ephemeral_1_default
Format specific information:
    compat: 1.1
    lazy refcounts: false

REST API request body 實例: {"os-migrateLive": {"disk_over_commit": false, "block_migration": true, "host": "compute2"}}

實時遷移的主要步驟如下:

其過程也可以分為三個階段:

3.2.1 實時遷移前的准備工作 (步驟 2 - 7)

Nova 通過 RPC 調用目的主機上 nova comute manager 的 pre_live_migration 方法,它依次:

(1)准備 instance 目錄:

      (1)創建 instance dir

(2)如果源和目的虛機不共享 instance path:獲取鏡像類型,為每一個disk,如果不使用 backing file 的話則調用 “qemu-img create” 方法來創建空的磁盤鏡像;否則,依次創建空的 Ephemeral disk 和 Swap disk,以及從  Glance 中獲取 image 來創建 Root disk

(3)如果不是 block migration 而且 不 is_shared_instance_path,則 _fetch_instance_kernel_ramdisk

(2)調用 volumer driver api 為每一個volume 建立目的主機和 volume 的連接

(3)調用 plug_vifs(instance, network_info) 將每一個 vif plug 到 OVS 上

(4)調用 network_api.setup_networks_on_host 方法,該方法會為遷移過來的虛機准備 dhcp 和 gateway;

(5)調用 libvirt driver 的 ensure_filtering_rules_for_instance 方法去准備 network filters。

3.2.2 調用 libvirt API 開始遷移虛機 (步驟 8 - 9)

  這部分的實現在 libvirt driver 代碼中。因為 libvirt 的一個 bug (說明在這里),當 libvirt 帶有 VIR_DOMAIN_XML_MIGRATABLE flag 時,Nova 會調用 libvirt 的 virDomainMigrateToURI2 API,否則調用 virDomainMigrateToURI API。

首先比較一下 block live migration 和 live migration 的 flags 的區別:

#nova block live migration flags:VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE, VIR_MIGRATE_TUNNELLED, VIR_MIGRATE_NON_SHARED_INC
#nova live migration flags:      VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE, VIR_MIGRATE_TUNNELLED    

各自的含義如下:

  • VIR_MIGRATE_UNDEFINE_SOURCE: 遷移完成后,將源虛機刪除掉。(If the migration is successful, undefine the domain on the source host.)
  • VIR_MIGRATE_PEER2PEER 和 VIR_MIGRATE_TUNNELLED 一起使用:點對點遷移,必須指定目的 URI,QEMU在兩者之間建立 TCP Tunnel 用於數據傳輸
  • VIR_MIGRATE_LIVE: 執行 live migration,不要停機 (Do not pause the VM during migration)
  • VIR_MIGRATE_NON_SHARED_INC: 使用非共享存儲式遷移即 block migration (Migration with non-shared storage with incremental disk copy)

再看看兩個 API 的參數:

int    virDomainMigrateToURI2        (virDomainPtr domain,
                     const char * dconnuri, # 格式為 qemu+tcp://<desthost>/system const char * miguri, #為 none const char * dxml, #指定遷移后的虛機的 XML。Nova 對 “/devices/graphics” 部分做了一點點更改。
                     unsigned long flags, # nova.conf 中的配置 const char * dname, #none
                     unsigned long bandwidth)  # 由 CONF.libvirt.live_migration_bandwidth 指定,默認為 0 表示由 libvirt 自己選擇合適的值

如果 libvirt 不帶 VIR_DOMAIN_XML_MIGRATABLE flag,則調用的 API 是:

int    virDomainMigrateToURI        (virDomainPtr domain,
                     const char * duri,
                     unsigned long flags,
                     const char * dname,
                     unsigned long bandwidth)

可見,兩個 API 唯一的區別是不能指定新的虛機使用的 XML 配置。這時候你必須手動配置 VNC 或者 SPICE 地址為 0.0.0.0 or :: (接收全部)或者 127.0.0.1 or ::1 (只限本機)。

調用 API 后,接下來就是等待其完成。這其中的過程應該主要包括:

(1)根據傳入的 domain xml,啟動一個虛機,它處於等待 TCP incoming 狀態

(2)從源 node 上將 domain 的數據傳過來

(3)快完成時,關閉源 node 上的虛機,傳輸最后一次數據,打開目的 node 上的虛機

(4)將源 node 上的虛機刪除

Nova 每個0.5 秒檢查源虛機的狀態,直到它被刪除。

遷移完成后,需要執行后續的操作(_post_live_migration)。

3.2.3 遷移完成后在源和目的主機上的后續操作(步驟 10 -29)

在源主機上,依次執行下面的操作:

  1. 調用 volume driver 的 disconnect_volume 方法和 terminate_connection 方法,斷開主機和所有 volume 的連接
  2. 調用 firewall driver 的 unfilter_instance 方法,刪除 domain 的 iptables 中的所有 security group ingress 規則 (self.iptables.ipv4['filter'].remove_chain(chain_name))
  3. 調用 network api 的 migrate_instance_start 方法,開始將網絡從源主機上遷移到目的主機上(實際上沒做什么事情,只是 pass)
  4. 調用 vif driver 的 unplug 方法,將每個 vif 從 OVS 上刪除                                                                                                                                      
    brctl delif qbr59cfa0b8-2f qvb59cfa0b8-2f 
    ip link set qbr59cfa0b8-2f down 
    brctl delbr qbr59cfa0b8-2f 
    ovs-vsctl --timeout=120 -- --if-exists del-port br-int qvo59cfa0b8-2f 
    ip link delete qvo59cfa0b8-2f
  5. 通過 RPC 調用目的主機上的 nova manager 的 post_live_migration_at_destination 方法,該方法會:
    1. 調用 network api 的 setup_networks_on_host 方法來設置網絡(處理 vpn,dhcp,gateway)
    2. 調用 network api 的 migrate_instance_finish 方法
    3. 調用 libvirt driver 的 post_live_migration_at_destination方法,它會調用 libvirt _conn.listDefinedDomains 方法查看遷移過來的主機的 domain是否存在;不存在的話,生成其 xml,然后調用 libvirt API  _conn.defineXML(xml) 去定義該 domain。
    4. 將新的 domain 數據更新到數據庫(包括新的 host,power_state,vm_state,node)
    5. 調用 network api 的 setup_networks_on_host 方法 (不理解為什么重復上面第1步)
  6. 調用 libvirt driver 的 driver.cleanup 方法去 _unplug_vifs (如果上面第四步失敗,則再次嘗試刪除所有 vif 相關的 bridge 和 OVS 連接),firewall_driver.unfilter_instance (和上面第2步重復了),_disconnect_volume(斷開 domain 和 所有 volume 的連接),_delete_instance_files (刪除 domain 相關的文件),_undefine_domain (刪除 domain)
  7. 調用 network_api.setup_networks_on_host 去 tear down networks on source host
  8. 至此,live migration 完全結束。

3.2.4 遷移過程中失敗時的回滾

 遷移的三個步驟中,前面第一個和第二個步驟中出現失敗的話,會調用 _rollback_live_migration 啟動回滾操作。該方法

(1)將虛機的狀態由 migrating 變為 running。

(2)調用 network_api.setup_networks_on_host 方法重做源主機上的網絡設置

(3)通過 RPC 調用,去目的主機上將准備過程中建立的 volume 連接刪除。

(4)通過 RPC 調用,去目的主機上調用 compute_rpcapi.rollback_live_migration_at_destination 函數,該方法會

(1)調用 network_api.setup_networks_on_host 方法去 tear down networks on destination host

(2)調用 libvirt driver 的 driver.rollback_live_migration_at_destination 方法,它會將 domain 刪除,並且清理它所使用的資源,包括  unplug vif,firewall_driver.unfilter_instance,_disconnect_volume, _delete_instance_files, _undefine_domain。

3.2.5 測試

環境:准備兩個虛機 vm1 和 vm2,操作系統為 cirros。打算將 vm1 遷移到另一個node 上。在 vm2 上查看 vm1 在遷移過程中的狀態。

遷移前:在 vm1 中運行 “ping vm2”,並在 vm2 中 ssh 連接到 vm1。

結果:vm1 遷移過程中,vm2 上 ssh 的連接沒有中斷,vm1 中的 ping 命令繼續執行。在另一次測試結果中,vm2 ping vm1 在整個遷移過程中 time 出現了一次 2ms 的時間增加。

3.3 遇到過的問題

3.3.1 apparmor

將虛機從 compute1 遷移到 compute2 成功,再從 compute2 遷移到 compute1 失敗,報錯如下:

An error occurred trying to live migrate. Falling back to legacy live migrate flow. Error: unsupported configuration: Unable to find security driver for label apparmor

經比較遷移前后的虛機的 xml,發現 compute2 上的虛機的 xml 多了一項:<seclabel type='none' model='apparmor'/> 。

分別在 compute 1 和 2 上運行 “virsh capabilities”,發現 compute1 沒有使用 apparmor,而 compute2 使用了 apparmor。

#compute 1<secmodel>
      <model>none</model>
      <doi>0</doi>
    </secmodel>

#compute2 上
    <secmodel>
      <model>apparmor</model>
      <doi>0</doi>
    </secmodel>

    最簡單的方法是在兩個 node 上都 disable apparmor(在 /etc/libvirt/qemu.conf 中添加 ‘security_driver = “none”  然后重啟 libvirtd),然后 destroy/start 虛機后,它的 xml 配置中的 apparmor 就沒有了。這篇文章 詳細介紹了 apparmor。

3.3.2 當虛機是 boot from volume 時,live migration 失敗。

報錯:

Command: iscsiadm -m node -T iqn.2010-10.org.openstack:volume-26446902-5a56-4c79-b839-a8e13a66dc7a -p 10.0.2.41:3260 --rescan
Exit code: 21
Stdout: u''
Stderr: u'iscsiadm: No session found.\n' to caller

原因是 cinder 代碼中有 bug,導致目的主機無法建立和 volume 的連接。fix 在這里

 

參考文檔:

https://www.mirantis.com/blog/tutorial-openstack-live-migration-with-kvm-hypervisor-and-nfs-shared-storage/

http://www.sebastien-han.fr/blog/2015/01/06/openstack-configure-vm-migrate-nova-ssh/

KVM 原理技術 實戰與原理解析 任永傑、單海濤著

OpenStack 官網

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM