Kdump

提供: ArchWiki
2018年3月6日 (火) 21:00時点におけるKusakata (トーク | 投稿記録)による版 (→‎クラッシュしたカーネルをダンプ: 同期)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

関連記事

Kdump はカーネルがクラッシュしたときにマシンのメモリの中身を保存する Linux の標準的な仕組みです。Kdump は Kexec がベースになっています。Kdump は2つのカーネルを利用します: システムカーネルとダンプキャプチャカーネルです。システムカーネルは通常のカーネルで、特殊な kdump のフラグを有効にして起動します。システムカーネルにはダンプキャプチャカーネルをロードするための領域を物理メモリ上に予約させなければなりません。クラッシュが発生したときはカーネルが壊れているためディスクからデータを読み込む方法がありません。そのため、あらかじめダンプキャプチャカーネルをロードしておく必要があるのです。

カーネルがクラッシュしたら、カーネルのクラッシュハンドラが Kexec を利用してダンプキャプチャカーネルを起動します。システムカーネルのメモリには手を加えず、クラッシュしたときのままの状態でダンプキャプチャカーネルから読み込むことができるようにします。ダンプキャプチャカーネルが起動したら、ユーザーは /proc/vmcore ファイルを使ってクラッシュしたシステムカーネルのメモリにアクセスすることができます。ダンプはディスクに保存したり、あるいはネットワークを介して他のマシンにコピーして調査することができます。

本番環境とダンプキャプチャカーネルは異なっています。システムカーネルは様々な機能を必要とするため、多数のカーネルフラグやドライバーを有効にしてコンパイルされます。一方、ダンプキャプチャカーネルの目的はハッキリしているので必要なメモリの量は少なくすることができます。例えば、メモリダンプをディスクにしか保存しない場合、ダンプキャプチャカーネルをコンパイルするときにネットワークのサポートを省いてしまっても問題ありません。しかしながら、この記事では物事を簡単にするためにシステムカーネルとダンプキャプチャカーネルは全く同じカーネルを使うことにします。つまり同じカーネルのコードを2回ロードすることになります。片方は通常のシステムカーネルであり、もう片方は予約済みのメモリ領域にロードされるカーネルです。

カーネルのコンパイル

システムカーネルとダンプキャプチャカーネルには、通常では設定されない設定フラグが必要になります。Arch におけるカスタムカーネルのコンパイルについてはカーネルコンパイルの記事を参照してください。ここでは Kdump の設定に絞って説明します。

カーネルを作成するときは、カーネルコンフィグ (あるいは config.x86_64) ファイルを編集して以下の設定オプションを有効にする必要があります:

config{.x86_64} file
CONFIG_DEBUG_INFO=y
CONFIG_CRASH_DUMP=y
CONFIG_PROC_VMCORE=y

デフォルトの Arch カーネルと区別が付くようにパッケージベースの名前を linux-kdump などと変更してください。カーネルパッケージをコンパイルしてインストールします。未圧縮のシステムカーネルバイナリである ./src/linux-X.Y/vmlinux を保存してください。デバッグシンボルが含まれているので後でクラッシュを解析するときに必要になります。

別々のシステムカーネルとダンプキャプチャカーネルを使用する場合、Kdump のドキュメントを読むことを推奨します。ダンプキャプチャカーネルを小さく作成する方法が複数書かれています。

kdump カーネルの設定

まずダンプキャプチャカーネルのメモリを予約する必要があります。ブートローダーの設定を編集してインストールしたシステムカーネルのブートオプションに crashkernel=64M を追加してください。例えば Syslinux ならブートエントリは以下のようになります:

/boot/syslinux/syslinux.cfg
LABEL arch-kdump
        MENU LABEL Arch Linux Kdump
        LINUX ../vmlinuz-linux-kdump
        APPEND root=/dev/sda1 crashkernel=64M
        INITRD ../initramfs-linux-kdump.img

64M のメモリで RAM が 12G まで搭載されているマシンのクラッシュダンプを処理することができます。環境によってはさらに多くのメモリを予約する必要があります。ダンプキャプチャカーネルがロードできない場合、メモリの値を 256M あるいは 512M まで増やしてください。ただし、設定したメモリ領域はシステムカーネルから使うことができなくなります。

システムカーネルを再起動してください。カーネルが正しいオプションで起動していることを確認するために /proc/cmdline ファイルをチェックしてください。

次に Kexec でダンプキャプチャカーネルを使用するように設定します。カーネル、initramfs ファイル、ルートデバイスの他に必要ならパラメータも指定してください:

# kexec -p [/boot/vmlinuz-linux-kdump] --initrd=[/boot/initramfs-linux-kdump.img] --append="root=[root-device] single irqpoll maxcpus=1 reset_devices"

上記のコマンドでカーネルが予約済みの領域にロードされます。-p フラグを指定しなかった場合、kexec はすぐにカーネルを起動しますが、フラグが指定されている場合、カーネルのロードだけを行なって起動自体はクラッシュするまで延期されます。

ノート: ロードされたカーネルについて cat /sys/devices/system/cpu/online はアクティブな CPU コアを表示します。maxcpus=1 カーネルパラメータはコア数を1まで 制限 します。設定が反映されなかったり SMP を有効にしたカーネルが 起動しない 場合、代わりに nr_cpus=1 を使ってみてください。

kexec を手動で実行するかわりに、Systemd サービスを使って起動時に kexec を実行することもできます:

/etc/systemd/system/kdump.service
[Unit]
Description=Load dump capture kernel
After=local-fs.target

[Service]
ExecStart=/usr/bin/kexec -p [/boot/vmlinuz-linux-kdump] --initrd=[/boot/initramfs-linux-kdump.img] --append="root=[root-device] single irqpoll maxcpus=1 reset_devices"
Type=oneshot

[Install]
WantedBy=multi-user.target

サービスを作成したら有効化してください:

# systemctl enable kdump

クラッシュカーネルがロードされていることを確認するには次のコマンドを実行:

$ cat /sys/kernel/kexec_crash_loaded

クラッシュのテスト

クラッシュをテストしたい場合、sysrq を使ってクラッシュさせることができます。

警告: カーネルのクラッシュでディスク上のデータが飛んでしまう可能性があります。自己責任で行なってください。
# echo c > /proc/sysrq-trigger

クラッシュが発生すると kexec はダンプキャプチャカーネルをロードします。

クラッシュしたカーネルをダンプ

ダンプキャプチャカーネルが起動したら、/proc/vmcore ファイルを読むことができます。ダンプはファイルに保存して後で解析することが推奨されています:

# cp /proc/vmcore /root/crash.dump

もしくは、任意で他のマシンにクラッシュダンプをコピーすることもできます。ダンプを保存したらマシンを再起動して通常のシステムカーネルを起動してください。

クラッシュダンプは非常に大きなものになることもあります。makedumpfileAUR を使って一部のメモリ領域を無視して圧縮を使うことでダンプの容量を小さくすることができます:

# makedumpfile -c -d 31 /proc/vmcore /root/crash.dump

以下の systemd サービスは自動的にクラッシュダンプを保存してメインカーネルで再起動します:

/etc/systemd/system/kdump-save.service
[Unit]
Description=Create dump after kernel crash
DefaultDependencies=no
Wants=local-fs.target
After=local-fs.target

[Service]
Type=idle
ExecStart=/bin/sh -c 'mkdir -p /var/crash/ && /usr/bin/makedumpfile -c -d 31 /proc/vmcore "/var/crash/crashdump-$$(date +%F-%T)"'
ExecStopPost=/usr/bin/systemctl reboot
UMask=0077
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit

ダンプキャプチャカーネルのコマンドラインから呼び出すことができます:

/etc/systemd/system/kdump.service
[Unit]
Description=Load dump capture kernel
After=local-fs.target

[Service]
ExecStart=/usr/bin/kexec -p [/boot/vmlinuz-linux-kdump] --initrd=[/boot/initramfs-linux-kdump.img] --append="root=[root-device] systemd.unit=kdump-save.service irqpoll maxcpus=1 reset_devices"
Type=oneshot

[Install]
WantedBy=multi-user.target

コアダンプの解析

gdb ツールを使ったり crash という名前の特殊な gdb 拡張を使うことができます。crash は以下のように実行します:

$ crash vmlinux path/crash.dump

vmlinux には先に保存したデバッグシンボルが含まれているカーネルバイナリを指定してください。

デバッグについては man crashhttps://people.redhat.com/~anderson/crash_whitepaper/ を参照。

参考情報