こんにちは、インフラエンジニアのryuです。
監視のアラートで、こんな通知を受け取ったことはないでしょうか。
「ロードアベレージが閾値を超えました」。慌ててサーバーにログインして top を見ると、CPU使用率は20%程度。どのプロセスも、たいしてCPUを使っていないように見えます。
では、あの高い数字は何だったのでしょうか。
ロードアベレージは、Linuxでいちばん有名な指標のひとつです。そのわりに、何を数えているのかを正確に説明できる人は意外と少ない数字でもあります。
今日は、ロードアベレージの正体を押さえたうえで、数字が高いときにどこを見れば原因にたどり着けるのかを、コマンドの組み合わせで追いかけていきます。
そもそもロードアベレージは何を数えているのか?¶
まずは、数字がどこに出ているかを確認しておきましょう。いちばん手軽なのは uptime です。
$ uptime
10:15:02 up 12 days, 3:41, 2 users, load average: 6.12, 3.08, 1.45
末尾の3つの数字が、ロードアベレージです。左から順に、直近1分・5分・15分の平均を表しています。
uptime のマニュアルには、次のように書かれています。
System load averages is the average number of processes that are either in a runnable or uninterruptable state. (ロードアベレージは、実行可能な状態か、割り込み不可能な状態にあるプロセスの平均数である)
ここが最初のポイントです。Linuxのロードアベレージは、CPUを使っている・使いたいプロセスに加えて、I/Oを待って動けないプロセスも数えています。
2種類の「待っている人」をたとえで整理しよう¶
スーパーのレジを思い浮かべてみてください。
レジで会計中のお客さんと、列に並んでいるお客さん。これが実行可能な状態、つまり R 状態のプロセスです。CPUというレジを使っているか、使う順番を待っています。
一方で、「倉庫から商品を取ってくるので少々お待ちください」と言われて、その場で動けずにいるお客さんもいます。これが割り込み不可能な状態、つまり D 状態のプロセスです。ディスクやネットワークストレージからの応答を待っていて、そのあいだは何もできません。
ロードアベレージは、この両方を足した人数の平均です。レジが空いていても、倉庫待ちのお客さんが大勢いれば、数字は高くなります。
冒頭の「CPUは暇なのにロードが高い」という状況は、まさにこれです。
/proc/loadavg を直接のぞいてみる¶
uptime や top が表示している値の出どころは、/proc/loadavg というファイルです。
$ cat /proc/loadavg
6.12 3.08 1.45 3/412 28731
各フィールドの意味を、表にまとめておきます。
| フィールド | 例 | 意味 |
|---|---|---|
| 1〜3番目 | 6.12 3.08 1.45 |
1分・5分・15分のロードアベレージ |
| 4番目(スラッシュの左) | 3 |
いま実行可能な状態にあるプロセス・スレッドの数 |
| 4番目(スラッシュの右) | 412 |
システムに存在するプロセス・スレッドの総数 |
| 5番目 | 28731 |
最後に作られたプロセスのPID |
4番目のフィールドは、平均ではなく「いまこの瞬間」の値です。ロードアベレージが6なのに、実行可能なものが3しかない。この差の中に、D 状態で待っているプロセスが隠れている可能性があります。
「ロードが4」は高いのか、低いのか?¶
次によく出る疑問が、「いくつを超えたら危ないのか」です。
答えは、CPUの数によって変わります。uptime のマニュアルにも、ロードアベレージはCPUの数で正規化されていない、と明記されています。1CPUのサーバーでロードが1なら、ずっと埋まりっぱなしです。4CPUのサーバーでロードが1なら、75%は空いていた計算になります。
まずは、そのサーバーが使えるCPUの数を確認しましょう。
$ nproc
4
nproc は、現在のプロセスが使える処理ユニットの数を表示します。コンテナやCPUの割り当てを制限した環境では、物理的なCPUの数より少なく出ることもあります。
CPUの数との比べ方の目安を、表にしておきます。
| ロードアベレージ ÷ CPU数 | 読み方の目安 |
|---|---|
| 1未満 | レジに空きがある。待ちはあまり発生していない |
| 1前後 | ほぼ埋まっている。余裕は小さい |
| 1を大きく超える | 誰かが待たされている。ただしCPU待ちかI/O待ちかは別途確認が必要 |
大事なのは、この比率はあくまで入り口だということです。ロードアベレージにはI/O待ちも含まれるので、比率が高いからといって「CPUが足りない」とは限りません。
1分・5分・15分の並びで「流れ」を読む¶
3つの数字は、並び順にも意味があります。
冒頭の例は 6.12, 3.08, 1.45 でした。1分の値がいちばん大きく、15分がいちばん小さい。これは、負荷がいままさに上がってきている状態です。
逆に 1.20, 3.50, 5.80 のように右ほど大きければ、ピークは過ぎて落ち着きつつあると読めます。
なお、この平均は単純な平均ではなく、古い値ほど影響が小さくなるように計算されています。急に負荷がかかっても、15分の値はゆっくりとしか上がりません。アラートの閾値を1分の値にするか15分の値にするかで、反応の速さが変わるのはこのためです。
ロードが高いとき、どこから見ればいい?¶
ここからが実務の本題です。ロードアベレージが高いと分かったら、次の問いは「待っているのはCPUの列か、倉庫の前か」です。
これを一度に見分けるのに便利なのが vmstat です。
$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 5 0 812340 10244 2210400 0 0 9820 120 980 1500 4 3 22 71 0
0 6 0 811900 10244 2211020 0 0 10240 96 1010 1620 3 2 20 75 0
1 5 0 811560 10248 2211800 0 0 9960 104 990 1540 4 3 21 72 0
1 5 は、1秒おきに5回表示するという意味です。1行目は起動してからの平均なので、2行目以降を見るのが基本です。
見るべき列を、表で整理しておきます。
| 列 | 意味 | 高いときに疑うこと |
|---|---|---|
r |
実行可能なプロセスの数(実行中+CPU待ち) | CPUの取り合い |
b |
I/Oの完了を待ってブロックされているプロセスの数 | ディスクやストレージの遅さ |
us / sy |
ユーザー空間・カーネルで使ったCPU時間の割合 | 計算処理やシステムコールの多さ |
wa |
I/O待ちで費やした時間の割合 | ストレージが追いついていない |
st |
仮想マシンでハイパーバイザーに奪われた時間の割合 | 同じ物理ホスト上の他のVMとの取り合い |
上の例では、r は0〜1なのに b が5〜6あり、wa が70%を超えています。レジは空いているのに、倉庫の前に行列ができている状態です。
パターン1: r が多い = CPUの取り合い¶
r がCPUの数を上回り続け、us や sy が高く id が低いなら、素直にCPUが足りていません。
この場合は、top でCPUを多く使っているプロセスを探します。top の画面で 1 キーを押すと、CPUごとの使用率が別々の行で表示されます。
%Cpu0 : 98.7 us, 1.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 3.0 us, 1.0 sy, 0.0 ni, 96.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 2.7 us, 0.7 sy, 0.0 ni, 96.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 2.3 us, 1.0 sy, 0.0 ni, 96.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
全体の平均だと25%程度に見えても、1つのCPUだけが張り付いていることがあります。シングルスレッドで動く処理が詰まっているときに、よく見かける形です。
仮想マシンなら st も確認してください。ここが高いなら、原因はサーバーの中ではなく、同じホストに同居している他のVMかもしれません。
パターン2: b が多い = I/O待ち¶
冒頭の「CPUは暇なのにロードが高い」の多くは、こちらです。
まずは、誰が待っているのかを特定しましょう。ps で状態が D のプロセスを抜き出します。
$ ps -eo state,pid,user,wchan:32,cmd | awk '$1 == "D"'
D 18422 mysql io_schedule /usr/sbin/mysqld
D 18455 root io_schedule tar czf /backup/data.tar.gz /var/lib
D 18460 app rpc_wait_bit_killable /usr/bin/python3 batch.py
ps のマニュアルでは、D は「uninterruptible sleep (usually IO)」、つまり通常はI/Oによる割り込み不可能な待ち状態と説明されています。wchan の列には、プロセスがカーネルのどこで待っているかの手がかりが出ます。
この例なら、バックアップの tar がディスクを読み込み、データベースがその巻き添えで待たされている、という筋書きが見えてきます。rpc_ で始まる待ちが見えたら、NFSのようなネットワーク越しのストレージを疑う手がかりになります。
次に、どのディスクが詰まっているかを iostat で確かめます。sysstat パッケージに含まれているコマンドです。
$ iostat -x 1 3
Device r/s rkB/s r_await w/s wkB/s w_await aqu-sz %util
sda 812.0 98240.0 38.50 14.0 120.0 22.10 31.60 99.8
r_await と w_await は、読み書きの要求が待ち行列に並んだ時間も含めた平均の応答時間(ミリ秒)です。aqu-sz は待ち行列の平均の長さを表します。
%util は注意が必要な列です。マニュアルにも、要求を1つずつ処理する装置なら100%付近で飽和と言えるが、並列に処理できるRAIDや最近のSSDでは性能の限界を表さない、と書かれています。%util だけで判断せず、await が普段よりどれだけ伸びているかをあわせて見てください。
D状態のプロセスは、止めようとしても止まらない¶
I/O待ちのプロセスを見つけると、とりあえず止めてしまいたくなるかもしれません。ところが、D 状態のプロセスは名前のとおり割り込みを受け付けないので、シグナルを送ってもすぐには終わらないことがあります。
倉庫の前で待っているお客さんに「もう帰ってください」と声をかけても、商品が届くまでは動けないのと同じです。killコマンドで -9 を付けても残り続けるなら、プロセスではなく、待たせている側のディスクやストレージの状態を調べるほうが先決です。
実際の切り分けを、順番どおりに並べてみよう¶
ここまでの流れを、アラートを受けてから原因にたどり着くまでの手順としてまとめておきます。
# 1) 数字と勢いを確認する(上がっている途中か、落ち着きつつあるか)
uptime
nproc
# 2) CPU待ちかI/O待ちかを見分ける(r と b、us/sy と wa)
vmstat 1 5
# 3-a) r が多いとき:CPUを使っているプロセスとCPUごとの偏りを見る
top # 起動後に 1 キーでCPUごとの表示
# 3-b) b が多いとき:待っているプロセスと、詰まっているディスクを見る
ps -eo state,pid,user,wchan:32,cmd | awk '$1 == "D"'
iostat -x 1 3
この順番にしておくと、「ロードが高い」という1つの数字を、「どのプロセスが、何を待っているのか」という具体的な話に変えられます。
メモリ不足がI/O待ちに化けることもある¶
もうひとつ、覚えておいてほしいパターンがあります。メモリが足りなくなってスワップが発生すると、ディスクへの読み書きが増え、結果としてI/O待ちが増えることがあります。
vmstat の si と so の列が0でなければ、スワップの出入りが起きています。この場合、ディスクを速くするより先に、メモリの使われ方を調べるほうが近道です。メモリの見方はLinuxのメモリ不足をavailableとOOM Killerの記録から見極めるで詳しく解説しています。
同じように、ディスクが満杯に近いときの挙動が気になる場合はLinuxの容量トラブルを切り分ける順番もあわせて読んでみてください。
ロードアベレージの監視、閾値はどう決める?¶
最後に、監視設計の話を少しだけしておきます。
ロードアベレージのアラートを「5を超えたら通知」のように固定の値で決めていないでしょうか。CPUが2つのサーバーと16のサーバーで同じ閾値を使うと、片方では鳴りすぎ、もう片方では鳴らなさすぎになります。
おすすめは、CPUの数で割った値で考えることです。そのうえで、普段の値を一定期間ながめて、そのサーバーにとっての「いつもの範囲」を知っておくことが大切です。
ロードアベレージは、原因を教えてくれる指標ではありません。「誰かが待たされている」ことを教えてくれる、入り口の指標です。
そのため、ロードアベレージだけでアラートを組むより、CPU使用率やI/O待ち、ディスクの応答時間と組み合わせて見るほうが、夜中の呼び出しで迷わずに済みます。
プロセスの状態を見る ps の基本的な使い方はpsコマンドの使い方解説に、top を使ったメモリの確認方法はLinuxのメモリ使用率を確認する方法にまとめています。コマンドそのものに不安がある方は、先にこちらを読んでおくと、今日の内容がぐっと追いやすくなるはずです。
こうした個々のコマンドを、障害対応の流れの中でつなげて使えるようになると、現場での安心感がまったく違ってきます。InfraAcademyのLinuxロードマップでは、プロセスやリソースの見方を順番に学び直せるように整理しているので、体系的に復習したい方はのぞいてみてください。
まとめ¶
今日の内容を振り返っておきます。
- Linuxのロードアベレージは、実行中・CPU待ちの
R状態に加えて、I/O待ちのD状態のプロセスも数えている - 数字はCPUの数で正規化されていないので、
nprocで確認したCPU数と比べて読む - 1分・5分・15分の並びから、負荷が上がっている途中か落ち着きつつあるかが分かる
vmstatのrとbで、CPUの取り合いかI/O待ちかを見分ける- I/O待ちなら
psでD状態のプロセスを探し、iostat -xで詰まっているディスクを確かめる
ロードアベレージが高いときに本当に知りたいのは、誰が何を待っているのかです。数字を見て慌てる前に、レジの列と倉庫の前、どちらに人が並んでいるのかを確かめてみてください。
一度この順番で追いかけてみると、次にアラートが鳴ったとき、きっと落ち着いて画面に向かえるはずです。
参考記事¶
- Ubuntu Manpage: uptime - Tell how long the system has been running
- Ubuntu Manpage: proc_loadavg - load average
- Ubuntu Manpage: vmstat - Report virtual memory statistics
- Ubuntu Manpage: ps - report a snapshot of the current processes
- Ubuntu Manpage: top - display Linux processes
- Ubuntu Manpage: iostat - Report CPU statistics and input/output statistics
- Ubuntu Manpage: nproc - print the number of processing units available



