作者简介:刘长鹏,Intel 软件工程师,主要从事SPDK开发维护工作,现在担任SPDK Core Maintainer。
文章转载自DPDK与SPDK开源社区
SPDK Vhost Target主要用来加速Guest IO处理,在实际使用中,Live Migration是一个比较常见的使用场景,下面我们来看下SPDK vhost是如何支持Live Migration的。
大家应该对vhost的架构有一定的了解,SPDK vhost target负责Guest IO的高速卸载,实现Guest到SPDK slave target间端到端的数据zero copy处理。QEMU仅负责设备的模拟,所以这里对存储的迁移是基于共享存储环境来讲的,比如客户可以使用Ceph提供的共享存储卷分配给源VM和目的VM。因为在Vhost架构中,QEMU并不负责Guest IO的处理,当收到迁移命令时,QEMU无法知道Guest所使用的块设备,哪些区域是脏数据,所以这里的迁移是指在IO运行过程中,在Vhost target端存在的脏队列状态和未完成的IO,QEMU Vhost驱动和SPDK Vhost Target需要配合把这些状态迁移到目的VM,当然已经完成并持久化在共享存储中的数据并不需要迁移(block migration)。
Vhost架构使用available ring和used ring来和Guest进行数据交换,在迁移时,脏数据的信息包括:available/used ring本身,used ring中未得到Guest Ack的IO请求描述符以及所指向的数据,另外ring中用来标识新请求/响应元素位置的index。有了以上信息,在迁移到目的VM后,所有的脏数据(如果存在)请求在目的VM会被重新执行。
为了更详细的说明这个问题,我们按照一个最坏场景来模拟迁移流程,实际测试中这个场景并没有出现,即使加大了fio的workload。
上图展示了IO运行过程中的一个场景,available的idx由Guest负责更新,last_avail_idx由SPDK vhost target负责维护,这2个值不相等表示available有未完成的IO请求,这里最新的请求ID是8;used ring的idx和last_used_idx由SPDK vhost target负责维护,当这2个值不相等时,代表IO已经完成,但是还没有通知到Guest,在热迁移发生时,last_used_idx由QEMU获取并保存,在目的VM中,由last_used_idx来恢复available ring的last_avail_idx,这个场景迁移到目的VM后,last_avail_idx的值就变为了4,那么在目的VM中,last_avail_idx 4到 idx 8之间的请求会被重新下发。
下面以vhost-blk为例,我们详细列一下迁移中的命令操作,为了便于展示,我们在同一台物理机不同的端口间进行迁移:
1.启动SPDK vhost-blk,创建两个vhost-blk controller,这两个controller共享相同的一个块设备(模拟共享存储),rpc命令操作如下:
1 2 |
$rpc construct_vhost_blk_controller vhost.0 Nvme0n1 $rpc construct_vhost_blk_controller vhost.1 Nvme0n1 |
这里的两个char socket文件分别是vhost.0 和 vhost.1,即代表这两个vhost-blk控制器。
2.启动源VM,部分命令参数如下:
1 |
-chardev socket,id=char0,path=/path/vhost.0 -device vhost-user-blk-pci,id=block0,chardev=char0 monitor telnet::1111,server,nowait |
3.启动目的VM,部分命令参数如下:
1 |
-chardev socket,id=char0,path=/path/vhost.1 -device vhost-user-blk-pci,id=block0,chardev=char0 -incoming tcp:0:2222 |
4.登录源VM,启动fio randwrite,并且使能数据verify选项,这里可以运行较长时间,在迁移完成后,我们需要在目的VM中查看该fio任务。
5.telnet 0 1111,输入migrate_set_speed 1g和migrate tcp:0:2222触发迁移。
6.登录到目的VM,查看之前启动的fio 任务,fio没有中断并且数据校验没有报错,说明此次迁移成功,当然用户可以启动vnc使用图形界面同时查看这两个VM的终端运行结果,可以更直观的观察到迁移过程。