Kdump
関連記事
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 はすぐにカーネルを起動しますが、フラグが指定されている場合、カーネルのロードだけを行なって起動自体はクラッシュするまで延期されます。
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
もしくは、任意で他のマシンにクラッシュダンプをコピーすることもできます。ダンプを保存したらマシンを再起動して通常のシステムカーネルを起動してください。
コアダンプの解析
gdb ツールを使ったり crash という名前の特殊な gdb 拡張を使うことができます。crash は以下のように実行します:
$ crash vmlinux path/crash.dump
vmlinux には先に保存したデバッグシンボルが含まれているカーネルバイナリを指定してください。
デバッグについては man crash や https://people.redhat.com/~anderson/crash_whitepaper/ を参照。
参考情報
- https://www.kernel.org/doc/Documentation/kdump/kdump.txt - kdump の公式ドキュメント
- http://www.dedoimedo.com/computers/www.dedoimedo.com-crash-book.pdf - The crash book