41

SPDK Vhost对Live Migration的支持

 5 years ago
source link: https://www.sdnlab.com/22438.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者简介:刘长鹏,Intel 软件工程师,主要从事SPDK开发维护工作,现在担任SPDK Core Maintainer。

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。

%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20180930104635.jpg

上图展示了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命令操作如下:

Java
$rpc construct_vhost_blk_controller vhost.0 Nvme0n1 $rpc construct_vhost_blk_controller vhost.1 Nvme0n1
1
2
$rpc construct_vhost_blk_controller vhost.0Nvme0n1
$rpc construct_vhost_blk_controller vhost.1Nvme0n1

这里的两个char socket文件分别是vhost.0 和 vhost.1,即代表这两个vhost-blk控制器。

2.启动源VM,部分命令参数如下:

Java
-chardev socket,id=char0,path=/path/vhost.0 -device vhost-user-blk-pci,id=block0,chardev=char0 monitor telnet::1111,server,nowait
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,部分命令参数如下:

Java
-chardev socket,id=char0,path=/path/vhost.1 -device vhost-user-blk-pci,id=block0,chardev=char0 -incoming tcp:0:2222
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的终端运行结果,可以更直观的观察到迁移过程。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK