System Monitoring and Performance Tuning
Linux システムモニタリングとパフォーマンスチューニング 包括ガイド
目次
- はじめに
- モニタリングツール概要
- 2.1 top / htop
- 2.2 vmstat
- 2.3 iostat
- 2.4 mpstat
- 2.5 sar
- 2.6 pidstat
- 2.7 free / uptime
- /proc ファイルシステムによるモニタリング
- パフォーマンスメトリクス
- 4.1 CPU メトリクス
- 4.2 メモリメトリクス
- 4.3 ディスク I/O メトリクス
- 4.4 ネットワークメトリクス
- ストレステスト
- プロファイリング
- 6.1 perf
- 6.2 strace / ltrace
- チューニング方法論
- CPU チューニング
- 8.1 nice / renice
- 8.2 taskset (CPU アフィニティ)
- 8.3 cgroups によるリソース制御
- メモリチューニング
- 9.1 swappiness
- 9.2 Huge Pages
- 9.3 OOM Killer
- ディスク I/O チューニング
- 10.1 I/O スケジューラ
- 10.2 readahead
- 10.3 ionice
- ネットワークチューニング
- モニタリングスタック概要
- 12.1 Prometheus + Grafana
- 12.2 Nagios / Zabbix
- トラブルシューティング
- ベストプラクティス
- 参考資料
1. はじめに
Linux システムの安定運用において、モニタリングとパフォーマンスチューニングは不可欠なスキルである。本記事では、基本的なモニタリングツールの使い方からカーネルパラメータの調整、さらにはエンタープライズレベルのモニタリングスタック構築まで、体系的に解説する。
パフォーマンスチューニングの基本原則は以下の通りである。
- 計測してから最適化する -- 推測に基づく最適化は逆効果になることが多い
- ボトルネックを特定する -- CPU、メモリ、ディスク I/O、ネットワークのいずれかが律速になっている
- 一度に一つの変更を行う -- 複数同時変更は効果の判断を困難にする
- ベースラインを確立する -- 正常時のメトリクスを把握しておく
2. モニタリングツール概要
モニタリングツール比較表
| ツール | カテゴリ | リアルタイム | 履歴 | CPU | メモリ | ディスク | ネットワーク |
|---|---|---|---|---|---|---|---|
| top | プロセス | Yes | No | Yes | Yes | No | No |
| htop | プロセス | Yes | No | Yes | Yes | No | No |
| vmstat | システム全体 | Yes | No | Yes | Yes | Yes | No |
| iostat | ディスク | Yes | No | Yes | No | Yes | No |
| mpstat | CPU | Yes | No | Yes | No | No | No |
| sar | 総合 | Yes | Yes | Yes | Yes | Yes | Yes |
| pidstat | プロセス別 | Yes | No | Yes | Yes | Yes | No |
| free | メモリ | 瞬間値 | No | No | Yes | No | No |
| uptime | 負荷 | 瞬間値 | No | Yes | No | No | No |
2.1 top / htop
top の基本操作
# 基本起動
$ top
# バッチモードで出力(スクリプトに便利)
$ top -b -n 1
# 特定ユーザのプロセスのみ
$ top -u apache
# 特定PIDのみ監視
$ top -p 1234,5678
top 出力例:
top - 14:32:01 up 45 days, 3:21, 2 users, load average: 1.52, 1.38, 1.25
Tasks: 287 total, 2 running, 284 sleeping, 0 stopped, 1 zombie
%Cpu(s): 12.5 us, 3.2 sy, 0.0 ni, 82.1 id, 1.8 wa, 0.0 hi, 0.4 si, 0.0 st
MiB Mem : 15921.4 total, 1234.5 free, 8456.2 used, 6230.7 buff/cache
MiB Swap: 8192.0 total, 7856.3 free, 335.7 used. 6789.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3421 mysql 20 0 2456.3m 1.2g 12340 S 15.2 7.8 234:56.78 mysqld
8765 www-data 20 0 456.2m 234.5m 8901 S 8.3 1.5 45:12.34 apache2
1234 root 20 0 123.4m 56.7m 3456 R 3.1 0.4 12:34.56 monitoring
top 出力の読み方:
| フィールド | 説明 |
|---|---|
us | ユーザ空間のCPU使用率 |
sy | カーネル空間のCPU使用率 |
ni | nice値変更プロセスのCPU使用率 |
id | アイドル率 |
wa | I/O待ち率(高いとディスクボトルネック) |
hi | ハードウェア割り込み |
si | ソフトウェア割り込み |
st | 仮想マシンからスチールされた時間 |
htop のインストールと高度な機能
# インストール
$ sudo dnf install htop # RHEL/CentOS/Fedora
$ sudo apt install htop # Debian/Ubuntu
# ツリー表示で起動
$ htop -t
# 特定ユーザのプロセスのみ
$ htop -u apache
htop は top と比較して以下の利点がある。
- カラフルなビジュアル表示(CPU/メモリバー)
- マウス操作対応
- プロセスツリー表示
- 水平・垂直スクロール
- GUI不要でプロセスのkill、reniceが可能
2.2 vmstat
# 2秒間隔で5回表示
$ vmstat 2 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 335712 1264512 234560 6396148 0 1 12 45 456 890 12 3 83 2 0
1 0 335712 1262340 234568 6396224 0 0 4 68 512 923 10 2 86 2 0
3 1 335712 1258176 234576 6396312 0 0 8 124 678 1102 18 4 74 4 0
1 0 335712 1260480 234584 6396380 0 0 0 52 445 867 8 2 89 1 0
2 0 335712 1259648 234592 6396448 0 0 12 36 498 912 11 3 84 2 0
vmstat 各フィールドの解説:
| カテゴリ | フィールド | 説明 | 警告の目安 |
|---|---|---|---|
| procs | r | 実行待ちプロセス数 | CPU数以上で高負荷 |
| procs | b | I/O待ちブロックプロセス数 | 常時 > 0 でI/Oボトルネック |
| memory | swpd | 使用中スワップ量(KB) | 増加傾向に注意 |
| memory | free | 空きメモリ(KB) | -- |
| memory | buff | バッファキャッシュ(KB) | -- |
| memory | cache | ページキャッシュ(KB) | -- |
| swap | si | スワップイン(KB/s) | > 0 でメモリ不足兆候 |
| swap | so | スワップアウト(KB/s) | > 0 でメモリ不足兆候 |
| io | bi | ブロックデバイス読み込み(blocks/s) | -- |
| io | bo | ブロックデバイス書き込み(blocks/s) | -- |
| system | in | 割り込み数/秒 | -- |
| system | cs | コンテキストスイッチ数/秒 | 極端に高い値に注意 |
2.3 iostat
# パッケージインストール
$ sudo dnf install sysstat
# 拡張情報を2秒間隔で表示
$ iostat -xz 2
Linux 5.15.0 (server01) 04/10/2026 _x86_64_
avg-cpu: %user %nice %system %iowait %steal %idle
12.45 0.00 3.21 1.82 0.00 82.52
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util
sda 8.52 245.67 0.34 3.84 1.23 28.84 12.34 456.78 2.56 17.19 2.45 37.01 0.00 0.00 0.00 0.00 0.00 0.00 0.05 2.34
nvme0n1 45.67 2345.89 1.23 2.62 0.15 51.37 78.90 4567.12 5.67 6.70 0.23 57.89 0.00 0.00 0.00 0.00 0.00 0.00 0.02 5.67
重要な iostat メトリクス:
| メトリクス | 説明 | 注目ポイント |
|---|---|---|
r/s, w/s | 秒間読み書きリクエスト数 | IOPS の指標 |
rkB/s, wkB/s | 秒間読み書きスループット | 帯域幅の指標 |
r_await, w_await | 平均レイテンシ(ms) | SSD: < 1ms, HDD: < 10ms が目安 |
aqu-sz | 平均キュー長 | 高いとデバイスが飽和 |
%util | デバイス使用率 | > 80% で飽和の可能性 |
2.4 mpstat
# 全CPU個別表示、2秒間隔
$ mpstat -P ALL 2
Linux 5.15.0 (server01) 04/10/2026 _x86_64_
02:32:01 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
02:32:03 PM all 12.50 0.00 3.20 1.80 0.10 0.40 0.00 0.00 0.00 82.00
02:32:03 PM 0 25.00 0.00 5.00 0.50 0.50 1.00 0.00 0.00 0.00 68.00
02:32:03 PM 1 10.00 0.00 2.50 3.00 0.00 0.50 0.00 0.00 0.00 84.00
02:32:03 PM 2 8.50 0.00 3.00 1.50 0.00 0.00 0.00 0.00 0.00 87.00
02:32:03 PM 3 15.00 0.00 2.00 2.00 0.00 0.50 0.00 0.00 0.00 80.50
特定のCPUだけ異常に高い場合、IRQの偏りやプロセスのCPUアフィニティ設定を確認する。
2.5 sar
sar (System Activity Reporter) は履歴データを持つ唯一の標準ツールである。
# CPU使用率の履歴(当日)
$ sar -u
# メモリ使用率
$ sar -r
# ディスクI/O
$ sar -d
# ネットワーク統計
$ sar -n DEV
# 特定日のデータ(/var/log/sa/saDD形式)
$ sar -u -f /var/log/sa/sa09
# 時間範囲指定
$ sar -u -s 09:00:00 -e 17:00:00
sar データ収集の設定 (/etc/cron.d/sysstat):
# 10分間隔でデータ収集(デフォルト)
*/10 * * * * root /usr/lib64/sa/sa1 1 1
# 日次サマリ生成
53 23 * * * root /usr/lib64/sa/sa2 -A
sar データの保存期間設定 (/etc/sysconfig/sysstat):
# データ保存日数(デフォルト28日)
HISTORY=28
# 圧縮を有効にする
COMPRESSAFTER=10
# データディレクトリ
SA_DIR=/var/log/sa
2.6 pidstat
# プロセス別CPU使用率(2秒間隔)
$ pidstat -u 2
Linux 5.15.0 (server01) 04/10/2026 _x86_64_
02:35:01 PM UID PID %usr %system %guest %wait %CPU CPU Command
02:35:03 PM 1000 3421 12.50 2.50 0.00 0.50 15.00 0 mysqld
02:35:03 PM 33 8765 6.00 2.00 0.00 0.00 8.00 1 apache2
02:35:03 PM 0 1234 2.50 0.50 0.00 0.00 3.00 2 monitoring
# プロセス別メモリ使用率
$ pidstat -r 2
# プロセス別ディスクI/O
$ pidstat -d 2
# 特定PIDの全メトリクス
$ pidstat -u -r -d -p 3421 2
# スレッド単位で表示
$ pidstat -t -p 3421 2
2.7 free / uptime
# メモリ表示(人間が読みやすい形式)
$ free -h
total used free shared buff/cache available
Mem: 15Gi 8.0Gi 1.2Gi 256Mi 6.1Gi 6.6Gi
Swap: 8.0Gi 327Mi 7.7Gi
# 10秒間隔で更新
$ free -h -s 10
# 合計行を表示
$ free -h -t
free 出力の解釈:
availableが最も重要 -- 新しいプロセスが実際に使えるメモリ量buff/cacheはカーネルがファイルキャッシュとして使用しているが、必要に応じて解放されるavailableがtotalの 10% 未満なら注意が必要
# uptime / ロードアベレージ
$ uptime
14:32:01 up 45 days, 3:21, 2 users, load average: 1.52, 1.38, 1.25
ロードアベレージの解釈:
| 値 | 1分 | 5分 | 15分 | 解釈 |
|---|---|---|---|---|
| 例 | 1.52 | 1.38 | 1.25 | 徐々に増加傾向 |
| 目安 | -- | -- | -- | CPU数以下が正常(4コアなら4.0以下) |
| 低下傾向 | 0.80 | 1.20 | 2.50 | 問題が解消に向かっている |
| 急上昇 | 8.00 | 2.00 | 1.00 | 突発的な負荷増 |
3. /proc ファイルシステムによるモニタリング
/proc はカーネルが公開する仮想ファイルシステムであり、全てのモニタリングツールの情報源である。
主要なファイル
# CPU情報
$ cat /proc/cpuinfo | grep "model name" | head -1
model name : Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz
# CPU使用率の生データ
$ cat /proc/stat | head -2
cpu 1234567 890 345678 9012345 67890 1234 5678 0 0 0
cpu0 308641 222 86419 2253086 16972 308 1419 0 0 0
# メモリ情報
$ cat /proc/meminfo | head -10
MemTotal: 16303564 kB
MemFree: 1264512 kB
MemAvailable: 6953924 kB
Buffers: 234560 kB
Cached: 6161588 kB
SwapCached: 12340 kB
Active: 8456320 kB
Inactive: 5234680 kB
Active(anon): 6123456 kB
Inactive(anon): 1234567 kB
# ディスクI/O統計
$ cat /proc/diskstats | grep -E "sda |nvme0n1 "
# ネットワーク統計
$ cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
eth0: 12345678901 9876543 0 0 0 0 0 123456 9876543210 8765432 0 0 0 0 0 0
# 特定プロセスの情報(PID 3421)
$ cat /proc/3421/status | head -15
Name: mysqld
Umask: 0077
State: S (sleeping)
Tgid: 3421
Ngid: 0
Pid: 3421
PPid: 1
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 1000
VmPeak: 2516124 kB
VmSize: 2516124 kB
VmRSS: 1258291 kB
# プロセスのファイルディスクリプタ数
$ ls /proc/3421/fd | wc -l
156
# プロセスのメモリマップ
$ cat /proc/3421/maps | head -5
# システム全体のファイルディスクリプタ使用状況
$ cat /proc/sys/fs/file-nr
4832 0 9223372036854775807
# (割当済み 空き 最大値)
/proc を使ったカスタムモニタリングスクリプト
#!/bin/bash
# /proc からCPU使用率を計算するスクリプト
get_cpu_usage() {
local cpu_line1 cpu_line2
local user1 nice1 system1 idle1 iowait1
local user2 nice2 system2 idle2 iowait2
cpu_line1=$(head -1 /proc/stat)
sleep 1
cpu_line2=$(head -1 /proc/stat)
read -r _ user1 nice1 system1 idle1 iowait1 _ <<< "$cpu_line1"
read -r _ user2 nice2 system2 idle2 iowait2 _ <<< "$cpu_line2"
local total1=$((user1 + nice1 + system1 + idle1 + iowait1))
local total2=$((user2 + nice2 + system2 + idle2 + iowait2))
local total_diff=$((total2 - total1))
local idle_diff=$((idle2 - idle1))
if [ $total_diff -gt 0 ]; then
local usage=$(( (total_diff - idle_diff) * 100 / total_diff ))
echo "CPU Usage: ${usage}%"
fi
}
get_cpu_usage
4. パフォーマンスメトリクス
4.1 CPU メトリクス
# CPU使用率の包括的確認
$ mpstat -P ALL 1 1
# コンテキストスイッチ数
$ vmstat 1 | awk 'NR>2{print "CS:", $12}'
# 実行キュー長
$ vmstat 1 | awk 'NR>2{print "Run Queue:", $1}'
# CPU別割り込み数
$ cat /proc/interrupts | head -5
CPU0 CPU1 CPU2 CPU3
0: 48 0 0 0 IR-IO-APIC 2-edge timer
1: 0 3 0 0 IR-IO-APIC 1-edge i8042
8: 0 0 1 0 IR-IO-APIC 8-edge rtc0
9: 0 0 0 3 IR-IO-APIC 9-fasteoi acpi
4.2 メモリメトリクス
# 詳細なメモリ使用状況
$ cat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|Dirty|Writeback|Slab"
MemTotal: 16303564 kB
MemFree: 1264512 kB
MemAvailable: 6953924 kB
Buffers: 234560 kB
Cached: 6161588 kB
SwapTotal: 8388608 kB
SwapFree: 8047452 kB
Dirty: 4520 kB
Writeback: 0 kB
Slab: 456780 kB
# ページフォルト確認
$ sar -B 1 3
02:40:01 PM pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s
02:40:02 PM 12.00 456.00 8901.00 0.00 5678.00 0.00 0.00 0.00
# NUMA メモリ統計
$ numastat
node0 node1
numa_hit 1234567890 1234567890
numa_miss 1234 5678
numa_foreign 5678 1234
interleave_hit 12345 12345
local_node 1234567890 1234567890
other_node 1234 5678
4.3 ディスク I/O メトリクス
# ディスクレイテンシ確認
$ iostat -xz 1
# r_await, w_await を確認
# I/Oスケジューラキューの状態
$ cat /sys/block/sda/queue/nr_requests
128
# ディスク使用率の推移
$ sar -d 1 5
# ファイルシステムの状態
$ df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda1 xfs 50G 35G 16G 69% /
/dev/nvme0n1p1 ext4 200G 120G 71G 63% /data
tmpfs tmpfs 7.8G 256M 7.6G 4% /dev/shm
4.4 ネットワークメトリクス
# ネットワークインターフェース統計
$ sar -n DEV 1 3
02:45:01 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
02:45:02 PM eth0 8901.00 7654.00 4567.89 3456.78 0.00 0.00 1.00 3.65
# TCP接続統計
$ ss -s
Total: 1234
TCP: 567 (estab 345, closed 89, orphaned 12, timewait 67)
Transport Total IP IPv6
RAW 2 1 1
UDP 23 15 8
TCP 478 312 166
INET 503 328 175
FRAG 0 0 0
# ネットワークエラー統計
$ netstat -s | grep -i error
123 packets received with checksum errors
0 packet receive errors
45 send buffer errors
# TCPリトランスミッション
$ sar -n TCP,ETCP 1 3
5. ストレステスト
stress-ng
# インストール
$ sudo dnf install stress-ng
# CPU負荷テスト(4ワーカー、60秒間)
$ stress-ng --cpu 4 --timeout 60s --metrics-brief
stress-ng: info: [12345] dispatching hogs: 4 cpu
stress-ng: info: [12345] successful run completed in 60.01s
stress-ng: info: [12345] stressor bogo ops real time usr time sys time bogo ops/s
stress-ng: info: [12345] cpu 123456 60.00s 239.87s 0.13s 2057.60
# メモリ負荷テスト(2GB使用、4ワーカー)
$ stress-ng --vm 4 --vm-bytes 2G --timeout 60s --metrics-brief
# ディスクI/O負荷テスト
$ stress-ng --hdd 2 --hdd-bytes 1G --timeout 60s --metrics-brief
# 混合負荷テスト
$ stress-ng --cpu 2 --vm 2 --vm-bytes 1G --hdd 1 --timeout 120s
# 特定のCPUストレッサ(行列計算)
$ stress-ng --matrix 4 --timeout 30s
# ネットワーク負荷テスト
$ stress-ng --sock 4 --timeout 60s
ストレステスト中のモニタリング例:
# ターミナル1: ストレステスト実行
$ stress-ng --cpu 4 --vm 2 --vm-bytes 1G --timeout 120s
# ターミナル2: リアルタイム監視
$ vmstat 2
# ターミナル3: プロセス別確認
$ pidstat -u -r 2
6. プロファイリング
6.1 perf
perf はカーネル組み込みのプロファイリングツールで、ハードウェアパフォーマンスカウンタにアクセスできる。
# インストール
$ sudo dnf install perf
# システム全体のCPUプロファイリング(10秒間)
$ sudo perf stat -a sleep 10
Performance counter stats for 'system wide':
80,234.56 msec cpu-clock # 8.023 CPUs utilized
234,567 context-switches # 29.236 /sec
5,678 cpu-migrations # 0.708 /sec
123,456 page-faults # 15.389 /sec
45,678,901,234 cycles # 5.694 GHz
23,456,789,012 instructions # 0.51 insn per cycle
3,456,789,012 branches # 430.752 M/sec
45,678,901 branch-misses # 1.32% of all branches
10.001234567 seconds time elapsed
# 特定コマンドのプロファイリング
$ sudo perf stat ./my_application
$ sudo perf stat -e cycles,instructions,cache-misses ./my_application
# CPU時間のサンプリング(フレームグラフ用)
$ sudo perf record -F 99 -a -g -- sleep 30
$ sudo perf report --stdio
# 関数別ホットスポット
$ sudo perf top -F 49
# 特定プロセスのプロファイリング
$ sudo perf record -F 99 -p 3421 -g -- sleep 30
$ sudo perf report
perf report 出力例:
# Overhead Command Shared Object Symbol
# ........ ....... .................. .............................
15.23% mysqld mysqld [.] row_search_mvcc
8.45% mysqld libc-2.31.so [.] __memmove_avx_unaligned
6.78% mysqld mysqld [.] buf_page_get_gen
5.12% mysqld mysqld [.] ha_innobase::index_read
4.56% mysqld [kernel.kallsyms] [k] copy_user_enhanced_fast_string
6.2 strace / ltrace
# システムコールのトレース
$ strace -c ls /tmp
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
25.23 0.000456 22 20 getdents64
18.45 0.000334 16 20 10 openat
12.78 0.000231 11 20 fstat
10.56 0.000191 9 20 close
8.34 0.000151 15 10 mmap
6.12 0.000111 11 10 mprotect
5.67 0.000103 10 10 read
4.56 0.000082 82 1 execve
3.45 0.000062 31 2 write
2.34 0.000042 21 2 brk
2.50 0.000045 9 5 rt_sigaction
------ ----------- ----------- --------- --------- ----------------
100.00 0.001808 120 10 total
# 特定のシステムコールだけトレース
$ strace -e trace=open,read,write -p 3421
# タイムスタンプ付きで出力
$ strace -tt -p 3421
# ファイルI/Oに関するシステムコールのみ
$ strace -e trace=file -p 3421
# ネットワーク関連のシステムコールのみ
$ strace -e trace=network -p 3421
# ライブラリコールのトレース
$ ltrace -c ./my_application
% time seconds usecs/call calls function
------ ----------- ----------- --------- --------------------
45.23 0.012345 1234 10 malloc
25.67 0.007890 789 10 free
15.45 0.004567 456 10 strlen
13.65 0.003456 345 10 strcmp
------ ----------- ----------- --------- --------------------
100.00 0.028258 40 total
7. チューニング方法論
USE メソッド (Utilization, Saturation, Errors)
Brendan Gregg が提唱する体系的なパフォーマンス分析手法。
| リソース | 使用率 (U) | 飽和度 (S) | エラー (E) |
|---|---|---|---|
| CPU | mpstat -P ALL | vmstat の r列 | perf stat |
| メモリ | free -m, vmstat | vmstat の si/so列 | `dmesg |
| ディスクI/O | iostat -xz の %util | iostat の aqu-sz | /sys/devices/.../ioerr_cnt |
| ネットワーク | sar -n DEV | ss -ntp のRecv-Q | netstat -s のerrors |
RED メソッド (Rate, Errors, Duration)
マイクロサービスに適した手法。
- Rate (リクエスト率): 秒間処理リクエスト数
- Errors (エラー率): 失敗したリクエストの割合
- Duration (応答時間): リクエスト処理にかかる時間
チューニングの手順
1. ベースライン計測
↓
2. ワークロード特性の把握
↓
3. ボトルネックの特定(USE メソッド)
↓
4. 仮説の立案
↓
5. 変更の実施(一度に一つ)
↓
6. 効果の計測
↓
7. 結果の評価 → 不十分なら 3 に戻る
↓
8. 文書化
8. CPU チューニング
8.1 nice / renice
プロセスの優先度を制御する。nice値は -20(最高優先度)から 19(最低優先度)の範囲。
# nice値を指定してプロセス起動(低優先度でバックアップ)
$ nice -n 10 tar czf /backup/data.tar.gz /data
# 実行中プロセスの優先度変更
$ renice -n 5 -p 3421
3421 (process ID) old priority 0, new priority 5
# ユーザの全プロセスの優先度変更
$ renice -n 10 -u www-data
# 現在のnice値確認
$ ps -eo pid,ni,comm | head -10
PID NI COMMAND
1 0 systemd
2 0 kthreadd
3421 0 mysqld
8765 5 backup_script
8.2 taskset (CPU アフィニティ)
# プロセスのCPUアフィニティ確認
$ taskset -p 3421
pid 3421's current affinity mask: f
# f = 1111 (バイナリ) = CPU 0,1,2,3
# CPU 0,1 だけに制限して起動
$ taskset -c 0,1 ./my_application
# 実行中プロセスのアフィニティ変更
$ taskset -p -c 2,3 3421
pid 3421's current affinity list: 0-3
pid 3421's new affinity list: 2,3
# CPUマスクで指定(ビットマスク)
$ taskset -p 0x0c 3421 # CPU 2,3 (0b1100 = 0x0c)
CPU アフィニティの用途:
- キャッシュ効率の向上(L1/L2キャッシュの有効活用)
- NUMA環境でのローカルメモリアクセス最適化
- リアルタイム処理用CPUの隔離
- ネットワーク処理とアプリケーション処理のCPU分離
8.3 cgroups によるリソース制御
cgroups v2 (systemd 統合)
# cgroups v2 が有効か確認
$ mount | grep cgroup2
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)
# systemd によるCPU制限
$ sudo systemctl set-property httpd.service CPUQuota=200%
# 200% = 2コア分
# systemd によるメモリ制限
$ sudo systemctl set-property httpd.service MemoryMax=2G
# スライス(グループ)の作成
$ sudo systemctl set-property user-1000.slice CPUQuota=400%
$ sudo systemctl set-property user-1000.slice MemoryMax=8G
drop-in ファイルで永続設定:
# /etc/systemd/system/httpd.service.d/resources.conf
[Service]
CPUQuota=200%
MemoryMax=2G
MemoryHigh=1800M
IOWeight=100
cgroups v2 手動設定
# cgroup 作成
$ sudo mkdir /sys/fs/cgroup/myapp
# CPU制限(100000 usec 中 50000 usec = 50%)
$ echo "50000 100000" | sudo tee /sys/fs/cgroup/myapp/cpu.max
# メモリ制限(1GB)
$ echo "1073741824" | sudo tee /sys/fs/cgroup/myapp/memory.max
# プロセスを cgroup に追加
$ echo 3421 | sudo tee /sys/fs/cgroup/myapp/cgroup.procs
# 現在のリソース使用状況確認
$ cat /sys/fs/cgroup/myapp/cpu.stat
usage_usec 1234567890
user_usec 987654321
system_usec 246913569
nr_periods 12345
nr_throttled 678
throttled_usec 901234
$ cat /sys/fs/cgroup/myapp/memory.current
536870912
9. メモリチューニング
9.1 swappiness
swappiness はカーネルがスワップを使用する積極性を制御するパラメータ。
# 現在の値確認
$ cat /proc/sys/vm/swappiness
60
# 一時的な変更
$ sudo sysctl vm.swappiness=10
# 永続的な変更
$ echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.d/99-tuning.conf
$ sudo sysctl -p /etc/sysctl.d/99-tuning.conf
swappiness 推奨値:
| 環境 | 推奨値 | 理由 |
|---|---|---|
| データベースサーバ | 1-10 | メモリ内データへの高速アクセスが重要 |
| Webサーバ | 10-30 | バランスの良い設定 |
| デスクトップ | 60 (デフォルト) | 一般用途に適切 |
| ファイルサーバ | 30-50 | キャッシュ活用とスワップのバランス |
9.2 Huge Pages
通常のページサイズ(4KB)より大きなページ(2MB, 1GB)を使用することで、TLBミスを削減しパフォーマンスを向上させる。
# 現在の設定確認
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 245760 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
# Huge Pages の設定(1024 x 2MB = 2GB)
$ echo 1024 | sudo tee /proc/sys/vm/nr_hugepages
# 永続設定
$ cat >> /etc/sysctl.d/99-hugepages.conf << 'EOF'
vm.nr_hugepages = 1024
vm.hugetlb_shm_group = 1000
EOF
# Transparent Huge Pages (THP) の状態確認
$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
# THP を無効にする(データベースワークロードで推奨)
$ echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
$ echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
THP 無効化の永続設定 (GRUB):
# /etc/default/grub
GRUB_CMDLINE_LINUX="... transparent_hugepage=never"
# GRUB設定更新
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
9.3 OOM Killer
メモリ枯渇時にカーネルが自動的にプロセスを停止する機能。
# OOM スコアの確認
$ cat /proc/3421/oom_score
150
# OOM スコア調整(-1000 から 1000)
# -1000 = OOM Killer から完全に除外
# 1000 = 最優先で kill される
$ echo -1000 | sudo tee /proc/3421/oom_score_adj # 保護
$ echo 500 | sudo tee /proc/8765/oom_score_adj # 優先的にkill
# OOM Killer の動作ログ確認
$ dmesg | grep -i "oom\|out of memory"
[12345.678901] Out of memory: Killed process 9876 (java) total-vm:4567890kB, anon-rss:3456789kB
# systemd サービスでの OOM 設定
# /etc/systemd/system/critical-app.service
[Service]
OOMScoreAdjust=-900
メモリ関連の追加チューニング:
# vm.overcommit の設定
# 0: ヒューリスティック(デフォルト)
# 1: 常にオーバーコミット許可
# 2: オーバーコミット禁止
$ echo 2 | sudo tee /proc/sys/vm/overcommit_memory
# オーバーコミット比率(overcommit_memory=2の場合)
# 物理メモリの80% + スワップ
$ echo 80 | sudo tee /proc/sys/vm/overcommit_ratio
# ダーティページの制御
$ sysctl -w vm.dirty_ratio=15 # 全メモリの15%まで
$ sysctl -w vm.dirty_background_ratio=5 # バックグラウンド書き込み開始
$ sysctl -w vm.dirty_expire_centisecs=3000 # 30秒後に期限切れ
# ページキャッシュのドロップ(デバッグ用)
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
# 1=ページキャッシュ、2=dentryとinode、3=両方
10. ディスク I/O チューニング
10.1 I/O スケジューラ
# 現在のスケジューラ確認
$ cat /sys/block/sda/queue/scheduler
[mq-deadline] kyber bfq none
$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber bfq
I/O スケジューラ比較:
| スケジューラ | 特徴 | 適したワークロード |
|---|---|---|
none | 最小レイテンシ、順序変更なし | NVMe SSD、仮想マシン |
mq-deadline | デッドライン保証、リードに優先度 | DB、汎用SSD |
bfq | 公平性重視、帯域配分 | デスクトップ、複数ユーザ |
kyber | 低レイテンシ、シンプル | 高速SSD |
# スケジューラの変更(一時的)
$ echo "mq-deadline" | sudo tee /sys/block/sda/queue/scheduler
# 永続設定(udevルール)
# /etc/udev/rules.d/60-io-scheduler.rules
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/scheduler}="mq-deadline"
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"
# udevルール適用
$ sudo udevadm control --reload-rules
$ sudo udevadm trigger
10.2 readahead
# 現在のreadahead値確認(単位: 512バイトセクター)
$ cat /sys/block/sda/queue/read_ahead_kb
128
# readahead を増やす(シーケンシャルリードが多い場合)
$ echo 1024 | sudo tee /sys/block/sda/queue/read_ahead_kb
# blockdev コマンドでも設定可能
$ sudo blockdev --getra /dev/sda
256
$ sudo blockdev --setra 2048 /dev/sda # 1024KB (2048 * 512 bytes)
10.3 ionice
# I/O優先度クラス
# 1: リアルタイム (0-7, 0が最高)
# 2: ベストエフォート (0-7, 0が最高) [デフォルト]
# 3: アイドル
# バックアップをアイドル優先度で実行
$ ionice -c 3 tar czf /backup/data.tar.gz /data
# ベストエフォート・低優先度で実行
$ ionice -c 2 -n 7 dd if=/dev/sda of=/backup/disk.img bs=1M
# 実行中プロセスのI/O優先度確認
$ ionice -p 3421
best-effort: prio 4
# 実行中プロセスのI/O優先度変更
$ ionice -c 2 -n 0 -p 3421
ディスクI/O 追加チューニング:
# キューの深さ調整
$ echo 256 | sudo tee /sys/block/sda/queue/nr_requests
# ライトバックキャッシュの有効化確認
$ cat /sys/block/sda/queue/write_cache
write back
# ファイルシステムマウントオプション(/etc/fstab)
# noatime: アクセス時間を更新しない(読み取り性能向上)
# nobarrier: バリアを無効化(バッテリーバックアップRAID向け)
/dev/sda1 /data xfs defaults,noatime 0 2
# ext4 のジャーナルモード
# data=writeback: 最高速(データ整合性リスクあり)
# data=ordered: バランス(デフォルト)
# data=journal: 最安全(最も遅い)
11. ネットワークチューニング
TCP パラメータチューニング
# /etc/sysctl.d/99-network-tuning.conf
# --- TCP バッファサイズ ---
# 最小、デフォルト、最大(バイト)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
# --- TCP コネクション管理 ---
# SYNバックログキューサイズ
net.ipv4.tcp_max_syn_backlog = 8192
# リッスンバックログ
net.core.somaxconn = 65535
# TIME_WAIT ソケットの再利用
net.ipv4.tcp_tw_reuse = 1
# FIN-WAIT-2 タイムアウト(秒)
net.ipv4.tcp_fin_timeout = 15
# キープアライブ設定
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 5
# --- TCP パフォーマンス ---
# ウィンドウスケーリング
net.ipv4.tcp_window_scaling = 1
# TCP Fast Open
net.ipv4.tcp_fastopen = 3
# 輻輳制御アルゴリズム
net.ipv4.tcp_congestion_control = bbr
# BBR を有効にする前にモジュールロード
# $ sudo modprobe tcp_bbr
# $ echo "tcp_bbr" | sudo tee -a /etc/modules-load.d/bbr.conf
# --- ネットワークキュー ---
net.core.netdev_max_backlog = 5000
net.core.netdev_budget = 600
# --- ポート範囲 ---
net.ipv4.ip_local_port_range = 1024 65535
# 設定適用
$ sudo sysctl --system
# 現在のTCP輻輳制御アルゴリズム確認
$ sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = bbr
# 利用可能な輻輳制御アルゴリズム一覧
$ sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic bbr
# ネットワーク接続状態の統計
$ ss -s
# 接続状態別カウント
$ ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
345 ESTAB
89 TIME-WAIT
23 LISTEN
12 CLOSE-WAIT
5 SYN-SENT
2 FIN-WAIT-2
NIC (ネットワークインターフェースカード) チューニング:
# 現在のNIC設定確認
$ ethtool eth0
Settings for eth0:
Speed: 10000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
# リングバッファサイズ確認
$ ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX: 4096
TX: 4096
Current hardware settings:
RX: 256
TX: 256
# リングバッファサイズ増加
$ sudo ethtool -G eth0 rx 4096 tx 4096
# オフロード機能確認
$ ethtool -k eth0 | grep -E "tcp-segmentation|generic-receive"
tcp-segmentation-offload: on
generic-receive-offload: on
# 割り込みコアレッシング調整
$ sudo ethtool -C eth0 rx-usecs 100 tx-usecs 100
12. モニタリングスタック概要
12.1 Prometheus + Grafana
Prometheus 構成
# /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_timeout: 10s
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- "localhost:9093"
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "node_exporter"
static_configs:
- targets:
- "server01:9100"
- "server02:9100"
- "server03:9100"
relabel_configs:
- source_labels: [__address__]
target_label: instance
regex: '(.+):9100'
replacement: '${1}'
- job_name: "mysqld_exporter"
static_configs:
- targets: ["server01:9104"]
Node Exporter のインストール
# ダウンロードとインストール
$ wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
$ tar xzf node_exporter-1.7.0.linux-amd64.tar.gz
$ sudo cp node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
# systemd サービス作成
$ sudo cat > /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.processes \
--collector.tcpstat \
--web.listen-address=:9100
[Install]
WantedBy=multi-user.target
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now node_exporter
アラートルール例
# /etc/prometheus/alert_rules.yml
groups:
- name: system_alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage is above 80% for 5 minutes (current: {{ $value }}%)"
- alert: HighMemoryUsage
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
for: 5m
labels:
severity: critical
annotations:
summary: "High memory usage on {{ $labels.instance }}"
- alert: DiskSpaceRunningLow
expr: (1 - node_filesystem_avail_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes) * 100 > 85
for: 10m
labels:
severity: warning
annotations:
summary: "Disk space low on {{ $labels.instance }}:{{ $labels.mountpoint }}"
- alert: HighDiskIOLatency
expr: rate(node_disk_read_time_seconds_total[5m]) / rate(node_disk_reads_completed_total[5m]) > 0.01
for: 5m
labels:
severity: warning
annotations:
summary: "High disk I/O latency on {{ $labels.instance }}"
Grafana ダッシュボード
# Grafana インストール (RHEL/CentOS)
$ sudo dnf install -y grafana
$ sudo systemctl enable --now grafana-server
# データソース追加 (API)
$ curl -X POST http://admin:admin@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://localhost:9090",
"access": "proxy",
"isDefault": true
}'
12.2 Nagios / Zabbix
Nagios 基本設定
# /etc/nagios/nagios.cfg(主要設定)
cfg_dir=/etc/nagios/conf.d
# ホスト定義
# /etc/nagios/conf.d/server01.cfg
define host {
use linux-server
host_name server01
alias Production Web Server 01
address 192.168.1.101
max_check_attempts 5
check_period 24x7
notification_interval 30
notification_period 24x7
}
define service {
use generic-service
host_name server01
service_description CPU Load
check_command check_nrpe!check_load
check_interval 5
retry_interval 1
}
define service {
use generic-service
host_name server01
service_description Memory Usage
check_command check_nrpe!check_mem
check_interval 5
retry_interval 1
}
define service {
use generic-service
host_name server01
service_description Disk Usage
check_command check_nrpe!check_disk
check_interval 10
retry_interval 2
}
Zabbix 概要
# Zabbix エージェントインストール
$ sudo dnf install zabbix-agent2
# 設定
# /etc/zabbix/zabbix_agent2.conf
Server=192.168.1.10
ServerActive=192.168.1.10
Hostname=server01
モニタリングスタック比較:
| 特徴 | Prometheus + Grafana | Nagios | Zabbix |
|---|---|---|---|
| データモデル | 時系列 (Pull型) | チェック結果 | 時系列 (Push/Pull) |
| スケーラビリティ | 高 | 中 | 高 |
| 可視化 | 優秀 (Grafana) | 基本的 | 良好 |
| アラート | AlertManager | 内蔵 | 内蔵 |
| 設定方法 | YAML | テキスト設定 | Web GUI |
| クラウドネイティブ | 最適 | 非対応 | 部分対応 |
| 学習コスト | 中 | 高 | 中 |
| エコシステム | 豊富 (Exporter) | プラグイン | テンプレート |
13. トラブルシューティング
よくある問題と対処法
CPU使用率が高い場合
# 1. どのプロセスがCPUを消費しているか特定
$ top -o %CPU -b -n 1 | head -15
# 2. そのプロセスの詳細確認
$ pidstat -p <PID> -u 1 5
# 3. strace でシステムコールを確認
$ sudo strace -c -p <PID>
# 4. perf でホットスポットを特定
$ sudo perf top -p <PID>
# 5. 対処: nice値の調整、CPU制限、プロセスの最適化
メモリリークの調査
# 1. メモリ使用量の多いプロセスを特定
$ ps aux --sort=-%mem | head -10
# 2. プロセスのメモリ詳細
$ cat /proc/<PID>/status | grep -E "VmSize|VmRSS|VmSwap"
$ pmap -x <PID> | tail -5
# 3. メモリ使用量の推移を監視
$ pidstat -r -p <PID> 5
# 4. Slab メモリの確認
$ sudo slabtop -s c | head -15
# 5. OOM Killer のログ確認
$ journalctl -k | grep -i "oom\|out of memory"
ディスクI/O遅延の調査
# 1. I/O待ちが発生しているか確認
$ iostat -xz 1 | grep -v "^$"
# 2. I/Oを大量に発生させているプロセスを特定
$ sudo iotop -o
# 3. pidstat でプロセス別I/O確認
$ pidstat -d 1
# 4. 対処: ionice、スケジューラ変更、readahead調整
ネットワーク遅延の調査
# 1. ネットワーク統計確認
$ ss -s
# 2. パケットロス/リトランスミッション確認
$ netstat -s | grep -i "retransmit\|error\|drop"
# 3. TCP接続状態確認
$ ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
# 4. インターフェースエラー確認
$ ip -s link show eth0
# 5. 対処: バッファ調整、輻輳制御変更、NICチューニング
14. ベストプラクティス
モニタリング
- ベースラインを確立する -- 正常時のメトリクスを記録し、異常検知の基準とする
- アラートの閾値を段階的に設定する -- Warning と Critical を分ける
- ダッシュボードを階層化する -- 概要 → 詳細 → 個別リソースの順
- ログとメトリクスを関連付ける -- 問題発生時に素早く原因特定できるようにする
- モニタリング自体を監視する -- Prometheus が落ちていないか別の仕組みで検知
パフォーマンスチューニング
- 計測ファースト -- 「遅い気がする」ではなく数値で判断する
- 一度に一つの変更 -- 効果を正確に測定するため
- 変更を文書化する -- 何を、なぜ、どう変更したかを記録
- 本番前にテスト -- ステージング環境で効果と副作用を検証
- 定期的に見直す -- ワークロードの変化に合わせてチューニングを更新
- カーネルデフォルトを尊重する -- 理由なく変更しない。デフォルト値は多くの場合で最適
チューニング推奨値サマリ
# /etc/sysctl.d/99-performance-tuning.conf
# --- メモリ ---
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
vm.overcommit_memory = 0
vm.min_free_kbytes = 65536
# --- ネットワーク ---
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_congestion_control = bbr
# --- ファイルシステム ---
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
15. 参考資料
- 書籍:
- Brendan Gregg 著『Systems Performance: Enterprise and the Cloud』(2nd Edition)
- Brendan Gregg 著『BPF Performance Tools』
- Webリソース:
- man ページ:
man top,man vmstat,man iostat,man sar,man perf,man sysctl - カーネルドキュメント:
/usr/share/doc/kernel-doc-*/Documentation/または kernel.org
最終更新: 2026-04-10
対象OS: RHEL 8/9, Ubuntu 22.04/24.04, 及び systemd ベースの主要Linuxディストリビューション