エムオーテックス株式会社が運営するテックブログです。

IaC未経験者によるCloudFormationスタック分割の記録

IaC未経験者によるCloudFormationスタック分割の記録

はじめに

こんにちは、プロフェッショナルサービス本部の山内です。 普段は、LANSCOPE エンドポイントマネージャー クラウド版のデバイス検査オプションの運用改善などを行っています。

この記事では、AWS CloudFormationを使い始めた当初にスタック分割でつまずいた自分だからこそ伝えられる、リアルな具体例とそこで考えたこと、結果こうなった!という道のりを書きます。

本記事の意図と注意事項

本記事はスタック分割の「正解例」ではなく、あくまで一つの参考事例です。スタック分割の初手を考える際のヒントとしてご活用ください。

前提・想定読者

このような方におすすめ

  • IaCやCloudFormationの経験があまりない方
  • ベストプラクティスは把握できているが、実際にスタックをどう分割するか悩んでいる方

本記事で扱う内容

本記事では、CloudFormationにおける「スタック分割」の考え方と具体的な実践例に絞って説明します。

  • スタック分割の具体例 (どのサービスをどのスタックにまとめたか)
  • リソース配置の根拠 (なぜそのリソースをそのスタックに置いたか)

本記事で扱わない内容

各種サービスの詳細な使い方、運用設計、テンプレート構成管理やCI/CDは、本記事の主旨から外れるため取り上げていません。

IaCを選択した背景と前提条件

複数人で並行してテストをするにあたり、利用できるAWS環境が1つしかないことが課題でした。環境の複製を検討しましたが、手動での複製はナレッジが蓄積されず、常時起動はコストを増加させてしまいます。 そこで今回、インフラをCloudFormationでコード化したことにより、誰でも同一環境を構築できるようにしました。必要な時だけリソースを作成する運用に切り替えることで、作業効率の向上とコストの最適化を両立しています。複製された環境は原則として日次で起動・停止(始業時にスタック作成、終業時に削除)し、この運用前提を反映したスタック分割設計をしています。

最終的なスタック分割まとめ

まずはじめに、私たちが最終的に整理したCloudFormationのスタック分割例をざっくりご紹介します。詳細や分割の理由については、続きでさらに掘り下げていきます。

  • Parameterスタック: Systems Manager(SSM) Parameter
  • IDスタック: IAM、Secrets Manager
  • NW(ネットワーク)スタック: VPC、ネットワーク関連、およびエッジサービス(ALB、API Gateway、AWS Certificate Manager(ACM)、Route 53、Amazon Simple Email Service(SES))
  • Computingスタック: EC2 Instance、Auto Scaling Group、Launch Template
  • Dataスタック: Aurora、DynamoDB、EFS、SQS、Microsoft AD、EventBridge Pipes

最終的なスタック分割の図

スタック分割全体像と方針

各スタック詳細の前に、分割方針や依存関係の整理について述べます。

スタック分割の方針

まず、下記資料を参考にし、「ライフサイクルと所有権によるスタック分割」に従って進めていました。
AWS CloudFormation 開発・テスト・デプロイ編(AWS Black Belt公式PDF)

しかしテンプレート作成を進めていく中で、これらの課題に直面しました。

  • スタック間の依存関係が複雑になりすぎて把握できない
  • 目的のリソースを探すときに、どのスタックを探せばよいか一つに特定できない

そこで、課題解決のため、以下の2点をルールとして定めました。

  • スタックの数を可能な限り増やさない
    • 理由: スタック間の依存関係を減らすため
  • リソースタイプごとにスタックを分け、同一リソースタイプが複数のスタックに存在しないようにする
    • 理由: 検索性を向上させるため

結果として、これらのルールはうまく機能し、課題が解決されました。また、スタック数が減ったことによって毎日の環境起動・停止という運用の簡素化にも寄与しました。

もちろん、スタック数を減らすことで、ひとつあたりのテンプレートサイズが大きくなるというデメリットもあります。しかし、今回大きくなったのは頻繁に変更のないNWスタックのみであったため、テンプレートサイズの肥大化よりも、スタック間の依存関係の整理を優先しました。

依存関係の整理

スタック間の依存関係の整理は、依存の向き(値の流れる方向)を意識して行いました。これによって、スタックの作成や削除における順序が自然とはっきりするので、簡単にでも整理しておくとよいです。

依存関係の図

スタックごとの詳細解説・構成要素

次に個別スタックの詳細に入ります。

1. Parameterスタック

  • 役割
    • 識別子レジストリ
  • 入れるもの
    • SSM Parameter(環境/用途ごとのキー規約で統一)
  • 入れないもの
    • 機密値(Secrets Managerへ)
    • 動的ID(他スタックのOutputs/Exportsに)
  • サイズ感
    • 規模: Small
    • Resource数: 10弱
    • 作成(実測値): 1分未満
  • Outputs/Exports
    • なし
  • Fn::ImportValue
    • なし

2. NWスタック

  • 役割
    • ネットワークと入口資産(ドメイン/TLS/API/メール)を一括管理
  • 入れるもの
    • VPC/Subnet/Route/ネットワークACL/SG、NATGW/IGW/EIP、VPC Endpoint
    • ALB/Listener/Target Group、API Gateway/ApiMapping
    • ACM、Route 53、SES、Instance Connect Endpoint、DHCPOptions
  • 入れないもの
    • Instance/Auto Scaling Group
    • DB/Storage/Queue
  • サイズ感
    • 規模: Large
    • Resource数: 150弱
    • 作成(実測値): 10分弱
  • Outputs/Exports
    • VPC ID
    • Subnet ID(DB用、NAT用、VPCE用、Storage用など)
    • SG ID
    • Target GroupなどのNWリソースID
  • Fn::ImportValue
    • なし

3. IDスタック

  • 役割
    • 権限と機密の集中管理。
  • 入れるもの
    • IAM Group/Role/Managed Policy/User、Instance Profile、Secrets Manager
  • 入れないもの
    • ネットワーク系リソース、サービス固有のSG
  • サイズ感
    • 規模: Medium
    • Resource数: 60弱
    • 作成(実測値): 5分弱
  • Outputs/Exports
    • IAMロールARN(監視・運用・連携用途)
    • EC2インスタンスプロファイルARN(アプリ/管理/メンテ用途)
  • Fn::ImportValue
    • なし

4. Computingスタック

  • 役割
    • 実行系。Network/ID/SSM/Secretsを参照して自律的に更新
  • 入れるもの
    • EC2 Instance、Launch Template、Auto Scaling Group、Scaling Policy
  • 入れないもの
    • ALB、Target Group(NWで集約)、IAM、Secrets Manager(IDで集約)
  • サイズ感
    • 規模: Medium
    • Resource数: 20弱
    • 作成(実測値): 5分弱
  • Outputs/Exports
    • なし
  • Fn::ImportValue
    • 各インスタンス用のSubnetやSG(NWスタックから)
    • 処理用インスタンスプロファイル/IAM Role(IDスタックから)

5. Dataスタック

  • 役割
    • 状態を持つリソースの集約(DB/Storage/Directory/Queue)
  • 入れるもの
    • Aurora(Cluster/Instance/Parameter/Subnet Group)、DynamoDB
    • EFS(File System/Mount Target)、SQS、Microsoft AD、EventBridge Pipes
  • 入れないもの
    • ALB、API Gateway、SG、IAM、Secrets Manager など
  • サイズ感
    • 規模: Large
    • Resource数: 30弱
    • 作成(実測値): 30分前後(RDS/EFS/ADで増加)
  • Outputs/Exports
    • なし
  • Fn::ImportValue
    • DBやRDSリソース用Subnet ID・SG ID(NWスタックから)
    • DB用途向けIAM(IDスタックから)

スタック分割の設計判断と根拠

スタック分割は既に示した基本方針に則っていますが、いくつかの判断について補足します。

まず、SES(EmailIdentity/ConfigurationSet)はドメイン認証との整合性とスタック数削減を優先し、エッジサービスと同居させる目的でNWスタックに置いています。ドメイン境界に近いリソースをネットワーク系と同一スタックに集約することで、設定や確認の散逸を防ぎます。

データフロー系については、PipesやSQSを「一時的な状態保持やデータ連携に関与する要素=状態を持つリソースに準ずるもの」と位置づけ、Dataスタックへ集約しています。これにより変更点の所在が明確になり、関連するリソースのライフサイクルを一括で扱えるため、結果としてスタック数も抑制できます。RDSのパラメータグループも同様に、DB本体と周辺設定を分断せずDataスタックに閉じることで、DB変更の影響範囲をスタック内に収め、運用判断を単純化しています。

ParameterスタックはSSM Parameterのみを置く構成ですが、これは過度分割ではなく運用メリットを狙った設計です。AMIなど環境依存のIDを一元管理し、テンプレートへIDを埋め込まないことで、差し替え作業をParameterの編集で完結させられます。結果としてデプロイの安定性と変更の可観測性が高まり、複数スタックへの反映も容易になります。

Dataスタック内にDynamoDBとRDS/EFSをまとめる点は、一般的には技術境界による分割と見られがちですが、本件では「毎日起動/停止を前提とすること」と「同一リソースタイプを跨がせないこと」を優先しています。状態を持つリソースを一括管理するほうが停止・起動手順や依存関係の把握が明確になり、むしろ運用が単純化すると判断しています。

セキュリティグループのIngressルール管理については、トレーサビリティ低下を避けるための運用ルールを設けています。個別化は循環参照を避ける必要がある箇所に限定し、必ず対応するSG本体定義の直後にIngressを並べます。さらに定義をNWスタックに集約することで確認箇所を1か所に絞り、SGとルールの対応関係をテンプレート上で一目で追えるようにしています。これらの方針により、分割の整合性を保ちながら運用負荷を最小化しています。

おわりに

最初は「正しく分ける」が難題でしたが、依存を揃え、タイプを集約し、スタック数を抑えるだけで霧が晴れました。結果として、検索・変更・起動・停止の負荷が目に見えて軽くなりました。もちろん万能ではないため、分割境界は運用データとフィードバックを基に継続的に見直します。チームの責務分担や変更頻度に応じて、最適な境界は変わります。だからこそ原則を言語化し、例外を管理することが重要です。本記事が皆さまの分割方針を決める小さな後押しになれば幸いです。

Appendix

スタック構成と配置したリソースタイプ一覧

スタック名 役割・特徴 主なリソースタイプ
Parameterスタック 識別子レジストリ AWS::SSM::Parameter
NWスタック ネットワークと入口資産の一括管理 AWS::EC2::VPC
AWS::EC2::Subnet
AWS::EC2::RouteTable
AWS::EC2::SecurityGroup
AWS::EC2::InternetGateway
AWS::EC2::NatGateway
AWS::EC2::VPCEndpoint
AWS::EC2::DHCPOptions
AWS::ElasticLoadBalancingV2::LoadBalancer
AWS::ElasticLoadBalancingV2::Listener
AWS::ElasticLoadBalancingV2::TargetGroup
AWS::ApiGateway::RestApi
AWS::ApiGateway::Stage
AWS::ApiGateway::Deployment
AWS::ApiGatewayV2::DomainName
AWS::ApiGatewayV2::ApiMapping
AWS::CertificateManager::Certificate
AWS::Route53::RecordSetGroup
AWS::SES::EmailIdentity
AWS::SES::ConfigurationSet
AWS::EC2::InstanceConnectEndpoint
IDスタック 権限・機密の集中管理 AWS::IAM::Group
AWS::IAM::Role
AWS::IAM::User
AWS::IAM::ManagedPolicy
AWS::IAM::InstanceProfile
AWS::SecretsManager::Secret
Computingスタック 実行層(計算リソースの配置) AWS::AutoScaling::AutoScalingGroup
AWS::EC2::Instance
AWS::EC2::LaunchTemplate
AWS::AutoScaling::ScalingPolicy
Dataスタック 状態を持つリソースの集約 AWS::RDS::DBCluster
AWS::RDS::DBInstance
AWS::RDS::DBSubnetGroup
AWS::RDS::DBParameterGroup
AWS::RDS::DBClusterParameterGroup
AWS::DynamoDB::Table
AWS::EFS::FileSystem
AWS::EFS::MountTarget
AWS::SQS::Queue
AWS::DirectoryService::MicrosoftAD
AWS::Pipes::Pipe