とあるサーバで慢性的に悩まされている io wait. 死ぬほど重くなく、調査できる状態で発生したのでこれはチャンスと言うことで調査した。その方法を記録。
io wait トラブルシューティング
Troubleshooting High I/O Wait in Linux | Benjamin Cane
The reason I/O Wait is difficult to troubleshoot is due to the fact that by default there are plenty of tools to tell you that your system is I/O bound, but not as many that can narrow the problem to a specific process or processes.
このページが素敵だった。コマンドをメモ。
★のコマンドが素敵なやつ。
# io waitが全体でどれくらいあるのかわかる
top
# io waitが起こってるdiskがどれかわかる。(HDDが1つしかなければたぶん意味ない)
iostat -x 2 5
# io waitを起こしているprocessがわかる(が、dockerdって言われても意味なし)
iotop
# ★kernelからsleepしてろや、って言われてるprocessを表示!
ps -eo state,pid,cmd | grep "^D"
# プロセスのr/wスピードを表示
cat /proc/$PID/io
# ★プロセスが書き込んでるファイル名を表示
lsof -p $PID
# ディレクトリがどのdiskに属するのか(disk 1つなら意味なし)
df 書込み対象ディレクトリ
# disk groupを表示(lvmしてなければ意味ないかな)
pvdisplay
まず iotopが役立たず ということを確信できたのがよかった。
$ iotop
dockerdの中にいるprocess名が知りたいんですよこっちは。せめてdocker-containerdを出してくれればtree表示にぶら下がるんだけど。
同様にdiskが1つしかないため iostatも役立たず。
素敵だったのは ps -eo
コマンド
ps -eo state,pid,cmd | grep "^D"
# 2sおきに更新
watch -n2 "ps -eo state,pid,cmd | grep '^D'"
kernelによって待ちにされてる?プロセスがわかる。見事にこれで特定できました。
しかし解決はしなかった・・・
D
になってしまったプロセスは kill -SIGKILL
しても死なない...。
この場合rebootするか待つしかないそうだ。
process - What if 'kill -9' does not work? - Unix & Linux Stack Exchange
However kill -9 is not guaranteed to work immediately. All signals, including SIGKILL, are delivered asynchronously: the kernel may take its time to deliver them
・・・2h待ってもio waitは下がらず。rebootしかないのか...もう少し待ってみるか・・・ → 結局rebootしました
重いprocessを探す
別事象。Load averageが死ぬほどおそいサーバがあった
[root@zzz:~]# top
top - 18:22:32 up 522 days, 21:48, 7 users, load average: 84.00, 84.03, 84.02
psコマンドも途中で止まってしまう。
途中で止まるコマンドがある場合は、strace
コマンドを使うとどこで止まっているかわかったりする。
[root@zzz:~]# strace ps -ef
...
...
stat("/proc/61428", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/61428/stat", O_RDONLY) = 6
read(6, "61428 (java) D 101527 101527 101"..., 2048) = 335
close(6) = 0
open("/proc/61428/status", O_RDONLY) = 6
read(6, "Name:\tjava\nUmask:\t0022\nState:\tD "..., 2048) = 1154
close(6) = 0
open("/proc/61428/cmdline", O_RDONLY) = 6
read(6, <--------ここから返ってこない
このjava process 61428 がいかんのやろうなぁ、みたいな。
topに プロセスごとのr/w
を表示できる方法
おまけ
hard drive - Linux disk IO load breakdown, by filesystem path and/or process? - Server Fault
yum install -y htop
htop
F5 (Tree view)
F2 (Setup)
Select columns
Select RBYTES WBYTES
F10 (Done)
>> 
# まとめ
自分が知りたかったのは **io waitが高いプロセス** というよりも、**kernelに待たされているプロセス** だったのかもしれない(r/wのbyte数見てもさっぱりわからないし)。
**/proc/$PID/io** を見るくだりもLinuxの基礎知識があれば自然と思いつくところ。週末のLPIC 101、がんばるぞー。