├── LICENSE
├── Makefile
├── README.md
├── README_en-us.md
├── debian
├── build.sh
├── control
├── postinst
├── preinst
└── prerm
├── kernel
├── Makefile
├── kiodump.c
├── kiodump.conf
└── kiodump.h
├── spec
├── distribution.spec
├── docker.spec
└── iodump.spec
└── user
├── Makefile
├── iodump.c
└── iodump.h
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alibaba Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | KERNELVER?=$(shell uname -r)
2 |
3 | default:
4 | make -C user
5 | make -C kernel
6 | clean:
7 | make -C user clean
8 | make -C kernel clean
9 | install:
10 | if [ $(id -u) -ne 0 ]; then { echo "root permission is required to install iodump";exit 0;} fi
11 | install -d /usr/lib/iodump/
12 | install kernel/kiodump.ko /usr/lib/iodump/kiodump.ko
13 | install -d /usr/src/os_health/iodump/
14 | install kernel/kiodump.conf /usr/src/os_health/iodump/kiodump.conf
15 | install user/iodump /usr/sbin/iodump
16 | ps h -C iodump -o pid && killall iodump || true
17 | if [ -e /sys/module/kiodump/parameters/enable ];then { echo N > /sys/module/kiodump/parameters/enable;} fi
18 | lsmod | grep -qw kiodump && modprobe -r kiodump || true
19 | if [ -e "/usr/lib/iodump/kiodump.ko" ];then \
20 | install -d /lib/modules/$(KERNELVER)/extra/os_health/iodump/;\
21 | install /usr/lib/iodump/kiodump.ko /lib/modules/$(KERNELVER)/extra/os_health/iodump/kiodump.ko;\
22 | /sbin/depmod -aeF /boot/System.map-$(KERNELVER) $(KERNELVER) > /dev/null;\
23 | modprobe kiodump;\
24 | if [ $$? -ne 0 ];then { echo "kiodump.ko modprobe is failed, check the dmesg info.";exit 0;} fi;\
25 | else\
26 | echo "The /usr/lib/iodump/kiodump.ko file does not exist in the iodump rpm package";\
27 | exit 0; \
28 | fi
29 | if [ -d /etc/modules-load.d/ ];then { install /usr/src/os_health/iodump/kiodump.conf /etc/modules-load.d/kiodump.conf;} fi
30 | uninstall:
31 | if [ $(id -u) -ne 0 ]; then { echo "root permission is required to uninstall iodump";exit 0;} fi
32 | ps h -C iodump -o pid && killall iodump || true
33 | if [ -e /sys/module/kiodump/parameters/enable ];then { echo N > /sys/module/kiodump/parameters/enable;} fi
34 | lsmod | grep -qw kiodump && modprobe -r kiodump || true
35 | rm -f /lib/modules/$(KERNELVER)/extra/os_health/iodump/kiodump.ko
36 | /sbin/depmod -aeF /boot/System.map-$(KERNELVER) $(KERNELVER) > /dev/null
37 | rm -f /etc/modules-load.d/kiodump.conf
38 | rm -fr /usr/lib/iodump/
39 | rm -fr /usr/src/os_health/iodump/
40 | rm -f /usr/sbin/iodump
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## iops dump使用手册
2 |
3 | [English](README_en-us.md) | 中文
4 |
5 | ## 目录
6 |
7 | - 一、[工具介绍](#工具介绍)
8 | - 二、[工具特点](#工具特点)
9 | - 三、[工具安装](#工具安装)
10 | - 3.1、[rpm包打包方法1](#rpm包打包方法1)
11 | - 3.2、[rpm包打包方法2](#rpm包打包方法2)
12 | - 3.3、[rpm包打包方法3](#rpm包打包方法3)
13 | - 3.4、[deb包打包方法](#deb包打包方法)
14 | - 3.5、[源代码编译安装](#源代码编译安装)
15 | - 四、[使用说明](#使用说明)
16 | - 4.1、[基本使用](#基本使用)
17 | - 4.2、[参数说明](#参数说明)
18 | - 4.3、[长期测试](#长期测试)
19 | - 五、[输出说明](#输出说明)
20 | - 六、[结果有效性](#结果有效性)
21 | - 6.1、[数据有效性](#数据有效性)
22 | - 6.2、[跟踪点的正确选择](#跟踪点的正确选择)
23 | - 6.3、[再谈数据有效性](#再谈数据有效性)
24 | - 七、[使用案例](#使用案例)
25 | - 7.1、[诊断磁盘io打满](#诊断磁盘io打满)
26 | - 7.2、[内存颠簸型磁盘io打满](#内存颠簸型磁盘io打满)
27 | - 7.3、[诊断元数据io](#诊断元数据io)
28 | - 7.4、[写类型的元数据io](#写类型的元数据io)
29 | - 7.5、[获取元数据io的文件信息](#获取元数据io的文件信息)
30 | - 7.6、[读类型的元数据io](#读类型的元数据io)
31 | - 7.7、[写系统调用触发元数据读io](#写系统调用触发元数据读io)
32 | - 7.8、[存储io的双峰模式](#存储io的双峰模式)
33 | - 八、[性能开销](#性能开销)
34 | - 九、[许可证](#许可证)
35 | - 十、[技术交流](#技术交流)
36 |
37 |
38 |
39 |
40 |
41 | ## 一、工具介绍
42 |
43 | iops dump工具是利用内核tracepoint静态探针点技术实现的一个io问题排查工具。通过iops dump工具,我们可以获取每一个IOPS(w/s和r/s)的详细信息,不仅包括IO请求的size大小,还包括IO请求的扇区地址,同时还包含IO请求的发生时间、读写的文件全路径、产生IO请求的进程、产生IO请求的系统调用和扩展IO类型等信息。这其中最具有特色的就是读写的文件全路径功能。为了便于向大家介绍iops dump工具,下文将我们简称其为iodump。
44 |
45 |
46 |
47 | ## 二、工具特点
48 |
49 | 当我们要排查操作系统磁盘IO问题时,可以使用iostat扩展命令进行具体分析。当iostat工具显示此时磁盘IO并发很高,磁盘使用率接近饱和时,还需要依赖更多的工具进一步查看影响磁盘IO使用率高的进程信息和读写文件信息。
50 |
51 | 常见的工具或者方法有iotop、blktrace、ftrace和block_dump等。实际使用中,它们都有各种不足:
52 | - iotop工具,可以细化到进程带宽信息,但缺乏进程级的IOPS信息,也没有对应的磁盘分区信息。
53 | - blktrace工具,功能强大,但使用较复杂。获取sector信息后,进一步通过debugfs等其他方式解析文件路径也比较低效。
54 | - ftrace工具,当跟踪块设备层静态探针点时,功能和blktrace工具类似,也需要通过debugfs等工具进一步解析文件路径。当跟踪文件系统层探针点函数时,无法精确对应IOPS数量。
55 | - block_dump工具,也同样存在以上ftrace工具的2个不足。
56 |
57 | **相比其他磁盘io类工具,iodump有如下几个特色优势** :
58 | 1. 支持自定义选择blk层探针点函数。
59 | 2. 支持自定义输出字段信息,包括时间、进程名、进程ID、IO大小、扇区地址、磁盘分区、读写类型、扩展IO类型、IO来源、Inode号,文件全路径。
60 | 3. 当采集进程异常退出后,支持内核态自动关闭探针。
61 | 4. 支持从2.6.32以上的各内核版本。
62 | 5. 当IOPS高时,支持抽样输出。
63 |
64 | iodump功能虽然强大,但iodump本质上采用的是加载内核模块方式实现,可能会引起操作系统crash,请在重要的生产环境使用前,提前进行充分测试。从计算平台的实际使用情况,未发生生产环境宕机。
65 |
66 |
67 |
68 | ## 三、工具安装
69 |
70 | 工具的安装,有如下几种方法:
71 |
72 |
73 |
74 | ### 3.1、rpm包打包方法1
75 |
76 | rpm包的打包方法如下,本方法适用于AnolisOS and CentOS等操作系统环境。
77 |
78 | ```bash
79 | $ yum install rpm-build rpmdevtools git
80 | $ cd /tmp/ # work dir
81 | $ git clone https://gitee.com/anolis/iodump.git
82 | $ rpmdev-setuptree
83 | $ tar -zcvf ~/rpmbuild/SOURCES/iodump-$(cat iodump/spec/iodump.spec |grep Version |awk '{print $2}').tar.gz iodump
84 | $ cp iodump/spec/iodump.spec ~/rpmbuild/SPECS/
85 | $ rpmbuild -bb ~/rpmbuild/SPECS/iodump.spec
86 | $ cd ~/rpmbuild/RPMS/x86_64/
87 | $ sudo rpm -ivh $(ls)
88 | $ sudo rpm -e iodump-$(uname -r) # remove package
89 | ```
90 |
91 | iodump工具本质上是内核驱动模块,在一个特定内核版本上生成的rpm包在另外一个不同的内核版本上是不能正常工作的。在这里我们将内核版本信息加入到rpm包的name部分,用以识别不同内核版本的rpm包。这里我们推荐使用如下rpm的查询命令区分一个rpm包的name、version、release和arch四个部分的内容。我们使用连续的3横线来区隔不同的部分,结果一目了然。
92 |
93 | ```bash
94 | $ rpm -qp iodump-4.19.91-24.8-1.0.1-1.an8.x86_64.rpm --queryformat="%{name}---%{version}---%{release}---%{arch}\n"
95 | iodump-4.19.91-24.8---1.0.1---1.an8---x86_64
96 | ```
97 |
98 | 使用这个方法打rpm,默认会依赖当前机器上默认第一个kernel-devel包。如果想指定版本的kernel-devel包,可以使用如下rpmbuild命令通过宏参数传入内核版本信息。
99 |
100 | ```bash
101 | $ rpmbuild -bb ~/rpmbuild/SPECS/iodump.spec --define "%kver $(uname -r)"
102 | $ rpmbuild -bb ~/rpmbuild/SPECS/iodump.spec --define "%kver 4.19.91-24.8.an8.x86_64"
103 | ```
104 |
105 |
106 |
107 | ### 3.2、rpm包打包方法2
108 |
109 | 有些情况下,在一个发行版下面,迭代了很多版本的内核,本方法适用于这种场景。
110 |
111 | 这里以Anolis 8为例,有Anolis8.2、8.4和8.6等多个小的发行版本,每个小版本也分别对应了不同的内核版本。
112 |
113 | > Release Kernel Version
114 |
115 | > 8.2 ANCK 64位 4.19.91-25.8.an8.x86_64
116 |
117 | > 8.4 ANCK 64位 4.19.91-26.an8.x86_64
118 |
119 | > 8.6 ANCK 64位 4.19.91-26.1.an8.x86_64
120 |
121 | 此时,新版本的gcc版本通常也更新,会对低版本向下兼容。因此,我们选择最新版本Anolis8.6作为打包机。并且安装上所有需要支持的内核版本对应的kernel-devel的rpm包。
122 |
123 | > Release Kernel-devel
124 |
125 | > 8.2 ANCK 64位 kernel-devel-4.19.91-25.8.an8.x86_64
126 |
127 | > 8.4 ANCK 64位 kernel-devel-4.19.91-26.an8.x86_64
128 |
129 | > 8.6 ANCK 64位 kernel-devel-4.19.91-26.1.an8.x86_64
130 |
131 | 相关版本的kernel-devel包,我们推荐在阿里巴巴开源镜像站进行搜索查找并下载。
132 |
133 | > https://developer.aliyun.com/packageSearch
134 |
135 | 具体打包方案如下:
136 |
137 | ```bash
138 | $ rpm -ivh --force kernel-devel-4.19.91-25.8.an8.x86_64.rpm kernel-devel-4.19.91-26.an8.x86_64.rpm
139 | $ yum install rpm-build rpmdevtools git
140 | $ cd /tmp/ # work dir
141 | $ git clone https://gitee.com/anolis/iodump.git
142 | $ rpmdev-setuptree
143 | $ tar -zcvf ~/rpmbuild/SOURCES/iodump-$(cat iodump/spec/distribution.spec |grep Version |awk '{print $2}').tar.gz iodump
144 | $ cp iodump/spec/distribution.spec ~/rpmbuild/SPECS/
145 | $ rpmbuild -bb ~/rpmbuild/SPECS/distribution.spec
146 | $ cd ~/rpmbuild/RPMS/x86_64/
147 | $ rpm -qpl $(ls) | grep kiodump # display all version kiodump
148 | $ sudo rpm -ivh $(ls)
149 | $ sudo rpm -e iodump # remove package
150 | ```
151 |
152 |
153 |
154 | ### 3.3、rpm包打包方法3
155 |
156 | 在一些大型互联网公司,会在低版本发行版上使用较高版本内核的情况。比如centos7的原装内核版本是3.10,但是为了支持业务需求,在centos7的发行版上将内核升级为更高版本,如4.18内核。本方法适用于这种场景
157 |
158 | 这里以centos7为例,假设这里当前某公司同时使用了6个版本的内核,分别是3.10.0-1062、3.10.0-1127、3.10.0-1160、4.18.0-240、4.18.0-305和4.18.0-348。我们需要基于centos7发行版,制作2个docker镜像。
159 |
160 | 第一个docker镜像中包含3个3.10内核版本,需要安装如下软件包,命名为image-centos7。
161 |
162 | ```bash
163 | $ yum install rpm-build
164 | $ rpm -ivh --force kernel-devel-3.10.0-1062.el7.x86_64.rpm kernel-devel-3.10.0-1127.el7.x86_64.rpm kernel-devel-3.10.0-1160.el7.x86_64.rpm
165 | ```
166 |
167 | 第二个docker镜像中包含3个4.18内核版本,需要安装如下软件包,命名为image-centos8。
168 |
169 | ```bash
170 | $ yum install rpm-build
171 | $ rpm -ivh --force kernel-devel-4.18.0-240.el8.x86_64.rpm kernel-devel-4.18.0-305.el8.x86_64.rpm kernel-devel-4.18.0-348.el8.x86_64.rpm
172 | $ rpm -Uvh gcc-8.5.0-4.el8_5.x86_64.rpm # 具体需要升级的gcc相关rpm包参考公司内部资料
173 | ```
174 |
175 | 然后,具体打包方案如下:
176 |
177 | ```bash
178 | $ yum install rpmdevtools git docker
179 | $ rpmdev-setuptree
180 | $ cd ~/
181 | $ git clone https://gitee.com/anolis/iodump.git
182 | $ tar -zcvf ~/rpmbuild/SOURCES/iodump-$(cat iodump/spec/docker.spec |grep Version |awk '{print $2}').tar.gz iodump
183 | $ cp iodump/spec/docker.spec ~/rpmbuild/SPECS/
184 | $ docker run --net=host -u root -v ~/rpmbuild:/root/rpmbuild -w /root/rpmbuild -it image-centos8 /bin/bash -c "rpmbuild -bb /root/rpmbuild/SPECS/docker.spec"
185 | $ docker run --net=host -u root -v ~/rpmbuild:/root/rpmbuild -w /root/rpmbuild -it image-centos7 /bin/bash -c "rpmbuild -bb /root/rpmbuild/SPECS/docker.spec"
186 | $ rm -fr ~/rpmbuild/SPECS/kiodump/ # clear kiodump.ko
187 | $ cd ~/rpmbuild/RPMS/x86_64/
188 | $ rpm -qpl iodump-*.an8.x86_64.rpm | grep kiodump # display all version kiodump
189 | $ sudo rpm -ivh iodump-*.an8.x86_64.rpm
190 | $ sudo rpm -e iodump # remove package
191 | ```
192 |
193 |
194 |
195 | ### 3.4、deb包打包方法
196 |
197 | deb包的打包方法如下,本方法适用于Ubuntu等操作系统环境。
198 |
199 | ```bash
200 | $ apt-get update
201 | $ apt install git
202 | $ cd ~/
203 | $ git clone https://gitee.com/anolis/iodump.git
204 | $ cd iodump/debian
205 | $ ./build.sh
206 | $ dpkg -i iodump-4.4.0-87-generic_1.0.1-1_amd64.deb
207 | $ dpkg -r iodump-4.4.0-87-generic # remove package
208 | ```
209 |
210 |
211 |
212 | ### 3.5、源代码编译安装
213 |
214 | 源代码安装方法。
215 |
216 | ```bash
217 | $ cd ~/
218 | $ git clone https://gitee.com/anolis/iodump.git
219 | $ cd iodump
220 | $ make
221 | $ sudo make install
222 | $ sudo make uninstall # remove
223 | ```
224 |
225 |
226 |
227 | ## 四、使用说明
228 |
229 |
230 |
231 | ### 4.1、基本使用
232 |
233 | 基本运命命令如下。并且运行时需要使用sudo进行提权。
234 |
235 | ```bash
236 | $ sudo iodump -p sda
237 | ```
238 |
239 | 结束运行iodump,可以在运行过程中直接使用键盘的ctrl+c的组合,或在另外一个终端运行如下命令。
240 |
241 | ```bash
242 | $ sudo killall iodump
243 | $ sudo killall -9 iodump
244 | ```
245 |
246 | 当向iodump进程发送SIGHUP、SIGINT和SIGTERM等信号时,用户态的iodump进程会在退出前向内核模块发送关闭内核跟踪的消息。但是,当向iodump进程发送-9,即SIGKILL信号时,用户态进程iodump将强制退出,无法向内核模块发送关闭内核跟踪的消息。此时,kiodump内核模块会在用户态iodump进程异常退出后,自动关闭内核跟踪开关。其它的blktrace等工具并没有此功能。
247 |
248 |
249 |
250 | ### 4.2、参数说明
251 |
252 | 为了完整的了解使用方法,我们可以查看帮助信息。
253 |
254 | ```bash
255 | $ iodump -h
256 |
257 | Usage: iodump [OPTIONS]
258 |
259 | Summary: this is a io tools. it can dump the details of struct request or struct bio.
260 |
261 | Options:
262 | -h Get the help information.
263 | -H Hiding header information.
264 | -a Set blk tracepoint action which is fully compatible with blktrace, default G, See Actions.
265 | -o Set the output field, such as datetime,comm,pid, See Formats.
266 | -p Set partition parameter, this option is necessary.
267 | -s Set saving output to the file. if not set, it will output to standard output.
268 | -t