RHEL 上級 #2 カーネルチューニング — sysctl、tuned、kdump

読了 10分

#1 ブートプロセス でカーネルがどうメモリに上がるかを見ました。この記事はその次の段階です。ブートが終わったカーネルに対して、ワークロードに合うようパラメータを調整し、ワークロードプロファイルを 1 行で切り替え、万が一カーネルがパニックで死んだときにその時点のメモリダンプを取って事後解析するツールまで 1 サイクルで扱います。

RHEL 上級 シリーズでこの記事の位置:

  • #1 ブートプロセス — GRUB2、dracut、レスキューモード
  • #2 カーネルチューニング — sysctl、tuned、kdump ← この記事
  • #3 パフォーマンス分析 — sar、top/htop、iostat、vmstat、perf
  • #4 SELinux 上級 — ポリシー作成、audit2allow
  • #5 セキュリティ強化 — auditd、OpenSCAP、FIPS
  • #6 Subscription / Satellite / Insights
  • #7 Cockpit による GUI 管理と Web Console

3 つのツールの位置づけ #

ツール何を調整するか適用タイミング
sysctlカーネルパラメータ (vm、net、kernel、fs)ランタイム即時 + ブートごと
tuned事前定義されたワークロードプロファイル (sysctl + cpufreq + io-scheduler 束)プロファイル適用時に即時
kdumpカーネルパニック時点でメモリダンプキャプチャパニック発生時点

sysctl は 1 行単位で直接触るツール、tuned はその 1 行をワークロード単位で束ねて一度に適用する抽象化、kdump はカーネルが死んだときだけ働くセーフティネットです。3 つを揃えて使うと運用で扱える 1 セットになります。

sysctl — ランタイムカーネルパラメータ #

Linux カーネルは /proc/sys/ 以下に自身のパラメータをファイルのように公開します。sysctl はそのファイルを読み書きするコマンドです。

基本使用
# 全パラメータを表示
$ sudo sysctl -a | less

# 特定パラメータを読む
$ sudo sysctl vm.swappiness
vm.swappiness = 30

# 即時変更 (再起動で消える)
$ sudo sysctl -w vm.swappiness=10

vm.swappiness のようなドット区切りキーは /proc/sys/vm/swappiness の表記にすぎません。

同等の 2 つ
$ sudo sysctl vm.swappiness
$ cat /proc/sys/vm/swappiness   # 同じ値

永続設定 — /etc/sysctl.d/ #

ブートごとに適用するにはファイルに書いておく必要があります。RHEL 9 の標準は /etc/sysctl.d/*.conf にモジュール式で書く方法です。

/etc/sysctl.d/99-tune.conf
# メモリ/スワップ
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 5

# ネットワーク
net.core.somaxconn = 4096
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1

# ファイルディスクリプタ
fs.file-max = 2097152
適用
# 特定ファイルだけ
$ sudo sysctl -p /etc/sysctl.d/99-tune.conf

# 標準位置をすべて (ブート時に自動で起こる動作)
$ sudo sysctl --system

/etc/sysctl.conf という単一ファイルも互換のため残っていますが、運用では /etc/sysctl.d/ の分離ファイル が標準です。変更の出所をファイル名で追跡しやすく、Ansible/パッケージで束ごと配るのにも適しています。

優先順位とファイル名規則 #

sysctl --system は次のディレクトリを辞書順で読みます。

読み順 (後で読んだ値が勝つ)
/etc/sysctl.d/*.conf
/run/sysctl.d/*.conf
/usr/lib/sysctl.d/*.conf
/etc/sysctl.conf

同じディレクトリの中では ファイル名アルファベット順。そこで運用設定は通常 99- 接頭辞をつけて最後に適用されるようにします (例: 99-tune.conf)。

よく触るキー #

運用で頻繁に手を入れるキー束。

キー意味推奨
vm.swappinessページキャッシュ vs スワップ選好度 (0=スワップ回避、100=積極的)サーバ 10、DB 1 ~ 5
vm.dirty_ratioダーティページ上限(%) — 超えると同期 flush20
vm.overcommit_memoryメモリオーバーコミットポリシーDB/Redis なら 1
net.core.somaxconnlisten() 待ち行列の最大4096 ~
net.ipv4.tcp_max_syn_backlogSYN 待ち行列4096 ~
net.ipv4.ip_local_port_rangeephemeral ポート範囲1024 65535
fs.file-maxシステム全体のファイルディスクリプタ上限200 万 ~
kernel.pid_maxPID 最大値コンテナが多い場合 4194304

DB ワークロード、Web サーバ、コンテナホストで触るキー束が違います。それぞれの標準束を一度決めて /etc/sysctl.d/ に配ると、新しいマシンを立てるたびにこのファイルだけコピーするやり方で一貫性を保てます。

変更が効かないケース #

  • 読み取り専用パラメータkernel.osrelease のようにブート後は変えられないキー。変更を試みると permission denied
  • ブート時にだけ意味のあるパラメータ — 一部の vm.* はランタイム変更可能ですが、kernel.numa_balancing のような値はブートパラメータで渡さないと意図通り動きません。
  • コンテナの中/proc/sys/ の一部はコンテナ namespace で隔離されています。ホストで変えれば効きます。

tuned — ワークロードプロファイル #

tuned は sysctl 値 + CPU governor + I/O scheduler + ディスク readahead といった複数のチューニング項目を プロファイル として束ねて一度に適用するデーモンです。RHEL 9 にデフォルトでインストールされ、ブート時に自動起動します。

有効化確認
$ sudo systemctl status tuned
$ sudo systemctl enable --now tuned

プロファイル一覧と適用 #

tuned-adm 基本
# 利用可能なプロファイル一覧
$ sudo tuned-adm list
Available profiles:
- accelerator-performance
- balanced                     - General non-specialized tuned profile
- desktop
- hpc-compute
- latency-performance          - Optimize for low latency at the cost of throughput
- network-latency
- network-throughput
- powersave
- throughput-performance       - Broadly applicable tuning that provides excellent...
- virtual-guest                - Optimize for running inside a virtual guest
- virtual-host                 - Optimize for running KVM guests
Current active profile: throughput-performance

# 現在のプロファイル
$ sudo tuned-adm active

# プロファイル変更
$ sudo tuned-adm profile virtual-guest

# 推奨プロファイル (RHEL がマシン環境を見て推薦)
$ sudo tuned-adm recommend
virtual-guest

tuned-adm recommend はベアメタル/仮想マシン/ノートを自動で区別して提案します。EC2 のような仮想インスタンスで RHEL を立てると virtual-guest を推薦するという具合です。

よく使うプロファイル #

プロファイル位置づけ
throughput-performance一般サーバのデフォルト。CPU governor performance、dirty ratio 緩和
latency-performance応答時間が最優先 — 取引システム、リアルタイム処理
network-latencylatency-performance + ネットワークキューチューニング
network-throughput大処理量ネットワーク (10G+ NIC)
virtual-guestKVM/AWS/GCP ゲストのデフォルト
virtual-hostKVM ホスト
powersave電力節約 (ノートなど)
accelerator-performanceGPU/アクセラレータワークロード

DB が回るマシンなら throughput-performance または latency-performance、クラウドゲストなら virtual-guest を出発点に。

プロファイルの中身 #

プロファイル定義
$ ls /usr/lib/tuned/throughput-performance/
tuned.conf

$ cat /usr/lib/tuned/throughput-performance/tuned.conf
[main]
summary=...
include=latency-performance

[cpu]
force_latency=cstate.id:3|3
governor=performance
energy_perf_bias=performance
min_perf_pct=100

[disk]
readahead=>4096

[sysctl]
kernel.sched_min_granularity_ns = 10000000
kernel.sched_wakeup_granularity_ns = 15000000
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
vm.swappiness=10
net.core.busy_read=50
net.core.busy_poll=50
net.ipv4.tcp_fastopen=3

[sysctl] セクションを見ると結局 sysctl キーの束です。tuned が適用されている間はそれらのキーがプロファイル値に保たれ、プロファイルを切ったり別のプロファイルに切り替えると新しい値で再適用されます。

カスタムプロファイル #

既存プロファイルを継承して一部だけ上書きするのが一般的です。

カスタムプロファイルディレクトリ
$ sudo mkdir -p /etc/tuned/myapp-throughput
$ sudo vi /etc/tuned/myapp-throughput/tuned.conf
/etc/tuned/myapp-throughput/tuned.conf
[main]
summary=Custom throughput profile for myapp
include=throughput-performance

[sysctl]
net.core.somaxconn = 16384
net.ipv4.tcp_max_syn_backlog = 16384
vm.swappiness = 1

[vm]
transparent_hugepages=never
適用
$ sudo tuned-adm profile myapp-throughput
$ sudo tuned-adm active
Current active profile: myapp-throughput

/etc/tuned/ はユーザ定義領域、/usr/lib/tuned/ はパッケージが提供するデフォルト領域。同じ名前のユーザ定義があれば、ユーザ側が勝ちます。

tuned と sysctl.d の関係 #

tuned が適用した sysctl 値と /etc/sysctl.d/ に書いた値が衝突することがあります。優先順位はシンプル — 後に適用された値が勝つ です。ブート順では通常 tunedsysctl --system より先に動くので、/etc/sysctl.d/ が結局勝ちます。ただし tuned-adm profile X をランタイムに再実行すれば、その時点でプロファイル値が上書きします。

運用推奨:

  • システム全体ポリシー/etc/sysctl.d/
  • ワークロード束tuned プロファイル
  • 両者が同じキーを扱うなら 片側に統一。通常は tuned プロファイルにキーを移して sysctl.d から外すほうがすっきりします。

kdump — カーネルパニック時点のメモリダンプ #

カーネルがパニックで死んだとき、その時点のメモリ状態をダンプファイル (vmcore) として取っておくと、再起動後に crash のようなツールで事後解析できます。kdump がその仕事を担います。

どう動くか #

kdump の核心は カーネルを 2 つメモリに置いておく ことです。

  1. ブート時点で正常カーネルとは別に crash kernel が事前にメモリに展開されます (kexec 機構)
  2. 正常カーネルがパニックすると、ハードウェアリセットを経ずに、メモリ上に展開された crash kernel に即座にジャンプします
  3. crash kernel が正常カーネルのメモリ領域を vmcore ファイルとしてディスクに記録します
  4. その後、通常ブートに移行します

crash kernel 用メモリはブート時点であらかじめ確保されます。そのため RAM の一部 (通常 256MB ~ 数 GB) が普段は使えなくなります。軽いコストではありませんが、パニック解析が必要な運用マシンではほぼ必須です。

有効化 #

RHEL 9 は通常デフォルトで有効です。確認:

kdump 状態
$ sudo systemctl status kdump
$ sudo kdumpctl status

# メモリ展開状況
$ sudo cat /sys/kernel/kexec_crash_loaded
1     # 1 なら展開済み

無効なら:

有効化
$ sudo dnf install -y kexec-tools
$ sudo systemctl enable --now kdump

crashkernel パラメータ #

ブート時点で確保しておくメモリは GRUB のカーネル引数で指定します。RHEL 9 は通常 crashkernel=auto または明示値を自動で設定しますが、ワークロードによっては手を入れる場面があります。

現在の値を確認
$ cat /proc/cmdline
... crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M ...

# 特定値に変更
$ sudo grubby --update-kernel=ALL --args="crashkernel=512M"
$ sudo reboot

crashkernel=512M は無条件 512MB。crashkernel=1G-4G:192M,4G-64G:256M,... は RAM サイズに応じて違う値を適用する表記。RHEL 9 デフォルト表記をそのまま残すのが通常は安全です。

vmcore の保存先 #

/etc/kdump.conf で vmcore をどこに保存するか決めます。

/etc/kdump.conf 主要部
# デフォルト: ローカルディスク
path /var/crash
core_collector makedumpfile -l --message-level 7 -d 31

# NFS に送る
# nfs nfs.example.com:/srv/crash

# SSH で送る
# ssh user@dump-server.example.com
# sshkey /root/.ssh/kdump_id_rsa

# ディスクに落とせなければ reboot だけ
# default reboot
キー意味
pathvmcore 保存パス
core_collector makedumpfile -d 31ダンプから空ページ/ページキャッシュ等を除いて縮小 (-d 31 推奨)
nfs / sshリモート保存。ローカルディスクが壊れた場合の保険
defaultダンプ失敗時の動作 (reboot、halt、poweroff、shell、dump_to_rootfs)

設定変更後:

initramfs 再生成と再起動
$ sudo kdumpctl rebuild
$ sudo systemctl restart kdump

テスト — わざとパニックを起こす #

本番マシンでは絶対に試さず、隔離されたテストマシンでのみ実行します:

強制パニック (テスト環境専用)
$ sudo sysctl -w kernel.sysrq=1
$ echo c | sudo tee /proc/sysrq-trigger

マシンが即座にパニックし、vmcore が /var/crash/<日付>/vmcore に落ちます。再起動後に確認。

結果確認
$ ls /var/crash/
127.0.0.1-2026-04-27-10:30:00/

$ ls /var/crash/127.0.0.1-2026-04-27-10:30:00/
vmcore  vmcore-dmesg.txt

vmcore-dmesg.txt だけ見てもパニック直前の dmesg が入っており、一次診断にはそれで足りる場面が多いです。

crash で解析 #

crash ツール
$ sudo dnf install -y crash
$ sudo dnf install -y kernel-debuginfo-$(uname -r) --enablerepo=rhel-9-for-x86_64-baseos-debug-rpms

$ sudo crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux \
             /var/crash/127.0.0.1-2026-04-27-10:30:00/vmcore

crash> bt        # パニック時点のスタックトレース
crash> log       # カーネルログ
crash> ps        # プロセス一覧
crash> mod       # ロード済みモジュール
crash> sys       # システム情報

bt (backtrace) 1 つ見るだけで、どの関数でパニックが起きたかが見えます。深い解析は別の話題ですが、vmcore が手元にあること自体が運用のセーフティネットです。

よくある落とし穴 #

  • sysctl -w だけ使ってファイルに書かない — 再起動で消えます。永続適用は必ず /etc/sysctl.d/ で。
  • /etc/sysctl.conf 単一ファイルにすべて書く — 変更出所の追跡ができません。モジュール別に 99-app.conf99-network.conf の形で分割推奨。
  • tunedsysctl.d が同じキーで衝突 — 最後に適用された値が勝ちます。片側に統一。
  • kdump ディスク容量不足 — vmcore は数 GB になり得ます。/var/crash のあるファイルシステムに余裕を確保。
  • kdump.conf 変更後に kdumpctl rebuild 漏れ — 変更が反映されません。常に rebuild → restart。
  • crashkernel= 引数の削除 — 誰かが GRUB 引数を整理して落とすと、次のブートから kdump が動きません。cat /proc/cmdline で定期確認。
  • コンテナホストで vm.overcommit_memory=1 を不用意に — 一部ワークロードでは OOM パターンが変わります。ワークロード別に検証。

覚えておくコマンド #

作業コマンド
sysctl 値の参照/一時変更sysctl <key> / sysctl -w <key>=<v>
sysctl.d 適用sudo sysctl --system
1 ファイルだけ適用sudo sysctl -p /etc/sysctl.d/99-tune.conf
tuned アクティブプロファイルsudo tuned-adm active
tuned プロファイル切替sudo tuned-adm profile <name>
tuned 推薦sudo tuned-adm recommend
kdump 状態sudo kdumpctl status
crash kernel 展開確認cat /sys/kernel/kexec_crash_loaded
kdump 再構成sudo kdumpctl rebuild && sudo systemctl restart kdump
vmcore 解析sudo crash <vmlinux> <vmcore>

まとめ #

  • sysctl — ランタイムカーネルパラメータ調整 + /etc/sysctl.d/*.conf で永続分離。99- 接頭辞で最後の適用を保証。
  • tuned — ワークロードプロファイルの束。throughput-performance (サーバデフォルト)、virtual-guest (クラウドゲスト)、カスタムは /etc/tuned/ に継承して一部だけ上書き。
  • kdump — カーネルパニック時点のメモリダンプキャプチャ。crash kernel 用メモリを crashkernel= で予約し、vmcore は /var/crash か NFS/SSH へ。crash で事後解析。
  • 3 つの位置 — sysctl は 1 行単位、tuned はワークロード束、kdump はパニックセーフティネット。同一キーが衝突したら片側に統一。

次回はカーネルが順調に動いているマシンで 何が時間を食っているか を覗き込むパフォーマンス分析です。sartop/htopiostatvmstatperf をどんな場面でどんなシグナルを見て取り出すかを整理します。

X