破綻するモノリスを解体せよ:CloudFormation Nested Stacksによるインフラのドメイン駆動設計
インフラをコード化(IaC)した結果、数千行に及ぶ「死の巨大YAML」を抱え、修正のたびに冷や汗をかく。それが君の現状ではないか?
AWS CloudFormationは、単なるプロビジョニングツールではない。大規模環境において、我々エンジニアが真に恐れるべきは「依存関係のスパゲッティ」と「ロールバックの地獄」だ。今回は、Nested Stacksを単なる「テンプレートの分割」としてではなく、インフラのドメイン駆動設計(DDD)におけるコンテキスト境界の分離として昇華させる手法を伝授する。
—
1. 単一テンプレートの限界:なぜ「巨大スタック」は死を招くのか
CloudFormationには「1つのテンプレートにつき500リソース」という制限がある。だが、真の問題はリソース数ではない。「変更の影響範囲(Blast Radius)」だ。
モノリシックなテンプレートでは、VPCを少し修正するだけで、その背後にいる数百のECSサービスやLambdaまでが再評価の対象となる。これは、CI/CDパイプラインにおいて「デプロイのボトルネック」を意味する。
真のアーキテクトは、スタックを「変更頻度」と「ライフサイクル」で分離する。
2. コンポーネントの抽象化:階層構造の設計指針
VPCやセキュリティグループといった「プラットフォーム層」と、ECSやRDSといった「アプリケーション層」を同一ライフサイクルで管理してはならない。
- Foundation Stack (L0): ネットワーク(VPC, Subnet, NACL)。変更頻度は極めて低い。
- Platform Stack (L1): 共有基盤(IAM Roles, Security Groups, Base ALBs)。
- Application Stack (L2): ビジネスロジック(ECS Service, Lambda, DynamoDB)。
これらをNested Stacksで繋ぐことで、個別のスタックが独立してデプロイ可能になり、万が一の障害時も「影響範囲を最小化」できる。
3. 深淵なるデータ連携:OutputsとParametersの厳格な型付け
親から子へのパラメータ渡しは、単なる転送ではない。「インターフェースの設計」だ。
以下の例では、親スタックがVPC IDを子スタックへ注入する典型的なパターンを示すが、ここで重要なのは`Export/Import`よりも`Nested Stacks`の直接パラメータ渡しを優先することだ。`Export`はスタック間の疎結合を装いつつ、実際には強い依存関係を生み、削除を極めて困難にするからだ。
親スタックの定義例
Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./network.yaml
Parameters:
Environment: !Ref EnvName
AppStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./ecs-service.yaml
Parameters:
# 親から子へ、必要な情報のみを注入する「依存注入」
VpcId: !GetAtt NetworkStack.Outputs.VpcId
SubnetIds: !GetAtt NetworkStack.Outputs.PublicSubnets
4. 運用管理の極意:完全自動化とデプロイのハック
手動で`aws cloudformation deploy`を叩いているようでは、まだアマチュアだ。大規模運用では、テンプレートの妥当性検証と、ドリフト(乖離)検知をパイプラインに組み込む必要がある。
独自自動化スクリプトの勘所
私は、スタック更新時のパフォーマンスを最大化するため、以下のPythonラッパーを用いている。
import boto3
高度な運用ハック:
大規模スタックの更新中に「WAITING」状態でスタックするのを防ぐため、
変更セット(ChangeSet)の実行前に必ずドリフトチェックを走らせる。
def validate_and_deploy(stack_name, template_body):
cf = boto3.client(‘cloudformation’)
# 1. テンプレートのLintチェック (cfn-lintは必須)
# 2. 変更セットを作成し、破壊的変更がないか確認
cs = cf.create_change_set(
StackName=stack_name,
TemplateBody=template_body,
Capabilities=[‘CAPABILITY_IAM’, ‘CAPABILITY_NAMED_IAM’]
)
# 3. 変更内容をログに出力し、人間がレビュー可能な状態で承認フローへ
パフォーマンス最適化のハック
- `–parallel-urls`の活用: 多数のネストされたスタックを同時並行で処理させるには、AWS CLIの`–parallel-urls`オプションを使い、階層の深さに応じたトポロジカルソートを自動化せよ。
- メタデータの最小化: 大規模スタックでは、テンプレート内の不要なコメントやMetadataセクションがメモリ消費を増大させる。ビルドパイプラインでYAMLをminify(圧縮)してS3にアップロードするのは、現場では常識的な最適化だ。
最後に:伝説的エンジニアからの提言
CloudFormationのNested Stacksは、ただの「機能」ではない。それは、君の組織のインフラ運用能力を写す鏡だ。
複雑さを隠蔽しようとしてはいけない。むしろ、コンポーネントを明確に分割し、インターフェースを厳格に定義することで、複雑さを「管理可能な単位」まで分解するのだ。
インフラは、一度作って終わりではない。コードと同じく、リファクタリングを繰り返し、常に「変更に強い状態」を維持し続けろ。それが、真のSREの仕事だ。
何か質問はあるか? 深淵を覗く覚悟があるなら、いつでも回答しよう。