作者简介:周雁波,Intel 存储软件工程师,主要从事SPDK软件开发工作;刘孝冬,Intel 存储软件工程师 ,主要从事SPDK以及ISA-L软件开发工作
文章转载自DPDK与SPDK开源社区
众所周知,SPDK采用用户态驱动,设备不再受内核的管制。因此,我们无法在系统上直接看到SPDK管制下的设备,从而使一些常用的相关设备工具无法使用。例如:fio,iostat,nvme-cli等等。为此SPDK团队开发了一系列的工具,配合SPDK来使用,从而达到和内核模式下同样的功能。此篇文章将向大家介绍SPDK生态工具中的监控管理工具。
sysstat/iostat
通过使用sysstat中的iostat工具,可以实时查看各种设备的活动情况和负载信息。例如IOPS,带宽,平均每次设备I/O等待时间等等。因此iostat在实际的应用场景下,可以帮助运维以及开发者实时掌握设备的各种情况,从而进行管理。在内核模式下,内核通过将系统中各个设备的I/O状态记录到内存文件系统/proc中,用户态工具iostat通过/proc文件系统与内核交互,从而获得相应的设备I/O信息,并进行计算得到最后的实时状态。
在SPDK所管理的设备当中,每个I/O都会通过spdk_bdev_channel下发到相应的设备中,SPDK在进行每个I/O操作的时候,都会将本次I/O信息记录在结构spdk_bdev_io_stat中。并提供相应的public函数接口以及其RPC调用,使用户能够及时获取到这些信息。因此,iostat可以通过SPDK所提供的RPC接口,向SPDK应用程序发送RPC请求,SPDK以JSON的形式返回当前状态下设备的I/O状态信息,从而使得iostat可以实时获取所需要的I/O统计信息,并且进行相应的计算,得到最后的结果。
iostat的使用方法较为简单,如下:
1 |
iostat [options] [<interval>] [<count>] |
通过iostat –help可以查看所有的参数信息,通常经常用到的一个参数为-x, 其表示显示扩展信息。下面我们以一个命令来解释iostat的输出信息,例如:
1 |
iostat –m –x 1 |
-m表示输出以megabytes为单位,-x表示输出扩展信息,1代表每隔一秒刷新一次。输出结果中,会列出每个设备的相关信息,下面我们来详细介绍:
- rrqm/s:每秒读请求被Merge的个数。
- wrqm/s:每秒写请求被Merge的个数。
- r/s:每秒读操作个数。
- w/s:每秒写操作个数。
- rMB/s:每秒读取的字节数。
- wMB/s:每秒写入的字节数。
- avgrq-sz:每个IO的平均扇区数
- avgqu-sz:平均请求队列的长度。
- await:每一个IO请求的平均时间。包括在队列的等待时间以及处理请求的服务时间。
- r_wait:每个读操作的平均时间,包括在队列的等待时间以及处理请求的服务时间。
- w_wait: 每个写操作的平均时间,包括在队列的等待时间以及处理请求的服务时间。
- svctm:表示平均每次设备I/O操作的服务时间,其中不包括等待时间。
- %util: 工作时间所占的百分比。该指标可以直观地反映出设备的繁忙程度。
nvme-cli
nvme-cli 是一个用于监控和配置管理NVMe设备的命令行工具,目前被运维及开发者广泛使用。加载Linux内核驱动后,NVMe控制器在设备模型中是字符设备,例如 /dev/nvme0; NVMe 的namespace是块设备,例如 /dev/nvme0n1。nvme-cli运行在Linux用户态下,通过内核驱动定义的IOCTL接口在NVMe字符设备和块设备上执行相关命令。
nvme-cli的典型执行方式是:
1 |
# nvme <command></command> [] [] |
其中按照命令的不同,可以分别指定为NVMe字符设备或块设备。
nvme-cli能够支持多样化的命令。在NVMe标准协议所定义的命令中,nvme-cli不仅能够支持admin命令,而且还可以执行IO命令。nvme-cli也支持不同制造商的特定命令,比如Intel, 华为,Memblaze等。
nvme-cli的常见用法有:
- 通过list 命令查看当前系统中的所有NVMe namespace;
- 通过 id-ctrl 和id-ns来获取NVMe 控制器和Namespace的相关信息;
- 通过show-regs来查看设备PCIe寄存器信息;
- 通过log相关的命令,获取控制器的各类日志记录;
- 通过ns系列管理命令,动态添加或删除NVMe设备的Namespace;
- 通过format命令来设置NVMe设备中namespace 的数据块格式。
除此之外,nvme-cli也是NVMf host 端的配置工具。通过nvme discover 可以列举可用的NVMf 子系统; 通过nvme connect 以及 nvme disconnect 可以连接或断开NVMf子系统。
为使用户能够依旧通过nvme-cli管理和监控SPDK 环境下的NVMe设备,SPDK提供了SPDK版本的nvme-cli。目前,SPDK 版nvme-cli通过多进程共享内存的方式工作。它的使用方式与常规的nvme-cli相同,只是设备名不再是/dev/nvmeX或/dev/nvmeXnY, 而是以PCI地址 (domain:bus:device.function)作为设备名。通过nvme list 可以获取SPDK环境下各个NVMe设备的PCI地址。
RPC
SPDK实现了一个JSON-RPC 2.0的服务,以允许外部的管理工具动态的配置SPDK,或监控工具动态的获取SPDK的运行状态。目前,JSON-RPC是SPDK最主要的监控管理工具,SPDK中包含的各个组件均有一些相应的RPC方法供使用者调用。未来,SPDK会丰富更多的RPC方法,来增加SPDK的灵活性,并减少对静态配置的依赖。
使用SPDK的RPC需要首先在SPDK的应用启动时使用“-r”参数指定RPC server的监听地址,默认地址为“/var/tmp/spdk.sock”。
使用SPDK提供的client端命令行工具“scripts/rpc.py”,可以方便的向SPDK server端发起RPC调用。它的使用方法如下:
1 |
rpc.py [-h] [-s SERVER_ADDR] [-p PORT] [-v]<command></command> [parameters list] |
其中,“-s”“-p”参数指定SPDK RPC server端的监听地址和端口;“command”“parameters list” 指定具体的RPC命令和对应的参数。
获取当前SPDK RPC所能支持的command可以通过以下命令获得:
1 |
rpc.py -h |
获取command命令所需的对应参数可以通过命令获得:
1 |
rpc.py <command></command> -h |
例如:
1 2 3 4 5 |
# ./scripts/rpc.py delete_bdev -h usage: rpc.py delete_bdev [-h] bdev_name positional arguments: bdev_name Blockdev name to be deleted. Example: Malloc0. |
执行delete_bdev RPC 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#./scripts/rpc.py -v delete_bdev "Nvme1n1" request: { "params": { "name": "Nvme1n1" }, "jsonrpc": "2.0", "method": "delete_bdev", "id": 1 } response: { "jsonrpc": "2.0", "id": 1, "result": true } |
如下图, 当一个SPDK RPC客户端发出RPC调用请求后,RPC Poller在轮询过程中,accept该连接请求。接收该连接上客户端发出的请求内容,并解析为Json请求。在SPDK中已经注册的所有RPC 方法中,通过逐个对比后,找出对应的方法函数并执行进入。在RPC的方法函数中,首先将Json请求解析成函数执行过程中需要的参数,完成相应的功能。完成功能后,根据需要填写JSON响应,并将它加入到发送队列。RPC Poller在轮询过程中,将该JSON响应发送给SPDK RPC客户端。
SPDK中JSON-RPC所依赖的代码主要分布在四个部分: lib/rpc; lib/jsonrpc; lib/json; 以及各个组件中以rpc结尾的C文件。它们的作用分别为:
- lib/jsonrpc
接收发送网络数据,解析和流化JSON请求 - lib/rpc
将JSON-RPC适配到SPDK 编程框架中 - lib/json
具体的数据流与JSON结构的解析与流化方法 - <module>_rpc.c
定义并注册具体的SPDK RPC方法
因此,用户也可以根据自己的需求,来添加自己的RPC调用。
总结
目前,SPDK被越来越广泛地应用到各个实际的应用场景中,相应的反馈和需求越来越多,相应的工具开发也提上了日程。在不久后的将来,SPDK会推出更多相应的生态工具,打造更加完备的用户态生态系统。