重大なカーネルCVEのために深夜2時に本番サーバーを再起動するのは、決して楽しい作業ではありません。複数のデータセンターに散らばる10台以上のVPSを管理している身としては、なおさらです。その繰り返しに嫌気が差した私は、kernel live patchingをきちんとセットアップすることに時間を投資しました。それ以来、セキュリティアップデートへの対処が大きく変わりました。
Kernel live patchingを使えば、稼働中のカーネルに直接セキュリティ修正を適用できます。ダウンタイムなし、メンテナンス窓なし、慌ててSlackにメッセージを送る必要もありません。実際に本番環境で運用して得た知見をお伝えします。
クイックスタート:5分でKernel Live Patchingを起動する
最速の方法はディストリビューションによって異なります。Canonical Livepatchに登録済みのUbuntuシステムであれば、ほぼ即座に動作させることができます。
Ubuntu — Canonical Livepatch
UbuntuはLivepatchをUbuntu Proの一部として提供しています(個人アカウントで最大5台まで無料)。
# ubuntu.com/security/livepatch で無料トークンを取得
pro attach YOUR_TOKEN_HERE
# livepatchを有効化
pro enable livepatch
# ステータスを確認
canonical-livepatch status --verbose
Ubuntuの場合、設定はこれだけです。数分以内に、マシンはライブカーネルパッチを自動的に受け取り始めます。
RHEL / CentOS / AlmaLinux — kpatch
Red Hatのkpatchはより細かな手動制御を提供しており、クリティカルなサーバーでは私もこちらを好んで使っています。
# kpatchをインストール
dnf install kpatch kpatch-dnf
# kpatchサービスを有効化
systemctl enable --now kpatch
# カーネルがライブパッチングをサポートしているか確認
grep CONFIG_LIVEPATCH /boot/config-$(uname -r)
出力にCONFIG_LIVEPATCH=yが表示されるはずです。表示されない場合、そのカーネルはライブパッチングサポート付きでコンパイルされていません。別のカーネルパッケージを探す必要があります。
カーネルがklpをサポートしているか確認する
# カーネルライブパッチサブシステムを確認
ls /sys/kernel/livepatch/
# ディレクトリが存在してアクセスできれば問題なし
# 空ディレクトリはパッチ未適用を意味する — 正常な状態
詳細解説:Kernel Live Patchingの実際の仕組み
深夜3時に何かが問題になったとき、仕組みを理解していることは重要です。カーネルライブパッチングフレームワーク(klp)は、脆弱な関数へのfunction callをパッチ済みバージョンにリダイレクトする新しいカーネルモジュールを挿入することで動作します。
プロセスの流れは次のとおりです:
- 脆弱な関数の修正バージョンを含むパッチモジュールがコンパイルされる
- モジュールが稼働中のカーネルにロードされる
klpサブシステムがカーネル関数トレース(ftrace)を使って元の関数への呼び出しをインターセプトする- 以降のすべての呼び出しがパッチ済みバージョンにリダイレクトされる
- 実行中のタスクは古い関数で完了し、新しい呼び出しはパッチ済みのものを使用する
移行状態が扱いにくい部分です。次のコマンドで監視できます:
# アクティブなライブパッチとその状態を一覧表示
cat /sys/kernel/livepatch/*/enabled
# 移行ステータスを確認(1 = 移行中、0 = 完了)
cat /sys/kernel/livepatch/*/transition
# 移行をブロックしているタスクを確認
cat /sys/kernel/livepatch/*/signal
transitionが長時間1のままの場合、一部のカーネルスレッドがまだセーフポイントに達していません。通常は問題ありません — 待つだけでOKです。長時間実行されるカーネルスレッド(kworkerやストレージI/Oスレッドなど)は、パッチが完全に有効化される前に現在の操作を完了する必要があります。
kpatchで手動でパッチを適用する
アクティブなサブスクリプションがないRHELベースのシステムでは、手動でパッチをビルドして適用できます。ただし、カーネル開発ヘッダーが必要です。
# ビルド依存パッケージをインストール
dnf install kernel-devel kernel-headers elfutils-libelf-devel
# 特定のkpatchモジュールを適用(ベンダー提供またはビルド済み)
kpatch load /path/to/kpatch-module.ko
# 現在ロード済みのパッチを一覧表示
kpatch list
# 特定のパッチを削除(必要な場合)
kpatch unload kpatch-module-name
応用編:自動化とフリート管理
10台以上のサーバーでこれを手動で実行するのは、すぐに別の問題になります。モニタリング面を自動化した方法を紹介します。
複数サーバーのパッチステータスを監視する
日次サマリーを取得するためにcronで実行しているシンプルなシェルスクリプトです:
#!/bin/bash
# livepatch-check.sh — 各サーバーで実行またはSSHループで実行
SERVERS=("server1.example.com" "server2.example.com" "server3.example.com")
for host in "${SERVERS[@]}"; do
echo "=== $host ==="
ssh -o ConnectTimeout=5 "$host" '
echo "Kernel: $(uname -r)"
if command -v canonical-livepatch &>/dev/null; then
canonical-livepatch status 2>/dev/null | grep -E "(running|last-check|fixed)"
elif command -v kpatch &>/dev/null; then
kpatch list 2>/dev/null || echo "パッチが読み込まれていません"
else
echo "ライブパッチングが設定されていません"
fi
echo "ライブパッチ移行状態: $(cat /sys/kernel/livepatch/*/transition 2>/dev/null || echo N/A)"
' 2>/dev/null || echo "SSH接続失敗"
echo
done
パッチ移行を強制する(慎重に使用すること)
スタックしたカーネルスレッドが原因でパッチが移行状態のままになることがあります。スレッドをセーフポイントに強制的に移動させるシグナルを送ることを試みることができます:
# スタックしているタスクに安全なパッチ適用ポイントへ進むよう通知
# 移行が何時間もスタックしている場合にのみ実行
echo 1 > /sys/kernel/livepatch/PATCH_NAME/signal
# 解決したか確認
cat /sys/kernel/livepatch/PATCH_NAME/transition
この方法は慎重に使っています。スレッドが重要な処理(データベースI/O、重い計算など)を実行中の場合、シグナルを強制すると中断される可能性があります。この方法を検討する前に、少なくとも30分待つことをお勧めします。
Ubuntuで自動パッチ適用を設定する
# livepatchデーモンが実行中かつ自動更新されているか確認
systemctl status snap.canonical-livepatch.canonical-livepatchd
# デーモンはデフォルトで60分ごとに新しいパッチを確認する
# タイマーを表示
systemctl list-timers | grep livepatch
SUSE Linux Enterprise — kGraft / klp
SUSEはklp(kernel live patching)をサポートツールに直接統合して使用しています:
# SCCサブスクリプションが有効なSLESの場合
zypper install kernel-livepatch-tools
# zypperで適用(通常のアップデートとして表示される)
zypper patch --category security --advisory SUSE-SU-XXXX:YYYY-1
# ステータスを確認
klp status
3年間の本番運用経験から得た実践的なヒント
3年間で10台以上のLinux VPSインスタンスを管理してきた経験から、本番環境への適用前に必ず十分なテストを行うことの重要性を学びました。ここでは本当に身になった教訓を紹介します。
Tip 1:ステージングを飛ばさない
ライブパッチングは、セキュリティ修正を本番環境に直接プッシュしたいという誘惑にかられます。モジュールをロードするだけだし、大丈夫じゃないか、と。しかしそれは間違った考え方です。以前、ネットワークドライバー用に使っていたカスタムカーネルモジュールとパッチが競合したことがあります。その症状は負荷がかかったときにしか現れませんでした。
現在のワークフロー:ステージングサーバーにパッチを適用し、通常の負荷モニタリング下で48時間動作させ、その後に本番環境へ適用します。ライブパッチングは時間を稼いでくれますが、テストを省略していい権利を与えてくれるわけではありません。
Tip 2:カバーされているCVEを把握する
ライブパッチはすべてのカーネルCVEをカバーするわけではありません。ベンダーが優先度の高いものだけを対象にしています。常にクロスリファレンスを確認しましょう:
# Ubuntu — 現在のlivepatchでカバーされているCVEを確認
canonical-livepatch status --verbose | grep -i cve
# 特定のCVEが対応済みか確認
canonical-livepatch status --verbose | grep CVE-2024-XXXXX
ライブパッチングでカバーされていないCVEに対しては、やはり再起動が必要です。ライブパッチングは再起動の頻度を減らしてくれますが、ゼロにはなりません。
Tip 3:最終的な再起動を計画する
ライブパッチはメモリに積み重なっていきます。ある時点で — 通常は別の理由でメンテナンス窓が設けられるとき — すべてのパッチが組み込まれたクリーンなカーネルで起動するために再起動すべきです。私は何も問題がなくても四半期ごとにこれをスケジュールしています。
# 最後の再起動からの経過時間を確認
uptime -s
# 現在アクティブなライブパッチの数を確認
ls /sys/kernel/livepatch/ | wc -l
Tip 4:カーネルバージョンのドリフトを監視する
フリート全体で異なるカーネルバージョンを実行している場合、バージョンによってライブパッチの利用可能性が異なります。週次チェックに追加しているモニタリングスニペットです:
#!/bin/bash
# フリート全体のカーネルバージョンを確認
for host in "${SERVERS[@]}"; do
echo -n "$host: "
ssh "$host" 'uname -r' 2>/dev/null
done | sort -t: -k2 | uniq -f1 -c
4台のサーバーがあるカーネルバージョンで、1台が古いバージョンで動いているのを見た場合、その古いサーバーはライブパッチを受け取れない可能性があります。さらに悪い場合、ベンダーがそのバージョンをもうサポートしていないため、パッチが全くあたらないこともあります。
Tip 5:制限を理解する
Kernel live patchingは既存のカーネル関数のセキュリティ脆弱性を処理します。できないことは次のとおりです:
- 新しいシステムコールやカーネルインターフェースの追加
- コアカーネルに含まれないドライバーへのパッチ適用
- カーネルデータ構造の変更が必要な問題の修正
- すでにライブパッチが当たっているパッチの置き換え(リセットには再起動が必要)
CVEがカーネルデータ型の構造的な変更を必要とする場合、ライブパッチングは単純に不可能です。ベンダーが再起動を要求するのは正しい判断です。
Tip 6:アラートを設定する
監視スタック(Prometheus、Nagios、その他何でも使っているもの)に以下の場合のアラートチェックを追加してください:
- ライブパッチが2時間以上
transition状態になっている - livepatchデーモンが24時間以上更新チェックを行っていない
- 新しいパッチが利用可能なのに適用されていない
サイレントな障害が最も厄介です。以前、livepatchデーモンがひっそりとクラッシュし、2週間もの間、保護されていると思い込んでいたことがありました。実際にはそうでなかったのに。
環境に合ったツールを選ぶ
アプローチ選択のクイックリファレンスです:
- Ubuntu(個人/小規模ビジネス):Ubuntu ProのCanonical Livepatch — 5台以下無料、設定不要
- Ubuntu(エンタープライズ):有料のUbuntu Pro — 無制限の台数をカバー
- アクティブサブスクリプション付きRHEL:Red HatのkpatchサービスがすべてΑを自動的に処理
- サブスクリプションなしのCentOS/AlmaLinux:コミュニティパッチモジュールによる手動kpatch — 手間はかかるが実行可能
- SUSE Enterprise:SCCサブスクリプション経由のklp
- 混在フリートまたは商用オプション:TuxCare KernelCare — ベンダーニュートラル、ほぼすべてに対応
Kernel live patchingは万能薬ではありませんが、私のワークフローに追加した中で最もROIの高いセキュリティツールのひとつです。ほとんどの構成でセットアップ時間は1時間以内、そして見返り — 重大なCVEに対する緊急再起動をスキップできること — はすぐに得られます。まず重要度の低いサーバーで始め、パッチステータスのツールが正しく機能することを確認してから、順次展開していきましょう。

