Linuxリソース枯渇のトラブルシューティング:CPU、メモリ、ディスク容量

実用的なコマンド、安全なクリーンアップ手順、根本原因の確認を通じて、LinuxのCPU、メモリ、ディスク枯渇をトラブルシューティングします。

Linuxリソース枯渇のトラブルシューティング:CPU、メモリ、ディスク容量

LinuxサーバーがCPU、メモリ、またはディスク容量を使い果たすと、最初の症状は通常あいまいです。サイトが遅い、SSHがログイン後にハングする、デプロイが失敗する、またはサービスが再起動を繰り返すなどです。インシデントを迅速に解決するには、どのリソースが枯渇しているかを特定し、その背後にあるプロセスやファイルシステムを見つけることです。

まずはリスクの少ない確認から行いましょう。topfreedfduvmstatjournalctlなどの読み取り専用コマンドは、マシンに変更を加えずに状況を把握できます。プロセスの強制終了やファイルの削除が必要になることもありますが、それは診断ではありません。

原因の特定:システムリソースの監視

リソース枯渇問題を修正する前に、どのリソースが過剰に使用されているか、どのプロセスが原因かを特定する必要があります。Linuxはこの目的のために豊富なコマンドラインツールを提供しています。

CPU使用率の監視

高いCPU使用率は、システムの動作を遅くし、応答不能にする可能性があります。これは多くの場合、暴走プロセス、要求の厳しいアプリケーション、または非効率的なスクリプトが原因です。

  • top:これは不可欠なリアルタイムシステムモニターです。デフォルトでCPU使用率順にソートされた動的なプロセスリストを表示します。全体的なCPU使用率、メモリ使用量、個々のプロセスの詳細を確認できます。

    top
    

    top内で1を押すと、個々のCPUコアの使用率を表示できます。Pを押すとCPU使用率でソートできます。一貫して高いCPU使用率を消費しているプロセスを探してください。

  • htop:拡張されたインタラクティブなtopのバージョンです。ユーザーフレンドリーで色分けされた出力、簡単なナビゲーションが好まれます。

    htop
    

    topと同様に、htopでもCPU使用率でソートし、詳細なプロセス情報を提供します。

  • mpstatsysstatパッケージの一部で、プロセッサごとの使用率、割り込み数、コンテキストスイッチなど、詳細なCPU統計を提供します。

    mpstat -P ALL 1
    

    このコマンドは、すべてのコアのCPU統計を1秒ごとに表示します。

また、ロードアベレージをCPUコア数と照らし合わせて確認します。

uptime
nproc

ロードアベレージ8は、2コアのVMと32コアのホストでは意味が大きく異なります。ロードには割り込み不可能なI/Oを待つタスクも含まれるため、CPU使用率が低いのにロードアベレージが高い場合は、ディスクやネットワークストレージが原因である可能性があります。

メモリ使用量の監視

システムが利用可能なRAMとスワップ領域を使い果たすと、ディスク領域を仮想メモリとして使い始め、大幅に速度が低下し、深刻なパフォーマンス低下を引き起こします。

  • free -h:システム内の空きおよび使用中の物理メモリとスワップメモリの合計量を、カーネルが使用するバッファとキャッシュとともに表示します。-hフラグは出力を人間が読みやすい形式(MB、GBなど)にします。

    free -h
    

    availableメモリとusedスワップ領域に注意してください。スワップ使用量が多い場合は、RAMが不足していることを示します。

  • top / htoptophtopはどちらもプロセスごとのメモリ使用量を表示します。%MEM値が高いプロセスを探してください。

  • vmstat:仮想メモリ統計を報告します。プロセス、メモリ、ページング、ブロックI/O、トラップ、CPUアクティビティに関する情報を表示できます。

    vmstat 5
    

    このコマンドは5秒ごとに統計を報告します。si(スワップイン)とso(スワップアウト)の列を確認します。値が高い場合は、重大なメモリスワッピングが発生していることを示します。

OOMキルの可能性については、カーネルログを確認します。

dmesg -T | grep -i 'killed process'
journalctl -k --since "1 hour ago" | grep -i oom

OOMキルが発生すると、インシデントの状況が変わります。すぐに問うべきことは、どのプロセスが強制終了されたか、なぜ利用可能なメモリを超えたか、systemdやオーケストレーターがそれを再起動したかどうかです。

ディスク容量の監視

ディスクパーティションがいっぱいになると、アプリケーションがデータを書き込めなくなり、エラーが発生し、システムが起動できなくなることさえあります。

  • df -h:ファイルシステムのディスク容量使用量を報告します。-hフラグは出力を人間が読みやすい形式にします。

    df -h
    

    このコマンドは、マウントされているすべてのファイルシステムをリストし、合計サイズ、使用済み容量、利用可能な容量、マウントポイントを表示します。使用率が100%またはそれに近いパーティションを探してください。

  • du -sh <directory>:指定されたディレクトリのファイル容量使用量を推定します。-sフラグは要約し、-hは人間が読みやすい形式にします。

    du -sh /var/log/*
    

    これを使用して、どのサブディレクトリが最もディスク容量を消費しているかを特定します。

inode使用量も確認します。

df -ih

ファイルシステムに空きギガバイトがあっても、inodeを使い果たしているとファイルを作成できません。これは、数百万の小さなファイル(キャッシュエントリ、メールキュー、セッションファイル、ビルドアーティファクト、ローテーションが不適切なログなど)がある場合に発生します。

リソース枯渇問題の解決

問題のあるリソースと原因プロセスを特定したら、問題を解決するための手順を実行できます。

高いCPU使用率への対処

  1. プロセスの特定topまたはhtopを使用して、高いCPUを消費しているプロセスID(PID)を見つけます。
  2. プロセスの調査:プロセスが何であるかを特定します。ユーザーアプリケーション、システムサービス、または予期しないものですか?
    • 正当な高使用率:正当なアプリケーションが多くのCPUを使用している場合(例:ソフトウェアのコンパイル、ビデオエンコード)、完了するのを待つか、オフピーク時にスケジュールするか、ハードウェアをアップグレードする必要があるかもしれません。
    • 暴走プロセス:プロセスがループに陥ったり、意図せず過剰なCPUを消費している場合は、再起動を試みることができます。それでも解決しない場合は、強制終了する必要があるかもしれません。
  3. プロセスの強制終了(注意して使用!)killコマンドを使用してプロセスにシグナルを送信できます。最も一般的なシグナルは次のとおりです。
    • SIGTERM (15):プロセスに正常に終了するよう要求します。
    • SIGKILL (9):プロセスを即座に強制終了します。これは最後の手段であり、プロセスがクリーンアップを行うことができません。
    # PID 1234のプロセスを正常に終了
    kill 1234
    
    # PID 1234のプロセスを強制終了
    kill -9 1234
    
  4. ログの確認:問題のあるプロセスに関連するエラーについて、システムログ(例:/var/log/syslog/var/log/messages、アプリケーション固有のログ)を確認します。
  5. アプリケーション/スクリプトの最適化:高いCPU使用率が非効率的なアプリケーションやスクリプトによるものである場合は、コードや設定の最適化を検討します。

高いCPUが常に悪いとは限りません。短時間だけすべてのコアを使用するバッチジョブは問題ない場合があります。リクエストがキューイングされている間に、シングルスレッドのプロセスが1つのコアで100%のままスタックしているのは別の問題です。期間、ユーザーへの影響、プロセスがビジーであることが予想されるかどうかを確認します。

サービスを再起動する前にさらにコンテキストが必要な場合は、スナップショットを取得します。

ps -fp <pid>
sudo lsof -p <pid> | head
sudo strace -p <pid> -tt -T -f

本番システムではstraceを慎重に使用してください。オーバーヘッドが追加される可能性がありますが、短いサンプルでも、プロセスがループしているのか、ファイルを待っているのか、ネットワークコールに失敗しているのか、同じリソースを繰り返し開いているのかがわかることがよくあります。

メモリリークと枯渇の解決

メモリリークは、プログラムが不要になったメモリを解放できず、徐々にすべての利用可能なRAMを消費する場合に発生します。これにより、過剰なスワッピングとシステムの応答不能が発生する可能性があります。

  1. プロセスの特定topまたはhtopを使用して、メモリ使用量(%MEM)または常駐セットサイズ(RSS)の値が時間の経過とともに着実に増加しているプロセスを見つけます。
  2. プロセスの調査:アプリケーションの性質を特定します。既知のメモリ問題があるアプリケーションですか、それともカスタムアプリケーションですか?
  3. アプリケーション/サービスの再起動:多くの場合、アプリケーションまたはサービスを再起動するだけで、蓄積されたメモリを解放することでメモリリークを一時的に解決できます。
    # 例:Apache Webサーバーの再起動
    sudo systemctl restart apache2
    
  4. アプリケーション固有の監視の確認:多くのアプリケーション(例:Webサーバー、データベース)には、メモリ問題の診断に役立つ独自の監視ツールやログがあります。
  5. コアダンプの分析:重要なアプリケーションの場合、コアダンプを有効にして、デバッグツール(gdbなど)を使用してリークが発生したときのメモリ状態を分析する必要があるかもしれません。これは高度なトラブルシューティング手順です。
  6. スワップ領域の増加(一時的な対策):リークをすぐに解決できない場合は、スワップ領域を増やして仮想メモリを増やすことができます。ただし、これは回避策であり、解決策ではありません。
  7. ハードウェアのアップグレード:システムがワークロードに対して一貫してメモリ不足になる場合は、物理RAMを追加する必要があるかもしれません。

より良いメモリ調査は、時間の経過に伴う変化を監視します。1回のtopスクリーンショットは、現在どのプロセスが大きいかを示すだけです。リークはトレンドです。

while true; do
  date
  ps -eo pid,comm,rss,%mem --sort=-rss | head -15
  sleep 60
done

同じプロセスがサンプル間で着実に上昇し、トラフィックが減少しても低下しない場合、リークのシグナルが強くなります。ピークトラフィック時に多くのプロセスが一緒に増加する場合、ワークロードが単に容量または同時実行制限を超えている可能性があります。

systemdサービスの場合、メモリ制限がすでに存在するかどうかを確認します。

systemctl show <service> -p MemoryCurrent -p MemoryMax

コンテナの場合、ホストレベルのfree -hは正常に見えても、コンテナが独自の制限に達している可能性があります。docker statskubectl top pod、またはOOMキルのオーケストレーターイベントを確認します。

ディスクパーティション満杯への対処

ディスクパーティションがいっぱいになると、さまざまなシステム障害が発生する可能性があります。通常は即座の対応が必要です。

  1. 満杯のパーティションの特定df -hを使用して、容量が100%のパーティションを見つけます。
  2. 大きなファイル/ディレクトリの検索du -shまたはdu -h --max-depth=1 <directory>を使用してディレクトリツリーを下り、容量を消費しているものを見つけます。
    # ルートパーティションで最大のディレクトリを見つける
    sudo du -h --max-depth=1 / | sort -rh
    
    一般的な原因には、ログファイル(/var/log)、一時ファイル(/tmp)、パッケージキャッシュ、ユーザーデータなどがあります。
  3. ログファイルのクリーンアップ:ログファイルは非常に大きくなる可能性があります。古いログを安全に削除したり、ログローテーション(logrotate)を設定してサイズを自動的に管理したりできます。
    • 古いログの削除:注意して、現在アクティブなログを削除しないようにしてください。findを使用して、特定の日数より古いファイルを削除できます。
      # /var/log/myapp内の30日より古い.logファイルを削除
      sudo find /var/log/myapp -name "*.log" -type f -mtime +30 -delete
      
    • ログローテーション:サービスに対してlogrotateが正しく設定されていることを確認します。通常は毎日実行され、古いログのアーカイブと削除を処理します。
  4. パッケージマネージャーキャッシュのクリア:パッケージマネージャーはダウンロードしたパッケージファイルを保持することがよくあります。これらをクリアすると、かなりの容量を解放できます。
    • Debian/Ubuntu (apt)
      sudo apt autoremove
      sudo apt clean
      
    • CentOS/RHEL/Fedora (yum/dnf)
      sudo yum autoremove  # または dnf autoremove
      sudo yum clean all   # または dnf clean all
      
  5. 未使用パッケージの削除:不要になったソフトウェアをアンインストールします。
    • Debian/Ubuntusudo apt remove <package_name>
    • CentOS/RHEL/Fedorasudo yum remove <package_name> または sudo dnf remove <package_name>
  6. 一時ディレクトリの確認/tmp内のファイルは、特に再起動後は安全に削除できることが多いですが、アプリケーションがアクティブに使用している場合は注意が必要です。
  7. ゴミ箱を空にする:デスクトップ環境を使用している場合は、ユーザーのゴミ箱を確認します。
  8. パーティションのサイズ変更を検討:容量が常に問題であり、クリーンアップでは不十分な場合は、パーティションのサイズを変更するか、ストレージを追加する必要があるかもしれません。これはより高度な操作であり、パーティションのアンマウントやライブ環境からの起動が必要になる場合があります。

削除してもまだ開かれているファイルに注意してください。実行中のプロセスがまだファイルハンドルを開いているため、大きなログファイルを削除した後でもdfはファイルシステムがいっぱいであると表示する場合があります。

sudo lsof +L1

削除されたファイルがまだ開かれたままの場合、所有するサービスを再起動またはリロードすると容量が解放されます。影響を理解せずに、インシデントの最中にデータベースや重要なサービスを再起動しないでください。

ジャーナルログの場合は、手動でファイルを削除するよりもjournalctlのクリーンアップを優先します。

journalctl --disk-usage
sudo journalctl --vacuum-time=14d

Dockerホストの場合は、コンテナログと未使用イメージを確認します。

docker system df
docker ps --size

本番ホストで広範なpruneコマンドを盲目的に実行しないでください。イメージ、ビルドキャッシュ、停止したコンテナ、ネットワークなど、誰かが保持することを期待していたものが削除される可能性があります。

プレッシャー下で機能するトリアージ順序

すべてが遅い場合は、固定された順序を使用して、理論を行き来しないようにします。

  1. ホストに到達可能であり、読み取り専用でないことを確認します。

    uptime
    date
    mount | grep ' ro,'
    
  2. CPUとロードを確認します。

    top
    uptime
    
  3. メモリとスワップを確認します。

    free -h
    vmstat 1 5
    
  4. ディスク容量とinodeを確認します。

    df -h
    df -ih
    
  5. 最近のカーネルとサービスのエラーを確認します。

    journalctl -p warning..alert --since "30 minutes ago"
    journalctl -k --since "30 minutes ago"
    

この順序で、CPU飽和、スワップストーム、ファイルシステム満杯、inode枯渇、OOMキル、ストレージエラーといった一般的な障害を迅速に捕捉できます。

最も害の少ない即時修正の選択

障害発生時には、恒久的な修正が準備できる前に短期的な修正が必要になる場合があります。

CPU枯渇の場合、特に状態を書き込むソフトウェアでは、kill -9よりも正常なサービス再起動の方が安全な場合があります。1つのバックグラウンドジョブがユーザートラフィックを飢餓状態にしている場合は、その優先度を下げます。

sudo renice +10 -p <pid>
sudo ionice -c2 -n7 -p <pid>

メモリ枯渇の場合、スワップを追加して期待するよりも、同時実行性を減らす方が安全なことがよくあります。Webワーカー数を減らし、バッチジョブを一時停止し、高価な機能を一時的に無効にします。スワップは時間を稼ぐことができますが、大量のスワップは通常、明確な障害を緩慢な障害に変えます。

ディスク枯渇の場合、理解しているファイルを削除またはローテーションします。適切な候補は、古い圧縮ログ、パッケージキャッシュ、廃止されたビルドアーティファクト、停止したジョブからの一時ファイルです。不適切な候補は、データベースファイル、アクティブなログ、アプリケーションデータディレクトリ内の不明なファイル、および説明できないものすべてです。

記録すべき根本原因メモ

システムが安定した後、何が変更されたかを書き留めます。有用なメモは具体的です。

  • 枯渇した正確なファイルシステムまたはリソース。
  • 関係するプロセス、ユーザー、サービス、コンテナ、またはcronジョブ。
  • それを証明したコマンド出力。
  • 実行した即時対応。
  • 必要な恒久的な修正。

これは単なる書類作成ではありません。デプロイ後にデバッグログが増加したために/varがいっぱいになったこと、またはワーカー数が2倍になったときにメモリプレッシャーが始まったことを知っていれば、次のインシデントははるかに簡単になります。

予防のためのベストプラクティス

  • 定期的な監視tophtopfreedf、および専用の監視ソリューション(例:Nagios、Zabbix、Prometheus)を使用して、CPU、メモリ、ディスク容量を定期的に監視します。
  • ログローテーションの自動化:ログを生成するすべてのサービスに対してlogrotateが適切に設定されていることを確認します。
  • アプリケーション設定のチューニング:アプリケーション設定を最適化して、リソース効率を高めます。たとえば、Webサーバーのワーカープロセス、データベース接続プールなどをチューニングします。
  • アラートの設定:持続的な高使用率、急激な増加、OOMキル、ファイルシステムの満杯、inode枯渇、サービス再起動に対するアラートを設定します。ハードリミットだけでなく、トレンドにもアラートを設定します。
  • システムアップデート:システムとアプリケーションを最新の状態に保ちます。新しいバージョンにはパフォーマンスの改善やバグ修正が含まれていることがよくあります。
  • リソース制限:マルチユーザーシステムやコンテナ化環境では、単一のプロセスが他のプロセスを飢餓状態にするのを防ぐために、リソース制限(ulimitやcgroupsを使用)の設定を検討します。

リソース枯渇のトラブルシューティングは、主に規律ある絞り込みです。制約されたリソースを見つけ、所有者を特定し、最小限の安定化変更を行い、その後、それが発生した理由を修正します。基本的なツールは、その順序で使用し、触れているものを理解する前に削除や強制終了をしないようにすれば、ほとんどのインシデントに十分です。