CloudFormation のスタック更新で何が起きているのか - 変更セット・ロールバック・置換の裏側

CloudFormation がスタックを更新する際の内部処理フローを、変更セットの差分検出、リソースの更新・置換・削除の判断ロジック、ロールバックの仕組みから解説します。

テンプレートの差分検出 - 何が変わったかをどう判定するのか

CloudFormation にスタック更新を指示すると、最初に行われるのは現在のテンプレートと新しいテンプレートの差分検出です。CloudFormation は各リソースの論理 ID (テンプレート内の名前) をキーとして、プロパティの変更を検出します。ここで重要なのは、CloudFormation が比較するのは「テンプレートに記述されたプロパティ」であり、「実際のリソースの現在の状態」ではないという点です。つまり、AWS コンソールや CLI で手動変更したプロパティは、CloudFormation のテンプレートに反映されていなければ差分として検出されません。この「ドリフト」(テンプレートと実際の状態の乖離) は、CloudFormation 運用で最も厄介な問題の一つです。ドリフト検出機能を使えば乖離を検出できますが、自動修復はされません。変更セット (Change Set) は、実際に更新を実行する前に、どのリソースがどう変更されるかをプレビューする機能です。変更セットを作成すると、CloudFormation は差分を分析し、各リソースに対して「追加」「変更」「削除」のいずれかのアクションを表示します。

更新・置換・削除 - リソースごとに異なる更新動作

CloudFormation のリソース更新には 3 つのパターンがあります。「中断なしの更新」(Update with No Interruption) は、リソースを停止せずにプロパティを変更します。たとえば、Lambda 関数の環境変数の変更や、S3 バケットのタグの追加はこのパターンです。「一時的な中断を伴う更新」(Update with Some Interruption) は、リソースが一時的に利用不能になります。EC2 インスタンスのインスタンスタイプの変更は、インスタンスの停止と再起動を伴います。「置換」(Replacement) は、既存のリソースを削除して新しいリソースを作成します。RDS インスタンスのエンジンバージョンの変更や、DynamoDB テーブルのパーティションキーの変更は置換になります。置換が最も危険なパターンです。データを持つリソース (RDS、DynamoDB) が置換されると、データが失われる可能性があります。CloudFormation のドキュメントには、各リソースタイプの各プロパティについて、変更時の動作 (中断なし / 一時中断 / 置換) が記載されています。スタック更新前に必ず確認すべき情報です。

依存関係の解決と更新順序

CloudFormation はテンプレート内のリソース間の依存関係を自動的に解析し、正しい順序で更新を実行します。依存関係は、Ref 関数、Fn::GetAtt 関数、DependsOn 属性から推定されます。たとえば、Lambda 関数が IAM ロールを参照している場合、IAM ロールが先に更新され、その後に Lambda 関数が更新されます。CloudFormation は可能な限り並列に更新を実行します。依存関係のないリソースは同時に更新され、更新時間が短縮されます。ただし、並列更新にはリスクもあります。セキュリティグループと EC2 インスタンスを同時に更新した場合、一時的にセキュリティグループのルールが不整合な状態になる可能性があります。循環依存 (リソース A がリソース B を参照し、リソース B がリソース A を参照する) は、CloudFormation がテンプレートの検証段階でエラーとして検出します。循環依存を解消するには、一方の参照を DependsOn に変更するか、リソースの設計を見直す必要があります。

ロールバックの仕組み - 失敗したらどこまで戻るのか

スタック更新中にリソースの作成や変更が失敗すると、CloudFormation は自動的にロールバックを開始します。ロールバックは、更新前の状態にすべてのリソースを戻す処理です。ただし、ロールバックは完全ではありません。「置換」で作成された新しいリソースは削除されますが、「置換」で削除された古いリソースは復元できません。DeletionPolicy を Retain に設定していれば、置換時に古いリソースが保持されるため、ロールバック後に手動で復旧できます。ロールバック自体が失敗するケースもあります。たとえば、更新中に手動でリソースを変更した場合や、ロールバック先の状態が現在のサービス制限に抵触する場合です。ロールバックが失敗すると、スタックは UPDATE_ROLLBACK_FAILED 状態になり、手動での介入が必要になります。ContinueUpdateRollback API を使用して、問題のあるリソースをスキップしてロールバックを続行できますが、スキップされたリソースは CloudFormation の管理外になります。この状態は運用上非常に厄介で、スタックの再作成が最善の解決策になることもあります。

スタック更新を安全に行うための実践的な対策

CloudFormation のスタック更新で事故を防ぐための対策は 4 つあります。第 1 に、変更セットの必ず確認です。直接更新 (UpdateStack) ではなく、変更セットを作成してプレビューし、意図しない置換や削除がないことを確認してから実行します。第 2 に、スタックポリシーの設定です。スタックポリシーは、特定のリソースの更新を禁止または制限するポリシーです。本番環境の RDS インスタンスや DynamoDB テーブルにスタックポリシーを設定し、置換や削除を禁止すれば、テンプレートのミスによるデータ損失を防げます。第 3 に、DeletionPolicy の設定です。重要なリソースに DeletionPolicy: Retain を設定すれば、スタックの削除やリソースの置換時にリソースが保持されます。第 4 に、ターミネーション保護の有効化です。スタック自体の誤削除を防ぐために、本番環境のスタックにはターミネーション保護を有効にします。これらの対策を組み合わせることで、CloudFormation の更新事故のリスクを大幅に低減できます。IaC の設計と運用を体系的に学ぶには、専門書籍 (Amazon)が参考になります。