Linuxを数秒で再起動する:kexecを使ってBIOSとPOSTをスキップする方法

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

9分間のメンテナンス・ウィンドウ

かつて、トラフィックの多いデータベースサーバーで、カーネルの重大な脆弱性にパッチを適用しなければならないことがありました。私は reboot コマンドを実行して待ちました。そして、さらに待ちました。サーバーが内部メモリチェックを実行している間に7分が経過しました。RAIDコントローラーの初期化でさらに2分が消えました。OSが実際にロードを開始したときには、監視システムはすでにP1(優先度1)のインシデントを発生させていました。本番環境において、この9分間の空白は単なる不便ではなく、SLAに対する脅威です。

数十台のエンタープライズ規模のサーバーを管理してきた結果、ハードウェアの初期化こそがアップタイム(稼働時間)の敵であることに気づきました。これがきっかけで、私のメンテナンスワークフローを根本から変えたツールに出会いました。それが kexec です。

ボトルネック:なぜハードウェアのリセットは時間を浪費するのか

通常の reboot は「コールドブート」をトリガーします。CPUがリセットされ、BIOS/UEFIが電源投入時自己診断(POST)を実行し、10GbE NICからNVMeコントローラーに至るまで、すべての周辺機器が再初期化される必要があります。512GBのRAMを搭載したDell PowerEdgeやHP ProLiantでは、ハードウェアフェーズだけで5〜8分かかることもあります。

Linuxには近道があります。制御をハードウェアに戻す代わりに、実行中のカーネルに対して、新しいカーネルをメモリに直接ロードするように指示できるのです。これにより、マザーボードのファームウェアを完全にバイパスできます。このプロセスは kexec システムコールによって処理されます。

クイックスタート:初めての kexec 再起動

これを利用するには、 kexec-tools パッケージが必要です。このユーティリティは、シェルとカーネル内部のkexec機能の橋渡しをします。

1. ツールのインストール

UbuntuまたはDebianベースのシステムの場合:

sudo apt update && sudo apt install kexec-tools

RHEL、AlmaLinux、またはRocky Linuxの場合:

sudo dnf install kexec-tools

2. ターゲットカーネルの特定

kexecに対して、起動したい特定のカーネルとinitrd(初期RAMディスク)を指定する必要があります。これらのファイルは /boot ディレクトリにあります。通常は、利用可能な最も高いバージョン番号のものを選びます。

ls /boot/vmlinuz* /boot/initrd.img*

3. 新しいカーネルのステージング

このステップでは、カーネルをまだ実行せずに、メモリの予約領域にロードします。プレースホルダーを実際のファイルパスに置き換えてください:

sudo kexec -l /boot/vmlinuz-$(uname -r) \
--initrd=/boot/initrd.img-$(uname -r) \
--reuse-cmdline
  • -l: カーネルをメモリにロードします。
  • --initrd: RAMディスクイメージを指定します。
  • --reuse-cmdline: 現在の起動パラメータ(rootのUUIDやコンソール設定など)を新しいカーネルにコピーします。

4. ジャンプの実行

切り替える準備ができたら、以下を実行します:

sudo kexec -e

SSHセッションは即座にハングアップします。20〜30秒以内に、BIOSシーケンスをすべてスキップしてサーバーがオンラインに戻ります。

kexec の仕組み:内部動作

ここでのエンジンは kexec_load システムコールです。カーネルをステージングすると、OSは新しいイメージを保存するために不連続なメモリページを割り当てます。現在アクティブなカーネルが使用しているメモリを上書きしないように、kexecはアーキテクチャ固有のマシンコードを含む「コントロールページ」を使用します。

ジャンプ(-e)を実行すると、システムは厳密な手順に従います:

  1. 現在のカーネルが、ネットワークやストレージなどのサブシステムを可能な限りクリーンにシャットダウンします。
  2. CPUがすべての割り込みを無効にします。
  3. コントロールコードが、新しいカーネルイメージを最終的な連続したメモリの目的地に移動させます。
  4. CPUが新しいカーネルのエントリポイントに直接ジャンプします。

ハードウェアの電源が切れることはないため、CPUがリセットベクタに戻ることはありません。実質的に、サーバーの「体」は起きたまま、「脳」だけを入れ替えることになります。

高度な使い方:systemd との統合

手動でのカーネルロードは単発のテストには適していますが、本番環境では自動化が必要です。最近のほとんどのディストリビューションでは、 systemd を使用してこのプロセスを安全に管理します。

ロード状況の確認

sysfsファイルシステムの仮想ファイルをチェックすることで、カーネルがステージングされ準備ができているかを確認できます:

cat /sys/kernel/kexec_loaded

1 はジャンプの準備ができていることを意味し、 0 はカーネルがステージングされていないことを意味します。

より安全な systemd によるアプローチ

kexec -e を直接使うのは少々強引です。サービスが停止するための十分な時間が常に与えられるとは限りません。代わりに、systemdのラッパーを使用することをお勧めします。これにより、カーネルの入れ替え前にデータベースがバッファをフラッシュし、ファイルシステムが適切にアンマウントされることが保証されます:

sudo systemctl kexec

これをデータベースノードに推奨します。kexecのスピードと、標準的なシャットダウンのデータ整合性を両立させることができます。

実環境での注意点と安全性

kexecは強力ですが、あらゆる再起動の代わりになるわけではありません。現場で導入して学んだことを共有します。

「汚れた」ハードウェアの処理

マザーボードがリセットされないため、一部のハードウェアデバイスがアクティブな状態のままになることがあります。新しいカーネルのドライバが特定のNICやファイバーチャネルカードを適切に再初期化しない場合、そのデバイスがハングする可能性があります。必ず、本番環境のハードウェアをミラーリングしたステージングサーバーでkexecをテストしてください。デバイスの起動に失敗した場合は、従来のコールドブートを行う必要があるかもしれません。

セキュアブートの制限

UEFIセキュアブートが有効な場合、標準の kexec -l コマンドは「Permission Denied」エラーで失敗することがよくあります。これは、署名されていないカーネルがサイドロードされるのを防ぐためのセキュリティ機能です。これを回避するには、 -s フラグを使用します(kexec -s -l ...)。これにより、ユーザースペースのユーティリティではなく、カーネル自身の署名検証メカニズムを使用するように強制されます。

コールドブートが必要な場合

kexecが更新するのはソフトウェアレイヤーのみです。BIOS/UEFIファームウェアを更新する場合、RAIDレベルを変更する場合、または物理RAMを交換する場合は、標準の reboot を実行する必要があります。kexecはハードウェアレベルの設定変更を適用することはできません。

最後に

パッチ適用スクリプトに systemctl kexec を組み込むことで、10分かかっていたダウンタイムを60秒未満に短縮できます。ストレスの多いメンテナンス作業が、わずかな瞬きのような時間に変わります。定期的なカーネルアップデートに活用し、サービスの応答性を維持してユーザーを満足させましょう。

Share: