概要
LinuxカーネルのOOM(Out of Memory)Killerは、システムの物理メモリとスワップが枯渇した際に、メモリ使用量の多いプロセスを強制終了(kill)してシステム全体のクラッシュを防ぐ仕組みです。プロセスが予期せず終了する原因としてよく見られます。
エラーメッセージ
Out of memory: Killed process 12345 (java) total-vm:4096000kB, anon-rss:3500000kB, file-rss:0kB, shmem-rss:0kB
dmesgでの表示:
[12345.678901] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/system.slice/myapp.service,task=java,pid=12345,uid=1000
[12345.678902] Out of memory: Killed process 12345 (java) total-vm:4096000kB, anon-rss:3500000kB
[12345.678903] oom_reaper: reaped process 12345 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
原因
- メモリリーク: アプリケーションが使用済みメモリを解放していない
- スワップ領域の不足または無効化: メモリの逃げ場がない
- cgroup/コンテナのメモリ制限: DockerやKubernetesのメモリリミットに到達
- 不適切なJVMヒープ設定: Javaアプリでヒープサイズが大きすぎる
- 同時実行プロセスが多すぎる: fork爆弾やワーカー数過多
解決策
1. OOM Killerのログを確認
1
2
3
4
5
6
7
8
9
| # dmesgでOOM Killerのログを確認
dmesg | grep -i "oom\|out of memory\|killed process"
# journalctlで確認
journalctl -k | grep -i "oom\|out of memory"
# システムログで確認
grep -i "oom" /var/log/syslog
grep -i "oom" /var/log/messages
|
2. メモリ使用状況の監視
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # メモリの概要
free -h
# プロセス別メモリ使用量(上位10件)
ps aux --sort=-%mem | head -11
# リアルタイム監視
top -o %MEM
# 詳細なメモリマップ
cat /proc/meminfo
# 特定プロセスのメモリ使用量
cat /proc/<PID>/status | grep -i "vmrss\|vmsize\|vmswap"
|
3. スワップの追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 現在のスワップ確認
swapon --show
# スワップファイルの作成(4GB)
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永続化(/etc/fstab に追加)
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# swappinessの調整(デフォルト60)
sudo sysctl vm.swappiness=10
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.d/99-custom.conf
|
4. oom_score_adjでプロセスの優先度を制御
1
2
3
4
5
6
7
8
| # プロセスのOOMスコアを確認
cat /proc/<PID>/oom_score
cat /proc/<PID>/oom_score_adj
# 重要なプロセスをOOM Killerから保護(-1000が最も保護される)
echo -1000 | sudo tee /proc/<PID>/oom_score_adj
# systemdサービスで設定
|
1
2
3
| # /etc/systemd/system/myapp.service
[Service]
OOMScoreAdjust=-500
|
5. Docker/Kubernetesのメモリ制限を調整
1
2
3
4
5
| # Dockerコンテナのメモリ制限を確認
docker stats
# メモリ制限を指定して実行
docker run -m 2g --memory-swap 3g myapp:latest
|
1
2
3
4
5
6
7
8
9
10
11
| # Kubernetes Pod のメモリ設定
apiVersion: v1
kind: Pod
spec:
containers:
- name: myapp
resources:
requests:
memory: "1Gi"
limits:
memory: "2Gi"
|
6. Javaアプリのヒープ設定
1
2
3
4
5
| # JVMのメモリ設定を適切に制限
java -Xms512m -Xmx1g -XX:MaxMetaspaceSize=256m -jar myapp.jar
# コンテナ環境ではメモリ認識を有効化
java -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -jar myapp.jar
|
関連エラー