虚拟机迁移

 

 

如果源宿主机和目的宿主机共享存储系统,则只需要通过网络发送客户机的 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:显示迁移进度

 

 

virsh migrate --live virtual01 --copy-storage-inc  qemu+tcp://192.168.136.96/system tcp://192.168.136.96  --verbose --persistent  --p2p

 

 

 

 

libvirt 启用远程连接

(1)SSH方式

使用最简单的SSH方式,只要拥有SSH连接到服务器的权限,就可以无需配置:

qemu+ssh://root@example.com/system

例如: qemu+ssh://root@172.16.0.12/system ,本机SSH连接到172.16.0.12时,要使用证书登录,否则每次连接都需要输入SSH用户名和密码。

(2)TCP方式:

qemu+tcp://example.com/system

例如:qemu+tcp://172.16.0.15/system,服务端只需要做简单配置即可:

vim /etc/libvirt/libvirtd.conf:

listen_tls = 0          #禁用tls登录
listen_tcp = 1          #启用tcp方式登录
tcp_port = "16509"       #tcp端口16509
listen_addr = "0.0.0.0"
unix_sock_group = "libvirtd"
unix_sock_rw_perms = "0770"
auth_unix_ro = "none"
auth_unix_rw = "none"
auth_tcp = "none"       #TCP不使用认证
max_clients = 1024       #最大总的连接客户数1024
min_workers = 50       #libvirtd启动时,初始的工作线程数目
max_workers = 200       #同上,最大数目
max_requests = 1000      #最大同时支持的RPC调用,必须大于等于max_workers
max_client_requests = 200   #每个客户端支持的最大连接数

 

同时修改libvirt-bin的配置文件:

有的在 /etc/sysconfig/libvirtd

 

 

改成:

 

 

 

 

或者:

vim /etc/default/libvirt-bin:

# Start libvirtd to handle qemu/kvm:
start_libvirtd="yes"

# options passed to libvirtd, add "-l" to listen on tcp
libvirtd_opts="-d -l --config /etc/libvirt/libvirtd.conf"

 

以上修改后,执行service libvirt-bin restart即可。 netstat -anpt就能看到libvirtd监听在TCP 16509端口

 netstat -tlnp 

前端 linux下开启libvirtd的tcp监控

 


使用 virsh 连接到别的服务器时,使用的是 tcp 连接

virsh -c qemu+tcp://host/system

如果目标服务器没有开启 libvirtd 的 tcp 端口监听时,会出现

error: unable to connect to server at 'host:16509': Connection refused
error: failed to connect to the hypervisor

ubuntu 下解决方法

sed -i 's/#listen_tls = 0/listen_tls = 0/g' /etc/libvirt/libvirtd.conf
sed -i 's/#listen_tcp = 1/listen_tcp = 1/g' /etc/libvirt/libvirtd.conf
sed -i 's/#auth_tcp = "sasl"/auth_tcp = "none"/g' /etc/libvirt/libvirtd.conf

vi /etc/default/libvirt-bin
修改为libvirt_opts = "-d -l"  
增加-l监听tcp

service libvirt-bin restart

centos 下解决方法

sed -i 's/#listen_tls = 0/listen_tls = 0/g' /etc/libvirt/libvirtd.conf
sed -i 's/#listen_tcp = 1/listen_tcp = 1/g' /etc/libvirt/libvirtd.conf
sed -i 's/#auth_tcp = "sasl"/auth_tcp = "none"/g' /etc/libvirt/libvirtd.conf
sed -i 's/#LIBVIRTD_ARGS="--listen"/LIBVIRTD_ARGS="--listen"/g' /etc/sysconfig/libvirtd

service libvirtd restart

 

api

使用libvirt控制KVM虚拟机进行热迁移,这里记录一下migrate方法的使用


import libvirt
import pprint
conn_004 = libvirt.open(‘qemu+tcp://username@server004/system’)
conn_005 = libvirt.open(‘qemu+tcp://username@server005/system’)
vm_domain = conn_004.lookupByName(‘instance_name’)
vm_domain.migrate(conn_005,True,’instance_name’,None,0)
pprint.pprint(help(vm_domain.migrate))
下面是程序的输出,也就是migrate接口的说明

 

IBM example:

virsh --keepalive-interval 10 migrate --live --persistent --undefinesource  --timeout 1200 --verbose vserv1 qemu+ssh://kvmhost/system

virsh migrate --live --auto-converge --timeout 300 vserv3 qemu+ssh://zhost/system

virsh migrate --live --auto-converge --timeout 300 --undefinesource --persistent  vserv3 qemu+ssh://zhost/system

发现有问题:

 

 

 

 

网卡名字需要相同

 

 

 

/etc/hosts

 

 

 

 

 这个是防火墙没有开

第二个是 没有相同名字的磁盘 qcow2

 

 

 qemu版本相差太大

 

 

kvm  与 qemu-kvm

 

 

 

 

 小版本差别。添加xml解决 网卡问题

 

 qemu-kvm --version

qemu-img -V

 

kvm --version

libvirtd --version

 

171:

 

 

 

 

 

 

 

其他遇到问题:https://www.iteye.com/blog/liuzhijun-1744236

为什么要迁移呢?当一台主机的负载过高时,我们希望把虚拟机迁移到一台系统更好的主机上。当主机发生硬件故障需要停机维护时,我们需要迁移虚拟机,如果主机就只跑了一台虚拟机我们可以把它迁移到其他主机,提高资源的利用率,等等。

 
迁移命令:
# virsh migrate --live GuestName DestinationURI   (--live :迁移过程中虚拟机一直保持运行状态)
GuestName指虚拟机名称,DestinationURI:目的主机的URI。
举例:# virsh  migrate --live vm0 qemu+tcp://192.168.0.200/system
迁移的要求是:需要目的主机和源主机有相同的环境,包括hypervisor
 
注意点:
笔者在做迁移的时候,所有前置条件都一配置好,执行迁移命令:
sudo virsh migrate --live vm0 qemu+tcp://192.168.1.200/system
却出现的如下错误:
error: Unable to resolve address 'ubuntu1204' service '49152': No address associated with hostname
笔者的系统环境是Ubuntu,错误中‘ubuntu1204’是192.168.1.200的主机名,对此错误很是不解,说是‘ubuntu1204’无法解析,查得资料:http://wiki.libvirt.org/page/Migration_fails_with_%22Unable_to_resolve_address%22_error
在迁移的过程中,运行在目的主机中的libvirtd进程要根据address和port创建一个URI,URI是目的主机用来接收数据和发回数据到源主机的libvirtd进程的。上面的错误的原因是libvirtd没法解析主机名到IP地址。可以看下图:
目的主机libvirtd在发回数据的时候,把hostname发回去了,而源主机就用直接请求hostname而非IP,恰巧在源主机没有做DNS配置,因此才出现次错误。
如果是在REHEL系列的Linux中出现的错误如所示:Migration fails with "Unable to resolve address" error
 
解决方案一:
配置source源主机的 /etc/hosts文件:加入"192.168.1.200 ubnuntu1204"  参考:http://bbs.openzj.com/thread-7200-1-1.html
 
解决方案二:
# virsh migrate vm0 qemu+tcp://192.168.1.200/system tcp://192.168.1.200
这时目的主机libvirtd进程将使用“tcp://192.168.1.200“作为迁移连接,libvirt会自动生成的端口追加到此URI后面,(这里相当于开启另外一个连接来迁移数据,可以和方案三对比之)当然也可以手动指定端口号如:
# virsh migrate vm0 qemu+tcp://192.168.1.200/system tcp://192.168.1.200 12345
 
解决方案三:使用隧道(tunnelled) 迁移,该方式不会为迁移创建单独的连接,而是通过与目的libvirtd通信的这个连接来传输数据。(例如连接:qemu+tcp://192.168.1.200/system)
# virsh migrate vm0 qemu+tcp://192.168.1.200/system  --p2p --tunnelled
 

 

问题解决了,顺便学习下libvirt migrate的概念:

 
说到虚拟机的迁移,其实就是数据的转移,数据的转移就涉及数据的传输,数据的传输需要通过网络。libvirt提供了两种方案。
 
hypervisor native transport:
“本地”数据传输,相当于一种手动方式做的迁移。数据是否可以加密取决于hypervisor自身是否已实现。
Migration native path
 
libvirt tunnelled transport
隧道化的(tunnelled)数据传输支持很强的加密功能,这要归结于libvirt的RPC协议。不好的一方面是数据会在hypervisor和libvirtd之间的传输。
Migration tunnel path
迁移时的通信控制:(此景会有一个第三方的管理程序来管理,上面所说单纯是从两个主机直接的角度来说的)
 
虚拟机的迁移需要两个主机之间的密切协调,同时应用程序(虚拟机管理平台)也将参与进来,此应用可以是在源主机、目的主机、甚至是第三台主机。
 
受管理的直接迁移(Managed direct migration):
直接管理迁移,libvirt客户端进程控制迁移的不同阶段。客户端应用程序必须连接以及获得在源主机和目的主机的libvirtd进程的认证。无需两个libvirtd进程间相互通信。如果客户端应用崩溃了,或者在迁移过程中失去了链接,一种办法就是强制终止迁移,重启源主机的guest CPU。
Migration direct, managed
管理的点对点迁移:(Managed peer to peer migrate)
对于点对点,libvirt客户端程序只是与在源主机的libvirtd进程通信,源主机libvirtd进程自己控制整个迁移的过程,直接连接到目的主机的libvirtd。如果客户端应用崩溃了或者与libvirtd失去连接,迁移过程无需中断直至迁移完成。需要注意的是源主机认证(通常是root)链接到目的主机,而不是通过客户端应用链接到源主机。
 
Migration peer-to-peer
不受管理的直接迁移:(Unmanaged direct migrate)
此迁移方式既不受libvirt客户端控制,也不受libvirtd控制,迁移的控制过程委托给基于hypervisor之上的管理服务来处理。libvirt 客户只需要通过hypervisor的管理层做一下初始化。不管是libvirt 客户端还是libvirtd崩溃了,迁移还是会照样进行直至完成。
 
Migration direct, unmanaged
 
迁移URI:
虚拟机迁移时,客户端应用程序需要准备的URI可达三个,具体取决于控制流如何选择或者API如何调用。第一个URI就是应用程序到运行着虚拟机的源主机的连接,第二个URI就是目的主机到应用程序之间的连接(在点对点的迁移中,这个连接是来自源主机,而不是客户端应用程序)。第三个URI就是hypervisor指定的用来控制以何种方式迁移的连接。在任何一种受管理的迁移中,前两个URI是必不可少的,第三个是可选的。而在不受管理的直接迁移中,第一个和第三个是必须的,第二个并不会使用。
 
 
通常管理应用程序只需关心前两个URI。二者都是普通的libvirt 连接URI格式。libvirt会通过查找目的主机的配置文件中的hostname自动确定hypervisor指定的URI(第三个URI)。
 
应用程序获取第三个URI时可能会出现的如下几种情况:
1、hostname的配置不正确,或者DNS不正确,如果主机的hostname不能正确的解析到IP地址的化就会生成一个错误的URI,这刚好时文章开头出现的问题。此时需要明确指定IP地址或者使用正确的hostname。
2、主机有多个网络接口,此时需要用IP明确指定来关联某个具体的网卡。
3、防火墙限制端口的使用,当libvirt自动生扯功能的端口需要防火墙对其端口是开放的。
 
 
 
参考:
 

https://blog.csdn.net/wan_hust/article/details/33793987:

之前一直以为KVM虚拟机迁移需要共享存储,虚拟机的镜像放到共享存储中,迁移的过程相当于启动一个监听虚拟机,将内存数据copy到目标服务器上,然后销毁source上的虚拟机,启动target上的机器。

废话不多说,直入正题(被迁移的机器成为:vmtest,所在服务器:source,目标服务器:target,#后是shell命令)
实验环境:
RedHat 6.2
# virsh version
Compiled against library: libvir 0.9.4
Using library: libvir 0.9.4
Using API: QEMU 0.9.4
Running hypervisor: QEMU 0.12.1

主要用两种方式,命令行virsh migrate 
命令行比较简单:
#virsh migrate vmtest qemu+ssh://target/system --live --storage-all

 

我们也可以用tcp代替ssh连接到目标服务器上,很多管理工具(webvirt)也是使用的tcp作为连接的方式。

 

 

在目的宿主机创建2个空的qcow2文件,路径、文件名以及大小必须与原虚拟机一致

qemu-img create -f qcow2 -o preallocation=metadata kylin.qcow2 20G

 

virsh migrate --live --copy-storage-all   --persistent –unsafe instance-1 qemu+ssh://root@compute02/system

 virsh migrate --live --copy-storage-all   --persistent –unsafe 

 

七、virsh migrate命令帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# virsh migrate --help
[--domain] <string> 域名,id 或 uuid
[--desturi] <string> 客户端(常规迁移)或者源(p2p 迁移)中看到到目的地主机连接 URI
--live 热迁移
--offline 离线迁移
--p2p 点对点迁移
--direct 直接迁移
--tunnelled 管道迁移
--persistent 目的地中的持久 VM
--undefinesource 在源中取消定义 VM
--suspend 部启用目的地主机中的域
--copy-storage-all 使用全磁盘复制的非共享存储进行迁移
--copy-storage-inc 使用增值复制(源和目的地共享同一基础映像)的非共享存储进行迁移
--change-protection 迁移结束前不得对域进行任何配置更改
--unsafe 即使不安全也要强制迁移
--verbose 显示迁移进程
--compressed 实时迁移过程中压缩重复的页
--auto-converge force convergence during live migration
--rdma-pin-all support memory pinning during RDMA live migration
--abort-on-error 在迁移过程中忽略软错误
--migrateuri <string> 迁移 URI, 通常可省略
--graphicsuri <string> 无空隙图形迁移中使用的图形 URI
--listen-address <string> listen address that destination should bind to for incoming migration
--dname <string> 在迁移过长中重新命名为一个新名称(如果支持)
--timeout <number> 如果 live 迁移超时(以秒计)则强制虚拟机挂起
--xml <string> 包含为目标更新的 XML 的文件名
--migrate-disks <string> comma separated list of disks to be migrated

八、 常见错误:

       1、迁移时遇到的错误描述:

1
2
# virsh migrate centos ­­live qemu+ssh://192.168.30.132/system
error: unable to connect to server at 'KVM­2:49152': No route to host

        原因:你的免密登录没有成功

              解决方法:重新做免密登录即可

       2、迁移时的存储错误:

1
2
# virsh migrate centos ­­live qemu+ssh://192.168.30.132/system
error: Failed to open file '/mnt/CentOS6.8.qcow2': Input/output error

          原因:存储没有挂载成功

               解决方法:mount -­o remount /dev/sdb /mnt

        3、迁移时FQDN错误:

1
2
# virsh migrate centos ­­live qemu+ssh://192.168.30.132/system
error: internal error hostname on destination resolved to localhost, but migration requires an FQDN

         原因:两台宿主机无法解析主机名

              解决方法:重新配置主机名和ip的解析

       4.迁移时语法错误:

1
2
# virsh migrate centos ­­live qemu+ssh://192.168.30.132:/system
error: internal error Unable to parse URI qemu+ssh://192.168.30.132:/system

       原因:qemu+ssh语法写错了 解 决 方 法 :

            正 确 的 应 该 是 : virsh migrate centos ­­live qemu+ssh://192.168.30.132/system

 

主机之间的客人迁移是一个复杂的问题,有许多可能的解决方案,每个解决方案都有自己的优点和缺点。为了最大限度地提高管理程序集成和管理员部署的灵活性,libvirt 实现了多个迁移选项。

网络数据传输

迁移期间使用的数据传输有两种选择,一种是管理程序自己的本机传输,另一种是通过 libvirtd 连接进行隧道传输。

管理程序本机传输

本机数据传输可能支持也可能不支持加密,具体取决于所讨论的虚拟机管理程序,但通常通过最小化所涉及的数据副本的数量来具有最低的计算成本。本地数据传输还需要管理员在部署主机时执行额外的特定于管理程序的网络配置步骤。对于某些虚拟机管理程序,可能需要在防火墙上开放大量端口以允许多个并发迁移操作。

现代虚拟机管理程序支持 TLS 用于迁移连接的加密和身份验证,可以使用VIR_MIGRATE_TLS标志启用。qemu管理程序驱动程序允许用户通过/etc/libvirt/qemu.conf中配置的 migrate_tls_force 旋钮强制使用 TLS 

迁移本机路径

libvirt 隧道传输

隧道数据传输将始终能够进行强加密,因为它们能够利用 libvirt RPC 协议中内置的功能。然而,隧道传输的缺点是,当数据在 libvirtd 和虚拟机管理程序之间移动时,源主机和目标主机都会涉及额外的数据副本。对于具有非常大 RAM 的客户机来说,这可能是一个更严重的问题,这会很快弄脏内存页面。在部署方面,隧道传输不需要任何额外的网络配置,超出一般 libvirtd 远程访问所需的配置,并且只需要在防火墙上打开一个端口即可支持多个并发迁移操作。

注意:使用 libvirt 的隧道时,某些功能,例如非共享存储迁移 ( VIR_MIGRATE_NON_SHARED_DISK )、多连接迁移 ( VIR_MIGRATE_PARALLEL ) 或复制后迁移 ( VIR_MIGRATE_POSTCOPY ) 可能不可用。

迁移隧道路径

 

 

 

 

热迁移:

1. mkdir hgh 

2. chmod 777 hgh 

3. qemu-img create -f qcow2 ubuntu-server.qcow2 20G  //是否必须

4.获取网卡 修改网卡,获取路径

5.修改xml文件 ,修改 网卡与路径。

6.修改  /etc/hosts  添加ip name

5 .

 

 

 

 

 

 

 

 

 需要添加用户名

 

 

 

或者获取存储池

virsh pool-list 

virsh pool-dumpxml default > default.xml

 

note:

cpu相同  个数相同 。 host-passthrough

macvtap0

macvtap1

网卡mac 修改

target 相同

 

pci mac地址

slot  以及bus都相同

 

如果在60-net.rules ,71-biosdevname.rules这两条规则中没有重命名网卡,且内核指定net.ifnames=1参数,则udev依次尝试使用以下属性值来命名网卡,如果这些属性值都没有,则网卡不会被重命名。

ID_NET_NAME_ONBOARD

ID_NET_NAME_SLOT

ID_NET_NAME_PATH

上边的71-biosdevname.rules 是实际执行biosdevname的策略

以及host
参考:https://blog.csdn.net/hzj_001/article/details/81587824

 

 

go调用 libvirt api

https://libvirt.org/html/libvirt-libvirt-domain.html#virDommainMigrate2

https://libvirt.org/docs.html

 

 virsh edit 10

 

 

 

vi 的时候

target 不同

alias 不同。

运行时候:

 

 

 

遇到问题:
https://patchwork.kernel.org/project/qemu-devel/patch/20170811164854.GG4162@localhost.localdomain/

'nbd-server-add': Block node is read-only

 

 

 qemu-img -V

4.0.1

 

 

 

 

 

 

 

 

 

 

参考:

https://blog.csdn.net/LEoe_/article/details/78740088

https://www.cnblogs.com/sammyliu/p/4572287.html

https://blog.csdn.net/qiongtianliuyun/article/details/109205169

https://blog.csdn.net/x_i_y_u_e/article/details/45223157

https://blog.csdn.net/weiyuanke/article/details/8020657

 https://www.dazhuanlan.com/reenigne/topics/1813118

https://blog.csdn.net/x_i_y_u_e/article/details/45223157

https://www.ibm.com/docs/en/linux-on-systems?topic=migration-migrate   IBM

https://blog.csdn.net/wan_hust/article/details/33793987

https://www.iteye.com/blog/liuzhijun-1744236

http://t.zoukankan.com/mo-xiao-tong-p-12877030.html

https://libvirt.org/migration.html#id14

posted @   redrobot  阅读(1612)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示