Proxmox クラスタを自動更新する — ただし本番VMが載っているノードは再起動しない

ホームラボ 2026年8月5日

自宅サーバーの更新は、必ず放置される

自宅で動かしているサーバーの apt upgrade を、あなたは最後にいつ実行したでしょうか。

1台なら気が向いたときにやれます。 4台になると、やらなくなります。 1台ずつ SSH して、更新して、再起動の要否を判断して、という作業を月に何度もやる人はいません。

そして更新されないまま放置されたサーバーは、セキュリティ的にただの負債になります。

筆者の環境は Proxmox VE の4ノードクラスタで、 そのうち3ノードに本番として動かしている VM が載っています。 止められないものが載っている以上、「全部自動で更新して再起動」も選べません

そこで、こういう方針にしました。

この記事が向いていない人

なぜ unattended-upgrades では足りないか

Debian 系には unattended-upgrades があり、Proxmox でも使えます。 セキュリティ更新を自動で当てる、という点では十分に機能します。

足りないのは再起動の判断です。

カーネルが更新されても、再起動するまで動いているのは古いカーネルのままです。 更新した気になっているだけ、という状態になります。

かといって無条件に再起動させると、本番VMが載っているノードが勝手に落ちます。 Proxmox の場合、ノードの再起動はその上の全 VM の停止を意味します。

つまり必要なのは「更新するかどうか」ではなく、 「このノードは今、再起動してよいか」を判定するロジックでした。

構成

systemd のタイマーとシェルスクリプト1本です。

# /etc/systemd/system/pve-auto-update.timer
[Unit]
Description=Weekly Proxmox automatic package update

[Timer]
OnCalendar=Sat *-*-* 03:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target

毎週土曜の午前3時に走らせています。ポイントが3つあります。

サービス側では優先度を落としています。

# /etc/systemd/system/pve-auto-update.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/pve-auto-update.sh
Nice=10
IOSchedulingClass=idle

Nice=10IOSchedulingClass=idle で、更新処理が VM の動作を邪魔しないようにしています。 深夜とはいえ、本番VMが動いている上での作業なので、ここは効きます。

更新の実行

export DEBIAN_FRONTEND=noninteractive

apt-get update
apt-get -y \
  -o Dpkg::Options::="--force-confdef" \
  -o Dpkg::Options::="--force-confold" \
  dist-upgrade
apt-get -y autoremove --purge
apt-get clean

DEBIAN_FRONTEND=noninteractive--force-confdef / --force-confold の組み合わせが要点です。

これが無いと、設定ファイルに変更がある場合にプロンプトで止まります。 誰も見ていない深夜3時に「設定ファイルをどうしますか?」と聞かれても、答える人がいません。 --force-confold は「変更済みの設定ファイルはそのまま残す」という指定で、 自分でいじった設定が勝手に上書きされるのを防ぎます。

再起動が必要かの判定

ここが本題です。

NEWEST_KERNEL=$(ls /lib/modules | sort -V | tail -1)
RUNNING_KERNEL=$(uname -r)

if [ -f /var/run/reboot-required ] || [ "$NEWEST_KERNEL" != "$RUNNING_KERNEL" ]; then
  ...
fi

/var/run/reboot-required だけを見ていては不十分です。 このファイルは update-notifier-common などが作るもので、環境によっては存在しません。

より確実なのは、インストール済みの最新カーネルと、現在動いているカーネルを比較することです。 /lib/modules のディレクトリ名がインストール済みカーネルの一覧なので、 sort -V(バージョン順ソート)の最後と uname -r を比べれば判定できます。

sort -V は重要です。単純な文字列ソートだと 6.8.10 より 6.8.9 が後ろに来ます。

自動再起動してよい条件

再起動が必要と分かったうえで、実際に再起動するかどうかを2つの条件で判定します。

条件1: このノードに本番VMが載っていないこと

PROD_VM_REGEX='akashi-web-server|astrokit-web-server|nextcloud'
if qm list | awk '$3=="running" {print $2}' | grep -Eq "$PROD_VM_REGEX"; then
  # 手動再起動に回す
fi

VMID ではなく VM 名で判定しているのが要点です。

Proxmox はクラスタなので、VM はノード間を移動します。 「VMID 102 が載っているノードは再起動しない」という書き方をすると、 マイグレーションした瞬間に判定が壊れます。移動先のノードは 102 を知らないからです。

VM 名で見ていれば、qm list はそのノードで動いているものだけを返すので、 どのノードに移動していても正しく判定されます

$3=="running" で状態も見ています。停止中の VM が載っているだけなら、再起動して構いません。

条件2: クラスタが quorate であること

elif ! pvecm status | grep -q 'Quorate:.*Yes'; then
  # quorum 異常 -> 再起動しない
fi

すでにクラスタが不安定なときに、さらに1ノード落としてはいけません。

Proxmox のクラスタは過半数のノードが生きていることを前提に動きます。 何らかの理由で既に quorum を失っている状態で再起動をかけると、 復旧がさらに難しくなります

「更新のための再起動」は急ぐ作業ではないので、異常時は何もしないのが正解です。

どちらかを満たさない場合

wall "pve-auto-update: $(hostname) は再起動が必要です (新カーネル $NEWEST_KERNEL / 本番VM稼働中のため手動で)"
touch /var/run/pve-auto-update-reboot-required

wall で全ログインセッションに通知し、フラグファイルを置きます。 次に SSH したときに気づけるようにしておく、という程度ですが、 「再起動が必要なノードがある」という事実が残るのが大事です。

自動化で一番まずいのは、判断を保留したことを誰も知らない状態になることです。

条件を満たした場合

shutdown -r +1 "pve-auto-update kernel reboot"

1分の猶予を置いてから再起動します。即時ではなく1分にしているのは、 その瞬間に誰かが作業していた場合に気づけるようにするためです。

運用してみて

良かった点

注意している点

自動化の目的は「全部を無人で回すこと」ではなく、 **「人がやるべき判断だけを人に残すこと」**だと考えています。 再起動してよいかどうかは機械が判定でき、 「本番を止めるタイミングをいつにするか」は人が決めるべきことでした。

まとめ


関連: 自宅に19インチラックを入れた / サイドフローとトップフロー、両方使った