【入門編】CloudFormationのクロススタック参照における循環依存(Circular Dependency)発生時のリファクタリング手法と移行パターン – インフラ構成管理(IaC)活用バイブル

こんにちは。インフラの深淵を覗き込み、数多のシステム障害をコードで解決してきたSREエンジニアです。

今日は、AWS CloudFormationを使い始めた多くのエンジニアが一度は遭遇し、そして立ち尽くす「循環依存(Circular Dependency)」という壁についてお話しします。

「スタックAがスタックBの出力を参照し、スタックBがスタックAの出力を参照する」。この状態に陥ると、スタックの更新も削除もできなくなり、インフラが「手出し無用のブラックボックス」と化します。

今日はこの泥沼から脱出し、疎結合で堅牢なインフラを構築するための「究極の設計パターン」を伝授します。

—

1. なぜ「循環依存」は発生するのか?(本質を理解する)

CloudFormationの `Export` と `Fn::ImportValue` は非常に強力ですが、これらは「強固な結合」を強います。

  • 依存関係の可視化: スタックAがスタックBの値をインポートしている場合、スタックBを削除しようとすると「他のスタックから参照されているため削除できません」というエラーが出ます。
  • 循環の罠: AがBを参照し、BがAを参照すると、どちらのスタックも更新・削除の順序を決定できなくなり、デプロイメントパイプラインは完全に停止します。

これは、あなたが書いたコードが「密結合」になっているという、設計上のシグナルです。

—

2. 疎結合への移行:SSM Parameter Storeによる「脱・依存」

循環依存を断ち切るための最も強力な武器は、AWS Systems Manager (SSM) Parameter Store です。

`ImportValue` は「直接参照」ですが、SSMは「名前解決」です。スタックAは「Bの詳細は知らないが、SSMにあるこのキーの値を読みに行く」という挙動に変わります。これにより、スタック間の物理的な依存関係が切断されます。

ステップ1:値をSSMに書き出す(提供側)

まず、スタックB(提供側)のテンプレートを修正します。

提供側のスタック(例: Network Stack)
Resources:
MyVpcIdParameter:
Type: AWS::SSM::Parameter
Properties:
Name: /my-app/vpc-id # 一意のパスで名前を付ける
Type: String
Value: !Ref MyVpc # VPC IDをSSMに保存

ステップ2:SSMから値を読み取る(利用側)

次に、スタックA(利用側)で `ImportValue` を捨て、SSMから動的に取得します。

利用側のスタック(例: App Stack)
Parameters:
VpcId:
Type: AWS::SSM::Parameter::Value
Default: /my-app/vpc-id # ここで疎結合に参照!
Description: SSMからVPC IDを注入する

これで、スタック同士は物理的に結びつかず、SSMという「共通の辞書」を介して通信するようになりました。

—

3. リファクタリングの安全な移行手順(現場の鉄則)

いきなり全てを書き換えると事故が起きます。以下の「3段階移行法」を守ってください。

1. 二重書き込みフェーズ: 既存の `Export` を残したまま、新しい SSM Parameter を作成します。まだスタックAは `ImportValue` を使い続けます。
2. 参照切り替えフェーズ: スタックAを修正し、`ImportValue` から SSM 参照へ切り替えます。
3. クリーンアップフェーズ: 全ての参照が切れたことを確認してから、古い `Export` を削除します。

—

4. 基礎セットアップ:まずはここから始めよう

もし、これからCloudFormationを触るというなら、以下の「黄金の構成」から始めてください。

1. インストール不要: AWS CLIがインストールされた環境があれば、`aws cloudformation deploy` コマンドだけで完結します。
2. HelloWorld的な動作確認: 以下のYAMLを `template.yaml` として保存し、デプロイしてみましょう。

AWSTemplateFormatVersion: ‘2010-09-09’
Description: SRE流・疎結合の第一歩
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub “my-awesome-app-bucket-${AWS::AccountId}”
Outputs:
BucketName:
Value: !Ref MyBucket
Export:
Name: !Sub “${AWS::StackName}-BucketName” # 最初のうちはExportでOK

実行コマンド:

aws cloudformation deploy \
–template-file template.yaml \
–stack-name my-test-stack

—

先輩エンジニアからのアドバイス

「依存関係」は、システムが成長すればするほど複雑になります。最初から完璧な構成を目指す必要はありませんが、「何かを変えるときに、他のスタックを壊すリスクはないか?」と常に自問自答してください。

SSM Parameter Storeへの移行は、少し手間がかかるように感じるかもしれません。しかし、大規模なシステムにおいて「スタックを切り離せる」という状態は、あなたに圧倒的な安心感と、デプロイの自由を与えてくれます。

この設計をマスターすれば、どんな複雑なインフラでも恐れることはありません。さあ、次はあなたの番です。コードで、インフラを自由に操りましょう。

タイトルとURLをコピーしました