# 热迁移虚拟机
<!-- TOC -->
-   [热迁移虚拟机](#热迁移虚拟机)
    -   [总体介绍](#总体介绍)
    -   [应用场景](#应用场景)
    -   [注意事项和约束限制](#注意事项和约束限制)
    -   [热迁移操作](#热迁移操作)

<!-- /TOC -->

## 总体介绍

### 概述

当虚拟机在物理机上运行时，物理机可能存在资源分配不均，造成负载过重或过轻的情况。另外，物理机存在硬件更换、软件升级、组网调整、故障处理等操作，如何在不中断业务的情况下完成这些操作十分重要。虚拟机热迁移技术可以在业务连续前提下，完成负载均衡或上述操作，提升用户体验和工作效率。虚拟机热迁移通常是将整个虚拟机的运行状态完整保存下来，同时可以快速恢复到原有的甚至不同的硬件平台上。虚拟机恢复后，仍然可以平滑运行，用户感知不到任何差异。根据虚拟机数据存储在当前主机还是远端存储设备（共享存储）的不同，openEuler支持共享存储热迁移和非共享存储热迁移两种方式。

### 应用场景

共享存储和非共享存储热迁移的共同应用场景有：

-   当物理机故障或者负载过重时，可以将运行的虚拟机迁移到另一台物理机上，以避免业务中断，保证业务的正常运行。
-   当多数的物理机负载过轻时，可以将虚拟机迁移整合，以减少物理机数量，提高资源的利用率。
-   当物理服务器硬件设备成为瓶颈，比如CPU、内存、硬盘等，需要更换性能更好的硬件，或者需要增加设备，但是又不能关闭虚拟机或者停止业务。
-   服务器软件升级，比如虚拟化平台升级，就可以把虚拟机从旧版本虚拟化平台热迁移到新版本虚拟化平台。

对于非共享存储热迁移，还可以应用在如下场景：

-   当物理机故障存储空间不足，需要将运行的虚拟机迁移到另一台物理机上，可以避免业务中断，保证业务的正常运行。
-   当物理机存储设备老化，性能不能支撑当前业务数据处理，成为系统性能的瓶颈，需要更换性能更强的存储，但是又不能关闭虚拟机或者停止虚拟机，这需要将运行的虚拟机迁移到一个具有更好性能的物理机上。

### 注意事项和约束限制

-   热迁移过程中，需要保证网络状态良好。如果发生网络中断，热迁移会暂停，直到网络恢复后才会继续，当发生超时，热迁移会失败。
-   迁移过程中，不允许对虚拟机进行生命周期和管理虚拟机硬件设备等操作。
-   虚拟机正在迁移的过程中，应尽可能保证源端、目的端服务器不被意外下电或重启，否则会导致热迁移失败，甚至可能导致虚拟机被下电。
-   虚拟机正在迁移的过程中，不允许对虚拟机做关机、重启或恢复操作，否则可能会导致热迁移失败，当执行ACPI方式重启时，再执行热迁移会导致虚拟机关闭。

-   只支持同构热迁移，即源端和目的端CPU型号需要相同。
-   跨业务网段虚拟机迁移可以成功，但是到目的端后会出现网络异常，为了防止该情况发生，需要用户保证迁移业务网段一致。
-   如果源端虚拟机vCPU数大于目的端的物理机CPU核数，则迁移后将会影响到虚拟机的性能，应保证目的端物理机CPU核数大于等于源端虚拟机vCPU数。

非共享存储热迁移过程中的额外注意事项：

-   不支持迁移源端和目的端为同一个磁盘镜像文件的迁移，用户需要对该类迁移进行特殊处理，提防覆盖写坏数据而导致镜像损坏。
-   不支持对共享磁盘的迁移，用户需要对该类迁移进行防呆处理。
-   迁移的目的端镜像只支持文件，不支持裸设备，用户需要对目的端是裸设备的迁移进行防呆处理。
-   目的端需要创建与源端大小、数量相同的磁盘镜像，否则迁移失败。
-   混合迁移场景，需要传入迁移的磁盘，不能包括共享和只读的磁盘。

## 热迁移操作

### 前提条件

-   进行热迁移之前要确保源端和目的端主机之间的网络是互通的，并且源端和目的获得资源权限是对等的，即两端同时能够访问到相同的存储资源和网络资源。

-   在执行虚拟机热迁移前应当对虚拟机进行健康检查，并确保目的端主机有足够的CPU、内存和存储资源。

### 设置热迁移参数（可选）

在执行热迁移之前，可以通过使用 virsh migrate-setmaxdowntime命令来指定虚拟机热迁移过程中能够容忍的最大停机时间，这是一个可选的配置项。

例如，指定名为_openEulerVM_的虚拟机最大停机时间为500ms：

```
# virsh migrate-setmaxdowntime openEulerVM 500
```

同时，可以通过调用virsh migrate-setspeed来限制虚拟机热迁移占用的带宽大小，防止当前虚拟机热迁移的时候占用带宽过大，对主机上的其他虚拟机或者业务造成影响，这个选择同样也是热迁移的一个可选项。

例如，指定名为_openEulerVM_的虚拟机热迁带宽为500Mbps：

```
# virsh migrate-setspeed openEulerVM --bandwidth 500
```

用户可以使用migrate-getspeed来查询虚拟机热迁移过程中的最大带宽。

```
# virsh migrate-getspeed openEulerVM
500
```

### 热迁移操作（共享存储场景）

1.  确认是否为共享存储。

    ```
    # virsh domblklist <VMInstanse>
     Target   Source
    --------------------------------------------
    sda      /dev/mapper/open_euleros_disk
    sdb      /mnt/nfs/images/openeuler-test.qcow2
    ```

    首先，使用virsh domblklist命令查询虚拟机的存储设备信息，例如上面的查询结果显示虚拟机配置有2个存储设备：sda盘和sdb盘，然后再分别查询一下这两个设备对应后端存储是本地存储还是远端存储，如果虚拟机的所有存储设备都在远端共享存储之上，则说明该虚拟机为共享存储虚拟机，否则为非共享存储虚拟机。

2.  执行如下命令，进行虚拟机热迁移。

    例如，将虚拟机_openEulerVM_迁移到目的主机上使用virsh migrate命令。

    ```
    # virsh migrate --live --unsafe openEulerVM qemu+ssh://<destination-host-ip>/system
    ```

    其中，<destination-host-ip\>为目的主机IP地址，热迁移之前需要进行ssh认证以获取目的端主机管理源权限。

    另外，virsh migrate命令还有--auto-converge和--timeout子选项来保证迁移的顺利完成。

    其中，相关子选项：

    --unsafe命令会强制进行热迁移，忽略安全检查步骤。

    --auto-converge命令会对CPU进行降频限速，确保热迁移流程能够收敛。

    --timeout选项会指定一个热迁移超时时间，热迁移超过指定时间后会强制挂起虚拟机让热迁移得以收敛。

3.  热迁移完成后命令返回，虚拟机在目的端主机正常运行。

### 热迁移操作（非共享存储场景）

1.  首先，先查询虚拟机存储设备列表，确保虚拟机使用的是非共享存储。

    例如，通过virsh domblklist查询到准备迁移的虚拟机有一个qcow2格式的磁盘sda，sda的xml配置为：

    ```
        <disk type='file' device='disk'>
          <driver name='qemu' type='qcow2' cache='none' io='native'/>
          <source file='/mnt/sdb/openeuler/openEulerVM.qcow2'/>
          <target dev='sda' bus='scsi'/>
          <address type='drive' controller='0' bus='0' target='0' unit='0'/>
        </disk>
    ```

    执行热迁移之前需要在目的端主机相同磁盘目录下创建一个虚拟磁盘文件，注意磁盘的格式和大小必须保持一致。

    ```
    # qemu-img create -f qcow2 /mnt/sdb/openeuler/openEulerVM.qcow2 20G
    ```

2.  在源端使用virsh migrate命令来执行热迁移，迁移的时候会将存储也一并迁移到目的端。

    ```
    # virsh migrate --live  --unsafe --copy-storage-all --migrate-disks sda \
    openEulerVM qemu+ssh://<dest-host-ip>/system
    ```

3.  热迁移完成后命令返回，虚拟机在目的端主机行正常运行，存储设备也被迁移到目的主机上。

