【SPDK】一、概述

  随着越来越多公有云服务提供商采用SPDK技术作为其高性能云存储的核心技术之一,intel推出的SPDK技术备受业界关注。本篇博文就和大家一起探索SPDK。

什么是SPDK?为什么需要它?

  SPDK(全称Storage Performance Development Kit),提供了一整套工具和库,以实现高性能、扩展性强、全用户态的存储应用程序。它是继DPDK之后,intel在存储领域推出的又一项颠覆性技术,旨在大幅缩减存储IO栈的软件开销,从而提升存储性能,可以说它就是为了存储性能而生。

  为便于大家理解,我们先介绍一下SPDK在虚拟化场景下的使用方法,以给大家一些直观的认识。

1. DPDK的编译与安装

  SPDK使用了DPDK中一些通用的功能和机制,因此首先需要下载DPDK的源码并完成编译和安装:

[root@linux:~/DPDK]# make config T=x86_64-native-linuxapp-gcc
[root@linux:~/DPDK]# make
[root@linux:~/DPDK]# make install (默认安装到/usr/local,包括.a库文件和头文件)

2. SPDK的编译

[root@linux:~/SPDK]# ./configure –with-dpdk=/usr/local
[root@linux:~/SPDK]# make

  编译成功后,我们在spdk/app/vhost目录下可以看到一个名为vhost的可执行文件,它就是SPDK在虚拟化场景下为虚拟机模拟程序qemu提供的存储转发服务,借此为虚拟机用户带来高性能的虚拟磁盘。

3. 大页内存配置

  SPDK vhost进程和qemu进程通过大页共享虚拟机可见内存,因此需要进行一些大页的配置和调整:

  • 可通过设置/sys/kernel/mm/hugepages/hugepages-xxx/nr_hugepages来调整大页数量(xxx通常为2M或1G)
  • qemu使用挂载到/dev/hugepages目录下的hugetlbfs来使用大页内存,可在挂载参数中指定大页大小,如mount -t hugetlbfs -o pagesize=1G nodev /dev/hugepages

4. vhost配置与启动

[root@linux:~/SPDK]# HUGEMEM=4096 scripts/setup.sh
[root@linux:~/SPDK]# app/vhost/vhost -S /var/tmp -m 0x3 -c etc/spdk/rootw.conf

  vhost命令执行过程中,是一个常驻的服务进程;-S参数指定了socket文件的生成的目录,每个虚拟磁盘(vhost-blk)或虚拟存储控制器(vhost-scsi)都会在该目录下产生一个socket文件,以便qemu程序与vhost进程建立连接;-m参数指定了vhost进程中的轮循线程所绑定的物理CPU核,例如0x3代表在0号和1号核上各绑定一个轮循线程;-c参数指定了vhost进程所需的配置文件,例如这里我通过内存设备(SPDK中称之为Malloc设备)提供了一个vhost-blk磁盘:

[root@linux:~/SPDK]# cat etc/spdk/rootw.conf
[root@linux:~/SPDK]#
[Malloc]
NumberOfLuns 1 #创建一个内存设备,默认名称为Malloc0
LunSizeInMB 128 #该内存设备大小为128M
BlockSize 4096 #该内存设备块大小为4096字节
[VhostBlk0]
Name vhost.2 #创建一个vhost-blk设备,名称为vhost.2
Dev Malloc0 #该设备后端对应的物理设备为Malloc0
Cpumask 0x1 #将该设备绑定到0号核的轮循线程上

5. 虚拟机启动与验证

  vhost进程启动后,我们就可以拉起qemu进程来启动一个新虚拟机,qemu进程的命令行参数如下(重点关注与SPDK vhost相关部分):

[root@linux:~/qemu]# ./x86_64-softmmu/qemu-system-x86_64 -name rootw-vm -machine pc-i440fx-2.6,accel=kvm \
-m 1G -object memory-backend-file,id=mem,size=1G,mem-path=/dev/hugepages,share=on -numa node,memdev=mem \
-drive file=/mnt/centos.qcow2,format=qcow2,id=virtio-disk0,cache=none,aio=native -device virtio-blk-pci,drive=virtio-disk0,id=blk0 \
-chardev socket,id=char_rootw,path=/var/tmp/vhost.2 -device vhost-user-blk-pci,id=blk_rootw,chardev=char_rootw \
-vnc 0.0.0.0:0

  通过上述启动参数,我们可以看出:

  • vhost进程和qemu进程通过大页方式共享虚拟机可见的所有内存(原因我们将在深入分析时讨论)
  • qemu在配置vhost-user-blk-pci设备时,只需要指定vhost生成的socket文件即可(-S参数指定的路径后拼接上设备名称)

  虚拟机启动成功后,我们通过vnc工具登陆虚拟机,执行lsblk命令可以查看到vda和vdb两个virtio-blk块设备,表明vhost后端已成功生效。这里要说明一下,qemu中配置的virtio-blk-pci设备、vhost-user-blk-pci设备或vhost-blk-pci设备,在虚拟机内部均呈现为virtio-blk-pci设备,因此在虚拟机中采用相同的virtio-blk-pci和virtio-blk驱动进行使能,如此一来不同的后端实现技术在虚拟机内部均采用一套驱动,可以减少驱动的开发和维护工作量。

如何实现SPDK?

  SPDK能实现高性能,得益于以下三个关键技术:

  • 全用户态,它把所有必要的驱动全部移到了用户态,避免了系统调用的开销并真正实现内存零拷贝
  • 轮循模式,针对高速物理存储设备,采用轮循的方式而非中断通知方式判断请求完成,大大降低时延并减少性能波动
  • 无锁机制,在IO路径上避免采用任何锁机制进行同步,降低时延并提升吞吐量

  下面我们将深入到SPDK的实现细节,去看看这些关键点分别是如何提升性能的。

1. 整体架构

  首先,我们来了解一下SPDK内部的整体组件架构:

  SPDK整体分为三层:

  • 存储协议层(Storage Protocols),指SPDK支持存储应用类型。iSCSI Target对外提供iSCSI服务,用户可以将运行SPDK服务的主机当前标准的iSCSI存储设备来使用;vhost-scsi或vhost-blk对qemu提供后端存储服务,qemu可以基于SPDK提供的后端存储为虚拟机挂载virtio-scsi或virtio-blk磁盘;NVMF对外提供基于NVMe协议的存储服务端。注意,图中vhost-blk在spdk-18.04版本中已实现,后面我们主要基于此版本进行代码分析。
  • 存储服务层(Storage Services),该层实现了对块和文件的抽象。目前来说,SPDK主要在块层实现了QoS特性,这一层整体上还是非常薄的。
  • 驱动层(drivers),这一层实现了存储服务层定义的抽象接口,以对接不同的存储类型,如NVMe,RBD,virtio,aio等等。图中把驱动细分成两层,和块设备强相关的放到了存储服务层,而把和硬件强相关部分放到了驱动层。

2. 深入数据面

  接下来我们将以SPDK前端配置成vhost-blk、后端配置成NVMe SSD场景为例,来分析整个数据面流程。我们将分两部分完成数据面的分析:

3. 深入管理面

  管理面流程比数据面要复杂得多,也无趣得多。因此我们在分析完数据面流程之后,再回头看看数据面中涉及的各个对象分别是如何被创建和初始化的,这样更利于我们理解这样做的目的,也不会一下子就被这些复杂的流程吓住而无法坚持往下分析。

  整个管理面功能包含vhost启动初始化和通过rpc动态管理两个部分,这里我们主要讨化启动初始化,根据启动时的先后顺序,分为


转载请注明:吴斌的博客 » 【SPDK】一、概述