7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS CloudFormation】スタック運用でハマらないための実務Tips

Last updated at Posted at 2025-12-08

※2025年12月時点の情報です。

はじめに。

AWS経験歴2年の神谷です。
経験してきた中で一番便利だと感じたCloudFormationスタックについて紹介します。

CloudFormationはテンプレートを書くところから始まりますが、実際の運用で効いてくるのは「スタックをどう扱うか」です。この記事では、スタックの基本、更新時の安全装置、削除時の振る舞い、ドリフト検出、分割の考え方、そして現場でよくある失敗と対処までをひととおりまとめました。


読者ターゲット

  • AWSを業務で使っているが、CloudFormationはまだ部分的にしか触っていない方
  • スタック更新で失敗した経験があり、安全な運用方法を知りたい方
  • IaCを導入したいが、運用フェーズの落とし穴を理解したいチームリーダー
  • AWS認定資格(SAA/DevOps)を勉強中で、実務的なTipsを探している方

目次

  1. スタックとは?テンプレートとの違い
  2. スタックのライフサイクル(作成/更新/削除)
  3. 更新を安全にする仕組み(Change Set/Stack Policy/Termination Protection)
  4. DeletionPolicyの使い分け(Retain/Snapshot/Delete)
  5. 更新の落とし穴(依存関係/不可変更属性/Replace)
  6. ドリフト検出の運用
  7. StackSets・Nested Stacks・Exports/Importsの設計の考え方
  8. パラメータ運用のベストプラクティス
  9. 実務Tips(段階的デプロイ/タグ/ログの読み方)
  10. よくある失敗例と再発防止策
  11. まとめ

1. スタックとは?テンプレートとの違い

  • テンプレートは設計図(YAML/JSON)。ResourcesParametersなどの宣言を持ちます。
  • スタックはテンプレートに具体のパラメータを与えて作ったリソースの集合体。イベントや状態、履歴を持つ“運用単位”です。
  • 同じテンプレートでも、パラメータを変えれば環境(dev/stg/prod)ごとに別スタックを作れます。運用視点では「テンプレートの書き方」だけでなく「スタックをどう分けて、どう更新するか」が重要です。

2. スタックのライフサイクル(作成/更新/削除)

作成(create-stack)

aws cloudformation create-stack \
  --stack-name app-network \
  --template-body file://network.yaml \
  --parameters \
      ParameterKey=VpcCidr,ParameterValue=10.0.0.0/16 \
      ParameterKey=PublicSubnetCidr,ParameterValue=10.0.1.0/24 \
  --capabilities CAPABILITY_NAMED_IAM
  • コンソールのEventsCREATE_IN_PROGRESS → CREATE_COMPLETEの流れを追います。
  • 失敗時は既定でロールバックします(ROLLBACK_IN_PROGRESS → ROLLBACK_COMPLETE)。

更新(update-stack)

aws cloudformation update-stack \
  --stack-name app-network \
  --template-body file://network.yaml \
  --parameters ParameterKey=PublicSubnetCidr,ParameterValue=10.0.2.0/24
  • 一部の属性は**不可変更(immutable)で、変更を試みると置換(Replace)**が発生します。
  • Replaceは「新規作成→切り替え→旧リソース削除」のため、IPやDNSの変更、停止時間に影響します。

削除(delete-stack)

aws cloudformation delete-stack --stack-name app-network
  • 個々のリソースの扱いはテンプレート側のDeletionPolicyで決まります(後述)。

3. 更新を安全にする仕組み(Change Set/Stack Policy/Termination Protection)

Change Set(事前プレビュー)

更新時に何が起きるかを先に確認できます。運用では習慣化したいところです。

aws cloudformation create-change-set \
  --stack-name app-network \
  --change-set-name preview-202512 \
  --template-body file://network.yaml

aws cloudformation describe-change-set \
  --stack-name app-network \
  --change-set-name preview-202512
  • 追加・変更・削除・置換の差分が見えます。特に本番では必須に近い扱いにしたいです。

Stack Policy(クリティカル保護)

重要リソース(例:S3バケット、IAMロール)への削除や置換を防ぐポリシーです。

{
  "Statement": [
    { "Effect": "Allow", "Action": "Update:*", "Principal": "*", "Resource": "*" },
    { "Effect": "Deny", "Action": ["Update:Delete","Update:Replace"], "Principal": "*", "Resource": "LogicalResourceId/ProdBucket" }
  ]
}

適用:

aws cloudformation set-stack-policy \
  --stack-name app-prod \
  --stack-policy-body file://stack-policy.json

Termination Protection(削除防止)

誤削除を物理的にブロックします。

aws cloudformation update-termination-protection \
  --stack-name app-prod \
  --enable-termination-protection

4. DeletionPolicyの使い分け(Retain/Snapshot/Delete)

Resources:
  ProdBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain   # スタック削除でも残す(データ保護)
  Database:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Snapshot # 削除時に自動スナップショット
  TempQueue:
    Type: AWS::SQS::Queue
    DeletionPolicy: Delete   # デフォルト相当。痕跡を残さない

実務の感覚

  • 本番のデータ系は基本的にRetainSnapshot
  • Retainはリソースが孤立しやすいので、命名規約・タグ設計で追跡できるようにしておきます。
  • PRレビューでDeletion差分(Delete指定の追加など)を確認する習慣をつけると事故が減ります。

5. 更新の落とし穴(依存関係/不可変更属性/Replace)

  • 暗黙依存はCloudFormationが推測してくれますが、要所は明示した方が安全です(DependsOnRefFn::GetAtt)。
  • 不可変更属性に触れるとReplaceを誘発します。影響(IP変更、DNS切替、ダウンタイム)を見積もり、必要ならblue/greenを前提に設計します。
  • セキュリティグループの相互参照や、LambdaとIAMロールのポリシー生成などは循環依存になりがち。片方向参照に整理するか、固定CIDRで一時回避するなどの対処を考えます。

6. ドリフト検出の運用

aws cloudformation detect-stack-drift --stack-name app-prod
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id <ID>
aws cloudformation describe-stack-resource-drifts --stack-name app-prod
  • 本番は基本的に手動変更禁止。やむを得ない場合は例外運用を記録し、速やかにテンプレートへ反映します。
  • 許容したい差分はParametersやSSM Parameterに逃がす設計にします。

7. StackSets・Nested Stacks・Exports/Importsの設計の考え方

StackSets(複数アカウント/リージョン展開)

組織横断のガイドラインや標準VPCなどの一斉配布に向いています。更新の波及範囲が大きいので、テンプレートは小粒にしておく方が扱いやすいです。

Nested Stacks(テンプレート分割)

大規模構成は、network/security/compute/dataなどに分けてモジュール化しておくと、変更の影響範囲が読みやすくなります。親→子のOutputs連携で疎結合に。

Exports/Imports(クロススタック参照)

Outputs:
  VpcId:
    Value: !Ref Vpc
    Export:
      Name: !Sub "${AWS::StackName}-VpcId"

共有値の再利用に便利ですが、Export名の変更や削除には制約が強めです。長期運用ではSSM Parameter Storeなども選択肢に入ります。


8. パラメータ運用のベストプラクティス

  • Defaultは最小限(誤デプロイ防止)。機密値はNoEcho: true
  • AllowedValuesAllowedPatternで入力制約をかけておくと事故が減ります。
  • SSMパラメータ参照で環境差分を外に出す:
Parameters:
  AmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/prod/amis/web'
  • MetadataParameterGroups/Labelsでコンソールの入力UIを整えておくと、共同作業がラクになります。

9. 実務Tips(段階的デプロイ/タグ/ログの読み方)

段階的デプロイ

  1. Change Setで差分を確認
  2. 非破壊変更のみ適用
  3. 破壊的変更はblue/green(新スタック→切替→旧削除)

タグ設計

  • Stack=app-prod / Env=prod / Owner=team-x などを全リソースへ付与。料金可視化や監査、Retainした孤立リソースの探索に効きます。

ログの読み方(Events)

  • 失敗時は最初のERRORではなく、その直前のイベントで原因を探します。
  • 物理IDから各サービスのコンソールへ飛んで詳細を確認します。
  • CloudTrailで権限不足(AccessDenied)が出ていないかも併せて見ると早いです。

10. よくある失敗例と再発防止策

  • 本番S3を誤削除DeletionPolicy: Deleteのまま適用。→ Stack Policy+DeletionPolicy: Retainを標準に。PRで削除差分をチェック。
  • ALBの設定変更でReplaceが発生:不可変更属性に触れた。→ 新リスナーを用意して段階的に切替(blue/green)。Change Setで事前に検知。
  • 手動でSGを調整して疎通OK→後の更新で消えた:ドリフトをテンプレートへ還元していない。→ ドリフト検出を定期運用、変更は必ずテンプレート経由。
  • Nested Stackの子で失敗して親が大きくロールバック:大変更を一括適用。→ 小刻みに適用、子スタック単位で先に検証。

11. まとめ

  • Change Set/Stack Policy/Termination Protection/DeletionPolicyを組み合わせて安全性を担保します。
  • Replaceの可能性は常に見積もり、必要ならblue/greenを前提に設計します。
  • ドリフト検出で“手動の誘惑”からスタックを守り、IaCの一貫性を維持します。
  • 分割(Nested/StackSets)とタグ設計で、長期運用に耐える形に整えます。

付録:最小構成テンプレート(抜粋)

AWSTemplateFormatVersion: '2010-09-09'
Description: Simple VPC with one public subnet and internet access

Parameters:
  VpcCidr:
    Type: String
    Default: 10.0.0.0/16
    AllowedPattern: '^([0-9]{1,3}\\.){3}[0-9]{1,3}\\/([0-9]|[1-2][0-9]|3[0-2])$'
  PublicSubnetCidr:
    Type: String
    Default: 10.0.1.0/24

Resources:
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-vpc'

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref Vpc
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref Vpc
      CidrBlock: !Ref PublicSubnetCidr
      MapPublicIpOnLaunch: true

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc

  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
    DependsOn: AttachGateway

  PublicSubnetRtAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

Outputs:
  VpcId:
    Value: !Ref Vpc
    Export:
      Name: !Sub '${AWS::StackName}-VpcId'
  PublicSubnetId:
    Value: !Ref PublicSubnet
7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?