User Poolはインフラではなくデータである — Terraformスタック分割の2軸

前回、素のterraform destroyでCognito User Poolごと消し飛ばし、ユーザー登録を全滅させた。復旧後にTerraformを認証基盤(infra/auth)と実行基盤(infra/service)の2スタックに分離したのだが、その反省会で「なぜ分けるのか」を言語化したら思いのほか汎用的な設計論になったので、書き残しておく。

軸1: 重要だから守るのではない。作り直せないから守る

最初は「ユーザー情報は重要だから隔離する」と考えかけた。これは半分しか合っていない。

ECSもALBもACM証明書も重要だ。落ちればサービスは止まる。しかしこれらは設計図(コード)から寸分違わず再生成できる。だから壊しても実は何も失わない。現に構築当日、再現性の検証と称して本番環境を2回壊して2回作り直した。壊せることは欠点ではなく、Infrastructure as Codeの成果そのものである。

一方、User Poolは違う。Terraformコードに書いてあるのは「こういう設定のプールがある」ことだけで、「誰が登録されているか」という状態はコードの外にある。壊したら戻らない。ユーザー全員に「もう一度登録してください」と頭を下げる羽目になる。

つまり分離の第一の基準は重要度ではなく再現可能性だ。

  • インフラ = コードから再生成できるもの。git が真実。気軽に壊して再現性を検証すべき
  • データ = 再生成できない状態を持つもの。破壊経路から隔離し、削除保護を付け、本気ならバックアップする

User Poolは後者である。インフラの顔をしたデータなのだ。

重要度が無意味なわけではない。効いてくるのは「保護の厚み」の判断だ。うちの会話履歴DB(EFS上のSQLite)も再現できないデータだが、今はデモデータなので、実行基盤と一緒に消えることを許容している。顧客の履歴を預かる日が来たら、同じ「再現できないデータ」でも扱いが変わる。置き場所は再現可能性で決め、保護の厚みは重要度で決める。

軸2: 壊したとき、誰が巻き添えになるか

分離にはもう1つの軸がある。依存の広がり(爆風半径)だ。

実行基盤に依存しているのは、そのサービス1つだけである。voice.pocraft.netの実行基盤を壊しても、被害はvoice.pocraft.netで完結する。

認証基盤は違う。User Poolは複数のサービスから参照され得る共有層だ。次のデモアプリを作るとき、同じプールを指せばユーザー登録を使い回せる——顧客は一度登録すれば、こちらの出すデモ全部にログインできる。フリーランスのデモ運用では、これは積極的に共有したい資産である。共有層を壊すと、将来の全サービスが巻き添えになる。

実はこの思想は構成のもう1箇所に無意識に現れていた。Route53のホストゾーン(pocraft.net)を、実行基盤のTerraformはresourceではなくdataで参照している。所有せず、レコードを1本足すだけ。ゾーンはブログなど他の用途とも共有される基盤だから、サービスのdestroyで消えてはならない——スタック分割と同じ判断を、こちらは最初から自然にやっていた。人は「明らかに共有のもの」には慎重になれるが、「1サービス目では専有に見えるもの」の共有性を見落とす。User Poolはまさにそれだった。

2軸で見ると、分割は二重に正当化される

問い 認証基盤 実行基盤
再現可能性 壊したらコードから戻るか 戻らない(ユーザー登録という状態) 戻る
依存の広がり 壊したら誰が巻き添えか 将来の全サービス そのサービスだけ

両軸とも同じ答えを指している。認証=守る層、実行=使い捨て層。だからstateを分け、守る層にはdeletion_protection = "ACTIVE"を付け、使い捨て層はterraform destroy一発で消せるままにしておく。

なお実行スタックは認証スタックの出力(pool ID等)をterraform_remote_stateで読む。参照の向きは常に「使い捨て層 → 守る層」の一方向で、逆はない。守る層は下の事情を知らない。

最終形は3層

正直に言うと、今の構成には妥協が1つある。会話履歴(EFS)という「再現できないデータ」が、使い捨てのはずの実行基盤に同居していることだ。デモデータのうちは許容だが、預かりものになったら引っ越しが要る。

行き着く先はおそらくこうだ。

  1. 認証層 — User Pool。共有・状態あり。原則destroyしない
  2. データ層 — 履歴DBなど。専有だが状態あり。バックアップ付き
  3. 実行層 — ECS/ALB/証明書。ステートレス。壊し放題

教訓は一行にまとまる。壊してよいものと壊してはならないものを、同じstateに置くな。 それを見分けるのは重要度ではなく、「作り直せるか」と「誰が巻き添えか」の2つの問いである。

リポジトリ(公開しました): github.com/yoshiharu-ishii/realtime_voice


リアルタイム音声AI 開発シリーズ

シリーズ目次(全7回のあらすじ)はこちら

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール