ステートフルなオーケストレーションに潜む隠れたコスト
SchemaBridge Team · 2026-02-02 · Distributed Systems, Immutable Infrastructure, Orchestration, Anti-Patterns, Reliability
なぜあなたの「シンプルな」社内ツールが最大の信頼性リスクになり得るのか、そしてImmutable Infrastructureのパターンをアプリケーションロジックに適用することでどう救われるのかを解説します。
マイクロサービスの世界では、私たちは疎結合であることに執着します。キューを使い、イベント駆動型アーキテクチャを採用し、モノリスを分割します。しかし、オーケストレーションエンジンの内部では、分散システムにおける最大の罪を犯しがちです。私たちはステートフルなループを書いてしまうのです。
SchemaBridgeでは最近、コアとなるシステムワークフローを全面的に見直しました。その過程で、多くのエンジニアリング組織を悩ませているのと同じアンチパターンに直面することになりました。これは単なるリリースノートの話ではなく、Immutable Infrastructureの原則をアプリケーション層に適用する際のケーススタディです。
「ループ」というアンチパターン
古典的な「ポーラー(Poller)」を考えてみましょう。
while not deployment.is_ready():
sleep(60)
check_status()
このコードは、安定した宇宙を前提としています。つまり、ポーリングプロセスが永遠に生き続けることを前提としているのです。実際には、これは分散モノリス(Distributed Monolith)の産物にほかなりません。[AWS Builders' Library]でも指摘されている通り、長時間稼働する同期的な状態への依存は、「ゾンビ」プロセスや予測不可能な障害モードを生み出します。
解決策:再帰的チェイニング
私たちは内部的な while ループから、関数型プログラミングで使われる継続渡しスタイル(Continuation Passing Style)や分散トランザクションにおけるSagaパターンに似た、再帰的実行モデルへと移行しました。
- パターン: ステップAはステップBを「待つ」ことをしません。ステップAはステップBを新しい独立したワークフローとして生成(spawn)します。
- 結果: 「保持」状態がゼロになります。オーケストレーターが停止しても、データベースの状態(ステップBがキューに入っている状態)が真実の情報源であり続けます。
イミュータブルなロジック:「コンテンツアドレス可能」なIDを用いたバージョニング
バージョニングが難しいことはよく知られています。ワークフロー定義を更新したとき、すでに実行中かもしれない実行(Execution)には何が起きるのでしょうか?
- アンチパターン: 「インプレース更新」。新しいコードをデプロイすると、既存の実行が突然異なる振る舞いを始めてしまいます。
- 業界標準: Immutable Infrastructure。サーバーにSSHでログインしてパッチを当てるのではなく置き換えるのと同じように、実行中のワークフロー定義にパッチを当てるべきではありません。
私たちは正規DSLハッシュ化(Canonical DSL Hashing)を実装しました。
ワークフローロジックの抽象構文木(AST)をハッシュ化することで、すべてのバージョンを一意でコンテンツアドレス可能なエンティティとして扱います。これはtemporal.ioなどの最新のエンジンで採用されている戦略と一致するものです。実行のIDはコードのIDに紐づくのです。
「ゴッドモード」を封じ込める
最後に、社内ツールのセキュリティに取り組みました。社内の「クリーンアップ」スクリプトにroot権限を与えることはよくあることです。しかしこれは最小権限の原則(Principle of Least Privilege)に反します。
調査の結果、私たち自身の社内「段階的ロールアウト」ツールが、重要なシステムIDを上書きできてしまう状態にあることが分かりました。これを封じるため、暗号学的に検証されたシステムアクターだけが特定の論理IDを要求できる「Sudo」パターンを導入しました。
まとめ
オーケストレーションが sleep() に依存しているなら、あなたはクラウドと戦っていることになります。
再帰、イミュータビリティ、そして厳密なIDを取り入れることで、私たちは「願望ベース」のオーケストレーションから「証明ベース」のオーケストレーションへと移行できます。
参考リンク: