【実務・中級編】CloudFormation DeletionPolicyとDependsOnを組み合わせた安全なリソース置き換え(Blue/Greenデプロイ風)の実現手法 – インフラ構成管理(IaC)活用バイブル

こんにちは。テックリードの私だ。

本番環境のデータベースや、厳格にIP固定されたネットワーク基盤、あるいはステートフルなECSサービスをCloudFormationで管理していて、「リソースのスキーマ変更(例えばRDSのインスタンスクラス変更や、S3バケットの置き換え、セキュリティグループの再定義など)」で冷や汗をかいた経験はないだろうか?

CloudFormationはデフォルトで「インプレース更新(既存を維持した変更)」を試みるが、プロパティによっては強制的な「置き換え(Replace = 削除して作り直し)」が発生する。これが本番環境でどうなるか。何も考えずに `aws cloudformation deploy` を叩けば、「先に削除(DELETE)」が走り、その後に「作成(CREATE)」が走るため、容赦なくダウンタイムが発生する。数秒の停止すら許されないSREの現場において、これは悪夢以外の何物でもない。

今回は、CloudFormationの奥義である `DeletionPolicy` と `DependsOn` を極限まで組み合わせ、本番環境でダウンタイムゼロの「Blue/Greenデプロイ風リソース置き換え」を実現する実戦的テクニックを授けよう。

—

1. 現場の生産性を極限まで高める:開発環境セットアップの極意

本番の安全性を語る前に、まず我々の開発スピードを爆発的に高めるための「隠しコマンド」と「神プラグイン」を共有しておく。これなしでIaCを書くのは、素手でバグだらけのレガシーコードに立ち向かうようなものだ。

開発スピードを加速させるキーボードショートカット (VSCode)

  • `Ctrl + Space` (リソース補完の強制的呼び出し): CloudFormation Linterと連携させ、リソースプロパティの候補を瞬時に引き出す。
  • `Shift + Alt + F` (ドキュメントフォーマット): インデントのズレによるYAMLの構文エラー(タブ混入の悲劇)を完全予防。
  • `Ctrl + Shift + V` (Markdownプレビュー): 巨大化したCFnテンプレートの構造を視覚的に俯瞰する。

絶対に入れるべき神VSCodeプラグイン

1. AWS CloudFormation Linter (aws-cfn-lint):
リソースの構文だけでなく、AWSのベストプラクティスやリージョン固有の制約違反をリアルタイムで検知する。これなしでデプロイパイプラインにコードを流すのは厳禁だ。
2. YAML Support by Red Hat:
カスタムCloudFormationタグ(`!Sub`, `!Ref`, `!GetAtt` など)のYAMLパースエラーを防ぐために必須。
3. Rainbow CSV / Indent-Rainbow:
多階層になりがちなYAMLのインデント視認性を爆上げし、コピペミスを根絶する。

チーム開発のための共有ルール (cfn-lint 設定)

チーム全員のコード品質を統一するため、リポジトリのルートに `.cfnlintrc` を配置し、CI/CDパイプラインとローカルのチェック内容を完全に一致させろ。

.cfnlintrc
—
対象とするリージョン
regions:

  • ap-northeast-1

無視するルールID(必要に応じて)
exclude-checks:

  • W3001

厳格なチェックを有効化
update-plugins: []

—

2. 理論:なぜ通常のCFnアップデートは本番を殺すのか?

CloudFormationがリソースの「置き換え(Replace)」を判断した時、デフォルトの挙動は以下の順序で行われる。

1. 新しいリソースの作成 (Create) ※一部のリソース(物理名が一意なものなど)はこれが先に行えない場合がある
2. 古いリソースの削除 (Delete)

しかし、例えば `AWS::RDS::DBInstance` や `AWS::ElastiCache::ReplicationGroup` などの名前が一意に定まるリソースや、アタッチメントが絡むリソースでは、「先に古いリソースを削除しようとして依存関係エラーになる」か、あるいは「新規作成と削除の間に数秒の空白期間(ダウンタイム)が生じる」。

これを防ぐ設計思想が 「Create-Before-Delete(先行作成)」 と 「Retain(遅延削除)」 の組み合わせによるBlue/Green的アプローチだ。

—

3. 実践:`DeletionPolicy` と `DependsOn` による安全なリソース置き換え

今回は最も事故りやすい「セキュリティグループ(Security Group)」または「ステートフルなストレージ/DB」を例にとり、「新リソースを完全に立ち上げ、トラフィックや参照を切り替えてから、旧リソースを安全に消す(あるいは残す)」 パターンをコードで解説する。

実用テンプレート構成例(YAML)

以下のコードは、リソースの論理名をサフィックス(`V2` など)で変更しつつ、`DependsOn` と明示的な `DeletionPolicy: Retain` を駆使して安全な移行を行う実践的なテンプレート片だ。

AWSTemplateFormatVersion: ‘2010-09-09’
Description: “Zero-Downtime Resource Replacement Pattern using DeletionPolicy and DependsOn”

Parameters:
Environment:
Type: String
Default: production
AllowedValues: [staging, production]

Resources:
# ==========================================
# 【Phase 1】新リソースの先行作成 (New Resource)
# ==========================================
AppSecurityGroupV2:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: “Security Group for Application Servers – V2 (Zero-Downtime Migration)”
GroupName: !Sub “app-sg-${Environment}-v2”
VpcId: “vpc-xxxxxxxxxxxxxxxxx”
SecurityGroupIngress:

  • IpProtocol: tcp

FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Tags:

  • Key: Name

Value: !Sub “app-sg-${Environment}-v2”

# ==========================================
# 【Phase 2】旧リソースの制御と依存関係の逆転 (Old Resource)
# ==========================================
AppSecurityGroupV1:
Type: AWS::EC2::SecurityGroup
# 【重要】V2の作成が完全に完了してからこのリソースの削除フェーズに入るよう制御
DependsOn: AppSecurityGroupV2
# 【重要】万が一の事故を防ぐため、CloudFormationによる自動削除を防ぎ手動クリーンアップへ委ねる
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
GroupDescription: “Security Group for Application Servers – V1 (Legacy)”
GroupName: !Sub “app-sg-${Environment}-v1”
VpcId: “vpc-xxxxxxxxxxxxxxxxx”
SecurityGroupIngress:

  • IpProtocol: tcp

FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Tags:

  • Key: Name

Value: !Sub “app-sg-${Environment}-v1”

Outputs:
ActiveSecurityGroupId:
Description: “The Security Group ID to be referenced by downstream resources (e.g., EC2/ECS)”
Value: !GetAtt AppSecurityGroupV2.GroupId
Export:
Name: !Sub “${Environment}-ActiveSecurityGroupId”

—

4. この設計がもたらす本番環境での圧倒的なメリット

上記のコードには、SREの経験則に基づいたいくつもの「防壁」が組み込まれている。

1. `DeletionPolicy: Retain` と `UpdateReplacePolicy: Retain`

CloudFormationのスタック更新によって意図せず古いリソースが消滅するのを物理的に防ぐ。これにより、万が一マイグレーションスクリプトや参照先の切り替えに漏れがあったとしても、「古いリソースが裏で生き残っている」状態を担保できる。旧リソースの完全消去は、新システムが完全に安定稼働した数日後、手動(あるいは別タスク)で `aws ec2 delete-security-group` を叩けばよい。

2. `DependsOn` による順序の完全制御

通常、論理名が変わるとCloudFormationはパラレルに動こうとするか、古い方を先に壊しにかかるリスクがある。`DependsOn: AppSecurityGroupV2` を旧リソース側に明記することで、「新リソースの作成成功 > 旧リソースの切り離し・削除待機」 という厳密なステート遷移を強制できる。

3. 出力値(Outputs)とクロスズ・スタック参照の分離

下流のリソース(ECSサービスやALBなど)からは、リソース名義を直接参照するのではなく、OutputsのExport値を参照させる。これにより、基盤側のスキーマ変更(V1からV2への移行)が発生しても、下流のアプリケーションスタックへの影響を最小限に抑えることが可能になる。

—

5. テックリードからの最終提言

インフラストラクチャ・作為のコード化(IaC)において、コードの綺麗さと同じくらい重要なのは「失敗した時のフォールバックシナリオがコードに埋め込まれているか」だ。

「とりあえずデプロイして動いたから良し」とするアマチュアの仕事と、「リソースのライフサイクルと削除挙動を完全に支配し、ビジネスの無停止を守り抜く」プロフェッショナルなSREの仕事の差は、まさにこの `DeletionPolicy` と依存関係制御の理解度にある。

次のデプロイから、あなたのテンプレートにもこの「攻めと守りのパターン」を組み込んでほしい。チーム全体の信頼性が、劇的に向上することを私が約束しよう。

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