はじめに

CloudFront ディストリビューションを移行する機会がありましたので、実際に対応した手順と注意点を紹介します。以下を前提とします。

  • DNS は Route 53
  • 同一アカウント内での移行
  • ユーザーからのアクセスはメンテナンスページに向いている状態

概要

方針として、CloudFront の変更と Route 53 の変更はなるべく同じタイミングでコマンドラインで実行し、不整合が発生しないようにします。

CloudFront

  • CloudFront の CNAME を新旧ディストリビューションで付け替える
  • CloudFront の CNAME は重複を許さないため、AssociateAlias API を使ってアトミックに付け替える (参考)

Route 53

  • A レコード (エイリアスレコード) の向き先を変更する

リソースの状態

作業前の CloudFront ディストリビューションの状態です。

CNAME 証明書 備考
移行元 test.example.com あり Route 53 の A レコードはこちらを向いている
移行先 なし あり

ちなみに移行先に CNAME が設定されていない場合でも証明書は必須です。ない場合は AssociateAlias API 実行時に以下エラーが発生します。

An error occurred (InvalidArgument) when calling the AssociateAlias operation: To add an alternate domain name (CNAME) to a CloudFront distribution, you must attach a trusted certificate that validates your authorization to use the domain name. For more details, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-requirements

TXT レコードの登録

AssociateAlias API を使う場合は、ドメインの所有権を検証するため事前に DNS に TXT レコードを仕込んでおく必要があります。TXT レコードにはドメインの先頭にアンダースコアを付けた値を設定します。Zone Apex の場合はプレフィックスとして _. がつくことになります。Value は移行先ディストリビューションのドメイン名です。

Record name Type Value
_.test.example.com TXT xxxxxxxxxxxxx.cloudfront.net

今回は test.example.com というパブリックホストゾーンで、Zone Apex である test.example.com の A レコード (エイリアスレコード) が移行元ディストリビューションに対して設定されています。上記の TXT レコードはその前提で設定しています。

これは一見正しいですが、実は失敗しました。のちほど説明します。

移行コマンド

CloudFront ディストリビューションの CNAME 付け替えと DNS レコードの向き先変更を続けて実行したいため、以下のように && で繋いで実行します。

aws cloudfront associate-alias --alias "test.example.com" --target-distribution-id "<新規作成したディストリビューションの ID>" &&
  aws route53 change-resource-record-sets --hosted-zone-id "xxxxxxxxxxxxxxxxxxxx" --change-batch '{
  "Comment": "Change of Domain Direction",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "test.example.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z2FDTNDATAQYW2",
          "DNSName": "<新規作成したディストリビューションのドメイン名 (xxxxxxxxxxxxxx.cloudfront.net)>",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}'

結果

コマンドを実行すると、以下のエラーが発生してしまいました。TXT レコードの検証に失敗しています。なぜでしょうか。

An error occurred (IllegalUpdate) when calling the AssociateAlias operation: Invalid or missing alias DNS TXT records.

トラブルシューティング

このエラーの原因ですが、TXT レコードの値として _test.example.com を期待していたところ、実際は _.test.example.com であったことが原因ではないかと推測しました。

test.example.com ホストゾーンは example.com ホストゾーンから DNS を委任されています。具体的には以下のようなケースです。

  • example.com という Route 53 パブリックホストゾーンがある
  • test.example.com という Route 53 パブリックホストゾーンがある
  • example.com は test.example.com の NS レコードを持っている

今回 test.example.com のホストゾーンに以下のように TXT レコードを書きましたが、これがうまくいきませんでした。

Public hosted zone Record name Type Value
test.example.com _.test.example.com TXT xxxxxxxxxxxxx.cloudfront.net

解決策として、委任元である example.com のホストゾーンで以下のように書く必要がありました。

Public hosted zone Record name Type Value
example.com _test.example.com TXT xxxxxxxxxxxxx.cloudfront.net

この変更後、移行コマンドを再度実行することでうまく移行できました。

おわりに

いちばん言いたかったのはトラブルシューティングのところです。検証で再現しているので、このケースの対策として間違ってはいないはずです。が、私は DNS にさほど詳しくないので、不備などがあれば教えていただけると幸いです。

また本件のような作業については、ユーザーに対してはメンテナンスページを表示しておくなど、通常のメンテナンス状況下で実施することを強く推奨します。