夜中に「見えているのに戻せない」

分散エージェントを運用しているチームが、ある夜に直面した状況がある。エージェントの一台が完全に落ちた。プロセスごと消える、いわゆる process death だ。監視は動いていた。アラートも上がった。「落ちているのは見えている」。しかし「こちらからは一切戻せない」という状態に陥った。

自動復旧の仕組みはあった。にもかかわらず、効かなかった。

この話を読んで「うちは大丈夫」と即座に思えるチームは、正直そう多くないと思う。監視ツールを入れて、watchdogを走らせて、「復旧の仕組みは整っている」という感覚を持っている現場は多い。だが今回の話は、その感覚に潜む構造的な穴を、実体験から丁寧に解剖したものだ。


落ち方は3種類あり、混同が設計を壊す

元記事では、分散ワーカーの障害を3クラスに分けている。

  • alive-but-stuck:プロセスは存在するが、ループが論理的に止まっている。外から「nudge(小突き)」すれば復帰する。
  • dead:プロセスが消えている。OSのプロセステーブルに存在しない。起こす相手がもういない。
  • delivery-gap:本体は生きているが、受信や通知のパイプだけが詰まっていて、外からは死んで見える。

この3つを「なんとなく落ちている」として一括りにすると、復旧設計が根本からズレる。

実際、このチームの自動復旧は nudge 型だった。「対象に起床シグナルを送って、止まっているループを再駆動させる」方式だ。これは alive-but-stuck には効く。プロセスが生きているから、シグナルを受け取って動き出せる。しかし dead には原理的に無力だ。プロセスが消えていれば、シグナルの宛先がもういない。nudge は虚空に消える。

ここで重要なのは、「watchdog がある」という事実が「あらゆる落ち方から戻せる」を意味しないという点だ。watchdog は stuck 用の道具であって、dead 用の道具ではなかった。にもかかわらず、心理的には「復旧の仕組みは整っている」という錯覚があった。実際に dead が起きて初めて、その守備範囲の穴が露わになった。


「見える」と「戻せる」はまったく別の話だ

ここからが本質的な論点になる。

元記事は、復旧を「検知(detector)」と「作動体(actuator)」に明確に分けている。

  • detector は「壊れている」と気づくところまでしか担えない。アラートを出す、ログに記録する、人に知らせる——これは状態を「観測」する力だ。
  • actuator は「壊れた状態を変える」力だ。プロセスを再起動する、マシンを叩く、別系統から relaunch する——これは状態を「変更」する力だ。

こう書くと当たり前に聞こえるが、多くのチームは detector を手厚く作り、actuator を「作ったつもり」になる。検知は「見える」を保証するだけで、「戻せる」は一切保証しない。この非対称性が、運用の現場では驚くほど見落とされている。

別マシン上の dead なプロセスを戻すには、actuator として事前に配備された遠隔実行経路が必要だ。リモートでコマンドを打てる常駐エージェント、SSH等の遠隔シェル、あるいは「プロセスの死を跨いで生き残り、再起動をかけられるスケジューラ」。このチームの構成には、そのいずれも事前に入っていなかった。監視は各機にあったが、遠隔から再起動をかける経路がゼロだった。

結果、唯一残った actuator は——人間が、その物理マシンの前まで行って、電源とプロセスを手で立ち上げることだった。夜中に、だ。


actuatorは「落ちる前」にしか作れない。これが核心だ

遠隔実行経路(sshd、常駐再起動エージェント、死を跨ぐスケジューラ)は、復旧したいその対象自身の上に、あらかじめ仕込んでおく必要がある。プロセスが死んだ後に「じゃあ遠隔ログインを有効化しよう」としても、ログインする先がもう応答しない。元記事の表現を借りれば、「鍵を、締め出された後に家の中へ置きには行けない」。

detector は事後でもある程度足せる。外から ping を増やすだけでよい。しかし actuator は必ず事前配備でなければならない。この非対称性が、分散フリートの復旧設計の核だ。

ここからは見方だが、この非対称性が見落とされる理由には構造的な癖がある。監視ツールはSaaS化・外部化が進み、導入コストが下がっている。一方、actuatorの設計は「自分のインフラに手を入れる」作業であり、緊急性がないときにはどうしても後回しになる。つまり「監視は厚く、作動体は薄い」という構成が、業界全体のデフォルトになりやすい土壌がある。

AIエージェントの活用が広がるほど、この問題は深刻になる。単一のAPIを叩くスクリプトとは違い、複数のエージェントが別マシンで常駐し、互いにメッセージを送り合う構成では、どこかが dead になる確率は台数に比例して上がる。エージェントが増えれば増えるほど、actuatorの事前配備を怠った「借金」の返済コストは跳ね上がる。


実務に落とすと、やるべきことは3つに絞れる

元記事が提示する設計原則を実務に引き直すと、優先度の高い順にこうなる。

1. 障害クラスとactuatorの対応表を、空欄なく埋める

stuck には nudge、dead には遠隔 relaunch(事前配備)、delivery-gap には受信パイプの再起動——「どのクラスを、何が戻すか」の対応表を作り、空欄を「未対応」として明示する。「watchdog がある」ではなく「これは stuck 用であって dead 用ではない」と書く。守備範囲を曖昧にした安全装置は、守備範囲外で必ず破れる。

2. リハーサルしていないactuatorは、ないのと同じだと思え

元記事には明確に書いてある。「健全なノードで『わざと止めて、遠隔から戻す』を一度通しておく。検証していない actuator は、actuator が無いのとほぼ同じだ(いざ叩いたら権限不足・経路断で動かない、が定番の事故)」。これは耳が痛い。構築した経路が実際に通るかどうか、平常時に確認していないケースは多い。

3. blast radiusで対応の温度を可変にする

落ちた部品が critical path の上にあるかどうかで、復旧の緊急度を変える。元記事のケースでは、落ちたのは「翌朝の定型バッチ一本」にしか影響しない補助的な一台だった。その日の最重要タスクには無関係だった。この切り分けができていれば、「検知は常に最大感度で、対応の緊急度は影響範囲次第で抑制的にする」という二段構えが成立する。夜中の偽アラート疲れと、本当の取りこぼしの両方を避けられる。


次に問題になるのはどこか

AIエージェントのフリート運用が一般化していくと、次に論点になるのはおそらく「actuatorの標準化」だ。現状、遠隔再起動の経路設計は各チームが手作りしており、ベストプラクティスが共有されていない。Kubernetesのようなオーケストレーション層が自動的に担う部分もあるが、「死を跨いで生き残る再起動エージェントをどう配備するか」という問いへの汎用的な答えはまだ薄い。

もうひとつは責任の所在だ。エージェントが自律的に動くシステムでは、「誰がactuatorを管理しているか」が曖昧になりやすい。開発チームなのか、インフラチームなのか、あるいはAIエージェント自身が他のエージェントの復旧を担うのか。この問いは、組織設計とも絡む。


まとめ:「監視を厚くする」と「戻せる」は別の投資だ

この記事から持ち帰るべき判断軸は一つだ。自分のシステムの復旧設計を見るとき、「検知の経路」と「作動体の経路」を分けて棚卸しする習慣を持つこと。そして actuator の対応表に空欄があれば、それは「夜中に人間が現地へ行く」という隠れたコストとして存在している。

監視ダッシュボードが綺麗に揃っている現場ほど、この罠に落ちやすい。「見えている」という安心感が、「戻せる」という根拠のない自信に変換される。その錯覚を、夜中の障害対応で初めて気づくのか、それとも平常時のリハーサルで潰しておくのか——どちらを選ぶかは、今日の判断にかかっている。


参考元: 分散エージェントの「落ちた後」の復旧は、落ちる前にしか作れない——検知と作動体の分離