CloudFormationスタックがACM証明書のDNS検証待ちで12時間後に失敗した

  • AWS
  • CloudFormation
  • ACM

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

起きたこと

CloudFormationスタックの中でRoute 53のHosted ZoneとACM証明書(DNS検証)を同じテンプレートで作ってた。ドメインの管理は先方が行っているので、Hosted Zone作成後に発行されるNSレコードを先方に設定してもらう必要がある。当然その間、証明書のDNS検証は終わらないし、スタックはCREATE_IN_PROGRESSのまま止まる。

放置してたら、約12時間後にスタックがCREATE_FAILEDになってロールバックされた。原因を調べた。

原因: ACM証明書のDNS検証待ちが約12時間で切れる

サービスロールを指定せずにACM証明書(DNS検証)をCloudFormationで作成し、CNAMEレコードを追加しないまま放置すると、約12時間後にスタックがCREATE_FAILEDになり、ROLLBACK_COMPLETEまで進むという検証結果がある。GitHub上でも同様の報告があって、ACM証明書リソース固有の待機挙動として12時間程度で切れるらしい。

紛らわしいのは、ACM側(Certificate Managerの機能として)の検証待ちタイムアウトは72時間と公式に明記されていること。つまり「ACMの検証自体は72時間待てるけど、CloudFormationのスタック操作としては先に12時間で見切りをつけられる」という二段構えになってる。実機で計測したわけではないので、そこは未確認。

これが今回のスタック失敗の直接原因。

ロールバックでHosted Zoneが消える

スタックがロールバックすると、そのスタック操作中に作成されたリソースは基本削除される。DeletionPolicyを指定していなければHosted Zoneも対象。

Hosted Zoneが消えて再作成されると、NSレコードは新規発行される。つまり最初にNS情報を渡した先方に、また新しいNS情報を渡し直す必要が出てくる。地味に面倒。

flowchart TD
    A[スタック作成開始] --> B[Hosted Zone作成]
    B --> C[NSレコード発行]
    C --> D[先方にNS情報を連携]
    D --> E[ACM証明書 DNS検証待ち]
    E -->|CNAME未設定のまま約12時間経過| F[スタック CREATE_FAILED]
    F --> G[ロールバック開始]
    G --> H[Hosted Zone削除 DeletionPolicy未指定の場合]
    H --> I[再作成時にNSレコードが変わる]

参考: AWS::CloudFormation::WaitConditionのタイムアウトとは別物

今回の12時間と紛らわしいのがAWS::CloudFormation::WaitConditionのタイムアウト。こっちはWaitConditionやCreationPolicyのTimeoutプロパティに指定できる最大値が43200秒(12時間)という、明示的にユーザーが設定する値の話。

MyWaitCondition:
Type: AWS::CloudFormation::WaitCondition
Properties:
Handle: !Ref MyWaitHandle
Timeout: '43200' # 指定できる最大値(秒)

EC2やAuto Scalingのリソースがシグナルを送るまで待つ用途で使うもので、今回のACM証明書のDNS検証待ちとは仕組みが別。たまたま同じ「12時間」という数字が出てくるので混同しやすいけど、WaitConditionを明示的に置いていなくても、ACM証明書のDNS検証待ちだけで同じく約12時間後に失敗する。

対策

思いつく範囲で3つ。

  • Hosted Zoneの作成を別スタックに分離する。ACM証明書やその他リソースの失敗がHosted Zoneに波及しないようにする
  • ACM証明書リソースにDeletionPolicy: Retainを付ける。ロールバック時にHosted Zoneだけ削除対象から外せる。ただし孤立したHosted Zoneの後始末は手動で必要になる
  • スタック作成時にDisableRollbackを有効にする。失敗してもリソースは残るので、NS設定完了後に手動でスタック操作を再開できる。ただし失敗状態のスタックがそのまま残るので運用が面倒になる

今回はHosted Zoneだけ先に別スタックで作って、先方にNS情報を渡してから、後続でACM証明書やそれ以外のリソースを別スタックで作る構成にした。ACM証明書の検証待ちで何かあっても、Hosted ZoneのNSは変わらない。