文/ 李光水:系统运维SIG核心成员、 毛文安:系统运维SIG负责人。

一、 需求背景
二、现有工具
在定位问题这类问题的过程中,我们会通过系统的现有工具,定位具体的进程、文件或者容器,然后采取下一步措施解决问题,如停掉进程、容器并查看问题现象是否消失。一般地,如下几类工具会使用比较频繁:
基于内核 diskstats 衍生的工具,如 iostat、sar-类命令的IO统计功能、vmstat-d
——可以宏观的从整个磁盘角度去统计 io 信息,如统计整盘的 iops、bps
基于内核 proc/$pid/io 衍生的工具,如 pidstat -d
——可以统计到进程贡献的总体IO
基于 Taskstats 衍生的工具,如 iotop
——可以统计到进程贡献的总体 IO 以及贡献的 iowait
尽管系统为我们提供了比较丰富的工具,但总有这样一种感觉:使用已有的命令,尽管知道磁盘的 IO 高了,但不知道是哪个进程贡献的;知道系统里面的某个进程贡献的 IO 高了,但又不确定这里有多少 IO 是被我关心的磁盘给消费的,也不知道这些 IO 都是在操作什么文件,总觉得哪哪都差一点儿。所以总结下来,得到如下几点诉求:
● 在磁盘 IO 被打满的情况下,希望观察是哪个进程贡献了比较多的 IO
● 系统上统计到某个进程贡献了大量的 IO,希望观察到这些 IO 最终是被哪个磁盘给消费,或者这些 IO 是在访问哪个文件,如果这个进程是来自某个容器,希望依然可以获取访问的文件以及此进程所在的容器
而本文所介绍的
iofsstat
,实现了从进程角度来统计 IO 信息、文件读写信息,满足了之前提到的几个诉求,可以应用到 io utils 高、io 打满类问题的定位中。
三、
iofsstat 功
能
介绍
3.1 统计指定磁盘的进程文件 IO
主要统计某进程对某文件贡献了多少
IO,对用户呈现的指标为进程角度+磁盘角度,磁盘角度这个毋庸置疑是为了能够看到磁盘的全貌,进程角度,是更细粒度的,可以看到对应的在这个时刻,各进程的贡献情况(PS:这里并非进程贡献的总和要等于磁盘整体的统计,因为统计的原理不一致,这里可以更多的关注两个角度之间的关联性,如在某一时刻,磁盘统计到高了,这个时候可以看到对应的这个时刻的各个进程的贡献程度),各指标如下:
进程角度:
comm:进程名、 pid:进程id、cnt_rd:读文件次数、bw_rd:读文件"带宽"、cnt_wr:写文件次数、bw_wr :写文件"带宽"、inode:文件inode编号、filepath:文件路径,当在一次采集周期内由于进程访问文件很快结束情况下,获取不到文件名则为"-"。
如进程来自某个容器,在文件名后缀会显示 [containterId:xxxxxx]
磁盘角度:
xxx-stat:r_iops:磁盘总的读 iops、 xxx-stat:w_iops:磁盘总的写 iops、xxx-stat:r_bps:磁盘总的读 bps、xxx-stat:w_bps:磁盘总的写 bps、xxx-stat:wait:磁盘平均 io 延迟、xxx-stat:r_wait:磁盘平均读 io 延迟、xxx-stat:w_wait:磁盘平均写 io 延迟、xxx-stat:util%:磁盘 io utils
sysak iofsstat -d vdb1 --fs 1 #间隔1秒统计一次vdb磁盘上的进程读写文件情况 2022/01/19 14:13:48 vda-stat: r_iops w_iops r_bps w_bps wait r_wait w_wait util% 0.00 98.00 0.00 91.5MB/s 946.34 0.00 946.34 93.20 comm pid cnt_rd bw_rd cnt_wr bw_wr inode filepath dd 55937 0 0 1096 137.0MB/s 9226 /home/data/tfatsf ...

3.1.1 进程、磁盘、文件信息

实际上满足功能的需求,只需要获取进程信息、IO 大小、dev 编号、文件 inode 编号就够了,而在文件系统层没有现成的符合这些需求的 tracepoint,因此考虑通过 kprobe_events 去 hook 特定函数;kprobe_events
又绕不开因为不同内核版本,数据结构会不一致,造成输入到 kprobe_events 的表达式不一致的问题,幸运的是因为 surftrace 已经帮我们解决了这个问题,我们只需要关注 kprobe 之后数据的解析,而无需关注表达式的变化。
3.1.2 如何获取文件路径
通过 3.1.1 已经获取文件 inode 编号,通过 find -inum 指定磁盘的挂载目录,或者通过 debugfs 方式,获取到文件名,但这种方式不仅耗时间也可能会耗 io;因为已经获取到了进程信息,接下来可以在 /proc/$pid/fd 过滤出来属于指定磁盘下的文件,然后比对文件的 inode 即可获取文件名,简单高效,但缺点是当比对文件过程中文件访问结束被 close 掉了,就获取不到文件名了,但这种情况一般在有问题的情况下出现概率也很低(一般关注的 IO 打满问题基本持续时间也都是秒级别)。
3.2 统计指定磁盘的进程IO贡献
主要统计某进程对某磁盘贡献了多少 IO,对用户呈现的指标为进程角度+磁盘角度,磁盘角度这个毋庸置疑是为了能够看到磁盘的全貌,进程角度,是更细粒度的,可以看到对应的在这个时刻,各进程的贡献情况(PS:这里并非进程贡献的总和要等于磁盘整体的统计,因为统计的原理不一致,这里可以更多的关注两个角度之间的关联性,如在某一时刻,磁盘统计到高了,这个时候可以看到对应的这个时刻的各个进程的贡献程度),各指标如下:
进程角度:
comm:进程名、pid:进程 id、 iops_rd:进程贡献的读 iops、bps_rd :进程贡献的读bps、iops_wr:进程贡献的写iops、bps_wr :进程贡献的写bps。
磁盘角度:
同 3.1 节磁盘角度。
sysak iofsstat -d vdb 1 #间隔1秒统计一次vdb磁盘上的进程io贡献情况 2022/01/19 12:04:38vda-stat: r_iops w_iops r_bps w_bps wait r_wait w_wait util% 0.00 118.00 0.00 104.2MB/s 976.82 0.00 976.82 95.60 comm pid iops_rd bps_rd iops_wr bps_wr [dd] 98675 1 4.0KB/s 259 32.4MB/s [kworker/u12:0] 91022 1 4.0KB/s 198 167.5MB/s [jbd2/vdb1-8] 19510 0 0 1 4.0KB/s ...
四、性能开销
五、代码开源
iofsstat 代码将在 3 月中旬开源,敬请期待。
加入微信群:添加社区助理-龙蜥社区小龙(微信:openanolis_assis),备注【龙蜥】与你同在;加入钉钉群:扫描下方钉钉群二维码。欢迎开发者/用户加入龙蜥社区(OpenAnolis)交流,共同推进龙蜥社区的发展,一起打造一个活跃的、健康的开源操作系统生态!

龙蜥社区( OpenAnolis)是由 企事业单位、高等院校、科研单位、非营利性组织、个人等在自愿、平等、开源、协作的基础上组成的非盈利性开源社区。龙蜥社区成立于 2020 年 9 月,旨在构建一个开源、中立、开放的Linux 上游发行版社区及创新平台。
龙蜥社区成立的短期目标是开发龙蜥操作系统( Anolis OS)作为 CentOS 停服后的应对方案,构建一个兼容国际 Linux 主流厂商的社区发行版。中长期目标是探索打造一个面向未来的操作系统,建立统一的开源操作系统生态,孵化创新开源项目,繁荣开源生态。
目前, 龙蜥OS 8.4 已发布,支持 X86_64 、Arm64、LoongArch 架构,完善适配飞腾、海光、兆芯、鲲鹏、龙芯等芯片,并提供全栈国密支持。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70004278/viewspace-2855169/ ,如需转载,请注明出处,否则将追究法律责任。