Linuxでメモリ使用量が増大した時の調査用コマンドと原因切り分けについて

最近、オンプレミスで稼働しているサーバーに入り、リソースの状況をチェックする機会がありました。

主にメモリについて調査をすることになったのですが、問題の切り分けや原因の特定がうまくできず、インフラチームに訊きながら進めているところです。

これまで取り組んできたエンジニアリングとは異なる難しさを感じています。(より基礎的な能力が必要とされている感、、)

以前、 メモリを開放する方法について調べた記事 を投稿したのですが、調査用のコマンドについてはあまり理解していなかったため、勉強がてら簡単にまとめることにしました。

メモリの使用状況を確認できるコマンド

free

free コマンドは、物理メモリとスワップメモリの合計量、空きメモリと使用中のメモリに関する情報が分かります。

$ free

# ↓出力結果
               total        used        free      shared  buff/cache   available
Mem:        4033784      718800      673224      368112     2641760     2791660
Swap:       1048572       65292      983280
  • free -h…人間が見やすい単位で表示
  • free -w…buffer と cache を分けて表示

Mem: について

  • total - システムに搭載されているメモリの合計量
  • used - 使用中のメモリ。計算式 → used = total - free - buffers - cache
  • free - 見かけ上の、使われていない空きメモリ量
  • shared - free コマンド自体の下位互換性を持たせるために残されているフィールド。
  • buff/cache - バッファキャッシュとページキャッシュおよびスラブによって使用されているメモリの量。システムの空き容量が減少すると自動で解放される。 -w オプションで buffer と cache の二つのフィールドに分けて表示できる。
  • available - 実質的な空きメモリの量。空きメモリが不足したら開放できるカーネル内のメモリ領域と free フィールドの値を足したもの。開放できるメモリには buff/cache の大部分も含まれる。

Swap: について

  • total - スワップ用に確保されている領域のサイズ
  • used - 使用中のメモリ。計算式 → used = total - free
  • free - スワップアウトできる領域のサイズ

vmstat

メモリの使用状況を細かく確認することができるコマンドです。例えば、プロセス、メモリ、ページング、ブロック IO、トラップ、CPU アクティビティに関する情報など。

$ vmstat

# ↓出力結果
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
 9  0  69900 949732 2036104 762212    0    0     9   126  153   80  1  3 95  0  0

free コマンドのように大まかな確認だけでなく、深堀調査したい時など幅広く使えます。

top

Mac の Activity Monitor のように、LoadAverage や CPU 使用率、メモリ使用率といった情報をプロセスごとにチェックすることができます。障害の原因がプロセスかカーネルか、、といったあたりの切り分けにも使えそうです。

$ top

# ↓出力結果
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  3.3 sy,  0.0 ni, 96.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3939.2 total,    926.8 free,    455.3 used,   2557.1 buff/cache
MiB Swap:   1024.0 total,    955.7 free,     68.3 used.   2905.8 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    1 root      20   0    4112   3260   2904 S   0.0   0.1   0:00.03 bash
   14 root      20   0    4244   3624   3016 S   0.0   0.1   0:00.02 bash
  237 root      20   0    6108   3264   2808 R   0.0   0.1   0:00.00 top

下記オプションをつけることで CPU やメモリ使用量の順にソートできます。

  • -o %MEM…メモリ使用量の順にソート
  • -o %CPU…CPU 使用量の順にソート
  • -n 1…1 回だけ情報を取得

/proc/meminfo

/ proc / meminfo は、システム上の空きメモリと使用済みメモリ(物理メモリとスワップメモリ ​​ の両方)の量、およびカーネルが使用するメモリとバッファなど確認できます。

$ cat /proc/meminfo

# ↓出力結果
MemTotal:        4033824 kB
MemFree:         2915376 kB
MemAvailable:    3014600 kB
Buffers:           25860 kB
Cached:           668468 kB
SwapCached:            0 kB
...省略

その他

slabtop/proc/slabinfosar コマンドなど色々あり、用途に応じて使えます。

原因の切り分け

下記は一例ですが、上述のコマンドを使い次のように進めていくことができると思います。

  1. freevmstat でメモリの使用量/空き容量、スワップの発生状況を確認

    - スワップが発生するほどメモリ容量が逼迫しているので空き容量を確保しないといけないな〜とか大雑把に判断できる

  2. top でプロセスが使用しているメモリを確認

    - メモリを大量に消費しているプロセスがある場合

    → プロセス、アプリケーション周りを調査

    - メモリを消費しているプロセスがない場合

    → システム(カーネル)が使用しているメモリ状況を調査…3 へ

  3. /proc/meminfo でカーネル含むメモリの使用状況を確認

  4. 3 の結果から、状況に応じて深堀調査をしていく

    例えば slab 関連の領域がメモリを多く使用している場合は slabtop などで slab に関する情報を調べるなど。

まとめ

メモリ利用状況を調査するコマンドと、問題が発生した時の切り分け手順について整理しました。

近年は GKE や AWS の ECS、Firebase などを使うケースが増え、ハードウェアに近い部分を調査する機会は少なくなってきたように思いますが、基本はやはり Linux だと思うので引き続き知識をアップデートしていこうと思います。