最初の1分で負荷の種類を見分ける
まず uptime でロードアベレージを確認します。ロードアベレージは、CPUで実行中のプロセスとCPUを待っているプロセスの平均数です。ディスクI/Oを待っているプロセスも含まれます。1分・5分・15分の3つの値が表示され、1分値だけが高ければ負荷は今始まったところです。3つとも高ければ、負荷はしばらく続いています。
次に top を起動し、上部の %Cpu(s) 行を見ます。ここで見るのは us(ユーザープロセス)、sy(カーネル)、wa(I/O待ち)、st(スチール:仮想マシンでホスト側に奪われた時間)の4項目です。どの項目が高いかで、この先の進路が決まります。
usが高い場合は、特定のプロセスがCPUを使っています。次の節へ進みます。waが高い場合は、ディスクI/Oが詰まっています。メモリとI/Oの節へ進みます。stが高い場合は、原因がサーバーの外にある可能性があります。クラウドや仮想化基盤の管理画面で、ホスト側の状況とインスタンスのCPUクレジット残量を確認します。- ロードアベレージは高いのにCPU使用率が低い場合は、I/O待ちで止まっているプロセスがあります。
ps -eo state,pid,cmd | grep '^D'でD状態(割り込み不可の待機)のプロセスを探し、NFSなどのネットワークストレージやディスク障害を疑います。
top/psで負荷の主を特定する
top の画面で P を押すとCPU使用率順、M を押すとメモリ使用量順に並びます。1 を押すとコアごとの使用率が出ます。1コアだけが100%に張り付いているなら、シングルスレッドの処理が原因です。次のコマンドでプロセスの起動時刻と親プロセスも記録しておきます。
ps -eo pid,ppid,user,%cpu,%mem,lstart,etime,cmd --sort=-%cpu | head -n 15上位のプロセス名がMySQL、PHP-FPM、Javaなど、そのサーバーの本来の役割に属するものなら、アクセス増加や重いクエリが原因である可能性が高くなります。アプリケーションのアクセスログとスロークエリログを確認します。プロセス名に見覚えがない場合や、起動時刻が負荷の始まった時刻と一致する場合は、以下の節で正体を確かめます。
定期ジョブとバックアップを確認する
負荷が毎日同じ時刻に始まるなら、定期ジョブを最初に疑います。systemctl list-timers --all でsystemdタイマーを確認します。cronは crontab -l(ユーザーごと)、/etc/crontab、/etc/cron.d/、/etc/cron.daily/ などに分散しているため、それぞれ確認します。バックアップ、ログローテーション、updatedb、ウイルススキャン、パッケージの自動更新が代表例です。
該当するジョブがあり、終了とともに負荷も下がるなら、障害ではなくスケジュールの問題です。実行時刻をずらすか、nice や ionice で優先度を下げます。一方、自分たちで登録した覚えのないジョブが見つかった場合は、削除せずに内容と更新日時を記録し、不正プロセスの節へ進みます。
ログ肥大とディスク容量を確認する
df -h で容量を、df -i でiノード(ファイル数の上限)を確認します。どちらかが100%に近い場合、書き込みに失敗したアプリケーションがリトライを繰り返し、CPUを消費することがあります。du -xh -d1 /var/log | sort -h で大きいディレクトリを探し、journalctl --disk-usage でjournalの使用量も確認します。
特定のログが急に増えている場合は、そのログの末尾を読みます。同じエラーが大量に出ているなら、根本原因はそのエラーです。外部からの大量の認証失敗が記録されている場合は、アクセス元の遮断やレート制限を検討します。
メモリ不足とスワップを確認する
free -h で available が小さいかを見ます。続けて vmstat 1 5 を実行し、si と so(スワップイン・アウト)が継続して0でないかを確認します。スワップが常に発生している状態では、ディスクへの読み書きが増えるため wa も上がり、全体が極端に遅くなります。
journalctl -k | grep -i 'out of memory' でOOM Killer(メモリ枯渇時にカーネルがプロセスを強制終了する機構)の記録も探します。記録がある場合、終了させられたプロセスが自動で再起動し、メモリ確保と強制終了を繰り返していることがあります。メモリを使っているプロセスが特定できたら、設定上の上限(ワーカー数、キャッシュサイズなど)を見直します。急に使用量が増えたのなら、メモリリークの可能性があります。
ディスクI/Oの詰まりを確認する
wa が高く、メモリにも余裕がある場合はI/Oを調べます。sysstatパッケージの iostat -x 1 で、デバイスごとの %util と r_await/w_await(1回の読み書きの平均待ち時間)を見ます。%util が100%近くで推移していれば、そのデバイスが詰まっています。どのプロセスが読み書きしているかは pidstat -d 1 または iotop で確認できます。
プロセスに心当たりがないのに待ち時間だけが長い場合は、ディスクそのものの劣化を疑います。dmesg -T にI/Oエラーが出ていないかを確認し、物理サーバーなら smartctl -a でSMART情報を確認します。
どれにも当たらないときに不正プロセスを疑う確認ポイント
ここまでの確認で説明のつかない高負荷が続く場合は、暗号資産マイナーなどの不正プロセスを疑います。マイナーとは、侵入したサーバーのCPUを使って暗号資産の採掘計算を行うプログラムです。脆弱なWebアプリケーションや、推測されやすいSSHパスワードを足がかりに設置されることが多いと報告されています(執筆時点)。
確認するのは次の点です。プロセスの実行ファイルの場所は ls -l /proc/PID/exe で確かめます。参照先が /tmp、/var/tmp、/dev/shm にある場合や、末尾に (deleted) と表示される場合は不審です。正規のソフトウェアがこれらの場所から常駐することはまれです。ss -tnp では、そのプロセスが見覚えのない外部アドレスへ接続し続けていないかを確認します。Webサーバーの実行ユーザー(www-data や apache など)が、シェルや見慣れないバイナリを子プロセスとして起動している場合も要注意です。
永続化の痕跡も探します。対象は、身に覚えのないcronやsystemdユニット、~/.ssh/authorized_keys に追加された鍵、新しく作られたユーザーです。さらに、/etc/ld.so.preload が存在しないかも確認します。このファイルはライブラリを強制的に読み込ませる仕組みで、top や ps の表示からプロセスを隠す目的で悪用されることがあります。top の合計CPU使用率が高いのに、一覧にそれらしいプロセスが見当たらない状態も、表示が改ざんされている兆候です。
初動対応へ移る判断基準
次のどれか1つでも当てはまれば、性能問題ではなくセキュリティインシデントとして扱います。一時ディレクトリや削除済みファイルから実行されているプロセスがある場合。説明のつかない外部への継続的な接続がある場合。登録した覚えのない自動起動設定や鍵、ユーザーがある場合。プロセスを隠す仕組みが見つかった場合です。
このとき、不審なプロセスをすぐ kill したり、サーバーを再起動したりしないでください。メモリ上の証拠が消え、侵入経路の特定が難しくなります。永続化されていれば、再起動後にまた動き出します。まず ps、ss、cronの内容などの出力をファイルに保存し、時刻とともに記録します。そのうえで、組織の手順に従って責任者に報告し、セキュリティグループやファイアウォールでネットワークを隔離します。不審なファイルを自分で実行して挙動を確かめることは避けます。社内に対応体制がない場合は、JPCERT/CC の公開資料を参照するか、専門の事業者に相談します。
どの段階にも当てはまらず原因がつかめない場合は、sar(sysstat)で負荷の履歴を取り、症状が出た時刻とデプロイ、設定変更、アクセス量の変化を突き合わせます。再発に備えて、CPU、メモリ、ディスク使用率、プロセス数の監視とアラートを設定しておけば、次回は負荷が始まった時刻から調査を始められます。