CloudFormation スタック間で値を渡す方法:Export/Import・Nested Stack・SSM Parameter Store の違い
CloudFormation でインフラを複数スタックに分割すると、必ず「あるスタックのリソース ID や ARN を、別のスタックからどう参照するか」という問題にぶつかります。代表的な方法である Export/Fn::ImportValue・Nested Stack・SSM Parameter Store について、仕組みと使い分けを整理します。
1. Export / Fn::ImportValue
出力元のスタックで Outputs に Export を定義し、参照側のスタックで Fn::ImportValue を使って読み込む方式です。
# 出力側スタック
Outputs:
VpcId:
Value: !Ref Vpc
Export:
Name: shared-network-vpc-id
# 参照側スタック
Resources:
WebSg:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !ImportValue shared-network-vpc-id
特徴
- CloudFormation ネイティブの機能で、追加のリソースが不要。
- Export された値は、Import している他のスタックが1つでも存在する限り、Export元スタックを更新・削除できない(値そのものを変更する更新も不可)。この密結合が最大の弱点。
- Export 名はリージョン内でグローバルに一意である必要があり、命名衝突に注意が必要。
向いているケース:VPC ID やベース ドメイン名など、めったに変更されない基盤系の値を、多数のスタックへ配布する場合。
2. Nested Stack
親スタックの中で AWS::CloudFormation::Stack リソースとして子テンプレートを呼び出し、子スタックの Outputs を親テンプレート内で !GetAtt ChildStack.Outputs.XXX として直接参照する方式です。
Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://.../network.yaml
AppStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://.../app.yaml
Parameters:
VpcId: !GetAtt NetworkStack.Outputs.VpcId
特徴
- 親子関係が1つの「デプロイ単位」として管理され、
update-stack/delete-stackも親スタック経由で一括実行される。 - Export/Import のような「他が参照しているから削除できない」問題が起きにくい(親スタックのライフサイクルに閉じるため)。
- 一方で、子テンプレートは S3 にアップロードしておく必要があり、ビルド・デプロイの手順が増える。
- 親スタックのイベント・ドリフト検出・ロールバックが子スタックにも連鎖するため、デプロイの影響範囲が広がりやすい。スタック数が多くなるとネストが深くなり見通しが悪化する。
向いているケース:常に一緒にデプロイ・破棄される密接なリソース群(例:1つのマイクロサービスが持つ Lambda・DynamoDB・API Gateway 一式)をテンプレートとして部品化したい場合。
3. SSM Parameter Store
値をスタックの外、Systems Manager Parameter Store に保存しておき、出力側・参照側の両方がそこを介して読み書きする方式です。
# 出力側:値をパラメータとして書き込む
Resources:
VpcIdParam:
Type: AWS::SSM::Parameter
Properties:
Name: /shared/network/vpc-id
Type: String
Value: !Ref Vpc
# 参照側:動的参照で読み込む(デプロイ時に解決)
Resources:
WebSg:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: "{{resolve:ssm:/shared/network/vpc-id}}"
特徴
- スタック同士が CloudFormation レベルで直接依存しない。Export/Import のような「参照されているから削除できない」制約がない。
{{resolve:ssm:...}}はテンプレートのデプロイ実行時に値を解決するため、値が更新されても該当パラメータを参照している別スタックへ自動反映はされない(明示的に再デプロイが必要)。ここは Export/Import と似た制約。- 別スタック・別リポジトリ・別チーム間で値を共有する場合でも、CloudFormation の枠を超えて(CLI・Lambda・他の IaC ツールからも)同じ値を参照できる汎用性がある。
- パラメータ自体に IAM ポリシーをかけられるため、誰が読み書きできるかを個別に制御しやすい。
向いているケース:チームをまたぐ疎結合な連携、CloudFormation 以外のツール(CDK、Terraform、アプリケーションコードなど)からも同じ値を参照したい場合。
比較まとめ
| 方式 | 結合度 | 削除時の制約 | 適用範囲 | 追加コスト |
|---|---|---|---|---|
| Export / Fn::ImportValue | スタック間で密結合 | Import 元が残っていると Export 元を更新・削除不可 | 同一リージョン内の CFn スタック限定 | なし |
| Nested Stack | 親子で密結合(1デプロイ単位) | 親を消せば子も消える。他スタックからの分離度は高い | 親テンプレート配下に閉じる | S3 へのテンプレート配置が必要 |
| SSM Parameter Store | 疎結合 | 制約なし(パラメータは独立して存在) | CFn 以外のツール・チームからも参照可 | パラメータ数に応じた管理コスト(Standard は無料枠あり) |
使い分けの指針
- 同じチームが管理する、変更頻度の低い基盤値(VPC・共通 KMS キーなど)を複数スタックへ配るだけなら、手軽な Export/Import で十分なことが多い。ただし更新・削除のしにくさは把握した上で使う。
- 常に一緒にデプロイ/破棄されるリソース群をテンプレートとして部品化したいなら Nested Stack。ただしネストが深くなりすぎないよう注意する。
- チーム・リポジトリをまたぐ連携や、CloudFormation 以外のツールからも参照したい値は SSM Parameter Store が最も柔軟。近年は疎結合を優先してこちらを標準にするチームも増えている。
いずれも「密結合でシンプルだが変更に弱い」か「疎結合で柔軟だが管理対象が増える」かのトレードオフがあり、スタック分割の単位・チーム構成・変更頻度に応じて選ぶのが基本方針です。