kanade-agent 自身のアップデート

agent の self-update は唯一 OBJECT_APP_PACKAGES + script_object ジョブを 使わない コンポーネントです。agent は ssh なしで現在実行中の自分自身のバイナリを差し替える必要があり、汎用 install ジョブよりタイトなループのため専用の仕組みを持っています。

仕組み

バケット / キー用途
OBJECT_AGENT_RELEASESagent バイナリ。キーは <version>。rollout watcher が agent アップデートだけに反応するように、OBJECT_APP_PACKAGES とは別バケット。
agent_config.<scope>.target_version各スコープ (global / グループ / pc) があるべきバージョン。agent の self_update ループがこれを watch しています。

フロー:

1. agent.self_update watches agent_config for target_version
2. If target_version != my agent_version:
   a. Pull `OBJECT_AGENT_RELEASES/<target_version>` to <exe>.new
   b. Sha-verify against the bucket's recorded digest
   c. Atomic swap: <exe> ← <exe>.new (via SCM stop/start)
   d. New binary boots, watcher arms again, loop closes

rollout watcher は cold broker (ホスト再起動後に agent と broker が同時に立ち上がる、など) に耐えなければなりません。#226 以前は最初の get_object_store 呼び出しで Err(_) => return; してしまうと watcher が恒久的に死んでいて、その起動セッション中は agent が二度と self-update しませんでした。#226 以降は watcher が backoff で再試行し、broker に到達できるまであきらめません。

ステップごとの手順

1. agent をビルド

cargo build --release -p kanade-agent

出力: target/release/kanade-agent.exe

2. publish

kanade agent publish target/release/kanade-agent.exe

CLI は PE VERSIONINFO リソースからバージョンを自動抽出します — --version フラグ不要、ラベルとバイナリの不一致もあり得ません。

3. roll out

スコープを選びます。canary 1 台から:

kanade agent rollout 0.42.2 --pcs canary-01

ping で確認:

kanade ping canary-01     # agent_version should flip to 0.42.2
                          # within a few seconds

問題なければ範囲を広げる:

kanade agent rollout 0.42.2 --groups office --jitter 5m
# or fleet-wide
kanade agent rollout 0.42.2 --global --jitter 30m

--jitter は実際の swap タイミングをある幅で分散させ、大きな fan-out 時に全ホストの OS サービスマネージャを同時に叩かないようにします。100 台以上の fleet では推奨。

4. 確認

kanade agent current
# → target_version = 0.42.2 (global)

あとは SPA の Agents ページ (もしくは /api/agents) で fleet 全体をスポットチェック: agent_version 列は jitter + 約 30 秒の heartbeat 間隔以内に新バージョンに収束するはず。

ありがちなトラブル

症状原因対処
kanade agent rollout が "version not in OBJECT_AGENT_RELEASES" と言うtypo もしくはスコープ違いkanade agent currentkanade jetstream object list agent_releases で再確認。
数分経っても kanade ping <host> が古いバージョンを返すagent が self-update しなかった — watcher が死んでいる (#226 以前の agent) か、ホストが broker に到達できない対象ホストの %ProgramData%\Kanade\log\agent.*.log をチェック。self_update が無言なら (「checking target_version」ログがない)、agent が古すぎる; deploy-agent.ps1 で手動ブートストラップ。
agent が flap する: 起動するも exit_code: 1 ですぐ落ちるこのホストでは新バイナリが起動できない (config の不整合、依存欠落など)。SCM の failure-actions により再起動が試みられるが再びクラッシュする — Event Viewer に Service Control Manager のエラーが連続して記録されるロールバック: kanade agent rollout <prev-version> --pcs <host>。次の watcher tick でホストは元のバージョンに戻ります。

なぜ別のバケット / スコープか?

OBJECT_APP_PACKAGES<name>/<version> をキーにした汎用 blob ストアです。agent rollout パターンに必要なのは:

  • agent の変更だけに反応する watcher (たくさんの名前が入ったバケットを poll するのではなく、特定の 1 つの KV キーを安価に watch)。
  • 「既知の全バージョン」ではなくスコープごとの「現在の target」セマンティクス — agent_config.<scope>.target_version こそが「自分は何を動かすべきか」の答えで、agent 側で列挙する必要がない。
  • operator 向け UX (kanade agent publish / rollout) が kanade app publish とは別サブコマンドツリーに分けるに足るくらい違う。

というわけで agent は OBJECT_AGENT_RELEASES + レイヤード config KV を、他のコンポーネントは OBJECT_APP_PACKAGES + アプリ別ジョブを共有します。