119. ドリフトは宣言と現実のずれである — 検出という照合作業とスタックポリシーという安全柵
CloudFormationのテンプレートに「こうあるべき」と書いた状態と、いま実際にAWS上にある状態がずれる問題を、検出の仕組みと防止の仕組みの両面から図で追っていきます。
① ドリフトとは「宣言」と「実体」のずれである
- 「Users can change those resources outside of CloudFormation... by using the underlying service that created the resource」
- 「a stack's actual configuration differs, or has drifted, from its expected configuration」
- 変更は事故のこともあれば、緊急対応で意図的なこともある。どちらでも、外側の変更はその後のスタック更新・削除を複雑にする。
ドリフトとは「テンプレートに書いた期待状態」と「いま実際にある状態」のずれのこと。CloudFormationの外側でリソースを直接変更すると発生し、後続のスタック操作を難しくする。
② 検出は「期待値」と「実測値」の照合である
- 「CloudFormation determines the expected resource property values, as defined in the stack template and any values specified as template parameters ... then compares those expected values with the actual values」
- 「A resource is considered to have drifted if any of its actual property values differ from the expected property values. This includes if the property or resource has been deleted.」
検出は「テンプレート+パラメータから求めた期待値」と「実在する実測値」のプロパティ単位の照合。可観測性編のアラームが期待の範囲と実測を比べたのと同じreconciliationを、設定値の世界でやっている。
③ ステータスはスタック→リソース→プロパティの3階層
- ADD=配列/リスト型のプロパティに値が追加された / REMOVE=プロパティが現在の構成から削除された / NOT_EQUAL=現在の値がテンプレート上の期待値と異なる(公式の定義)
- リソースのDELETED=リソースそのものが削除されている / MODIFIED=期待構成と異なる
- 「A stack is considered to have drifted if one or more of its resources have drifted.」
状態はプロパティ差分(ADD/REMOVE/NOT_EQUAL)→リソース(MODIFIED/DELETED/IN_SYNC/NOT_CHECKED)→スタック(DRIFTED/IN_SYNC/NOT_CHECKED)とボトムアップに集約される。下位のドリフトが上位へ伝播する。
④ 検出の盲点 — 「明示的に書いた」ものだけが照合される
- 「CloudFormation only determines drift for property values that are explicitly set ... This doesn't include default values ... explicitly set the property value, even if you are setting it to the default value.」
- 「When detecting drift on a stack, CloudFormation does not detect drift on any nested stacks ... you can initiate a drift detection operation directly on the nested stack.」
- 検出可能なスタック状態: CREATE_COMPLETE / UPDATE_COMPLETE / UPDATE_ROLLBACK_COMPLETE / UPDATE_ROLLBACK_FAILED
- スタックレベルのタグもドリフト判定の対象。
照合されるのは明示的に宣言したプロパティだけ。デフォルト任せのプロパティ・未サポートのリソース・ネストされた子スタックはドリフト判定されない。追跡したい値はデフォルトと同じでも明示的に書くのが対策。
⑤ スタックポリシー — 更新事故を防ぐJSONの安全柵
- Action 4種: Update:Modify=無停止/一部停止・物理ID維持 / Update:Replace=作り直しで物理IDが変わりうる / Update:Delete=削除 / Update:*=全更新操作
- 「When you create a stack, all update actions are allowed on all resources.」
- 「After you set a stack policy, all of the resources in the stack are protected by default. To allow updates on specific resources, you specify an explicit Allow statement」
- 「The Principal element is required, but supports only the wild card (*)」
- Condition は ResourceType を StringEquals / StringLike で指定(ワイルドカードを使うときは StringLike 必須)。
スタックポリシーはEffect/Action/Principal/Resource/Conditionの5要素からなるJSON。設定した瞬間に全リソースがデフォルト保護へ反転し、明示的なAllowがなければどんな更新も通らない。
⑥ Denyが常に勝つ — IAMと同じ競合解決、ただし更新中だけ
- 「a Deny statement always overrides an Allow statement. To ensure that a resource is protected, use a Deny statement」
- 「A stack policy applies only during stack updates. It doesn't provide access controls like an ... (IAM) policy. Use a stack policy only as a fail-safe mechanism ... To control access to AWS resources or actions, use IAM.」
- 本番DBを消したくなければIAMで権限を絞るのが本筋。スタックポリシーはその手前に置く「うっかり更新」へのフェイルセーフ。
AllowとDenyが重なればDenyが常に勝つ——認証暗号編のIAM評価と同じ競合解決規則が、適用範囲「更新中だけ」という違いを伴って再登場。本番DBのUpdate:Replaceだけを拒否すれば、置換によるデータ喪失を構造的に防げる。
⑦ 一時的上書きと、消せないポリシー
- 「create a temporary policy that overrides the stack policy ... The override policy doesn't permanently change the stack policy.」
- 「CloudFormation applies the override policy only during this update.」
- 「You can't delete a stack policy. To remove all protection from all resources, you modify the policy to explicitly allow all actions on all resources.」
- CLI: 恒久設定は set-stack-policy、更新1回だけの上書きは update-stack の --stack-policy-during-update-body / -url。
保護されたリソースを更新したいときは、その1回だけ有効な上書きポリシーを渡す——恒久設定は変わらない。そしてスタックポリシーは削除できず、保護を外すには全許可ポリシーへ書き換えるしかない。