Route53に登録したレコードを異なるAWSアカウントに移譲してみる

2021.10.11

概要

あるAWSアカウント(以降、移行元)のRoute53で管理していたドメインを、異なるAWSアカウント(以降、移行先)に移譲することになりました。
本エントリーでは、そのシチュエーションを想定して試したみた内容を記載します。

「別の AWS アカウントへのホストゾーンの移行」が大いに参考になりました。

目次

1.はじめに

シチュエーションの詳細について記載します。

現状

移行元アカウントのRoute53で「{my-domain}」ホストゾーンを管理している。
{my-domain}は全社単位で利用しているドメインであり、以下のように機能やアプリケーションごとにレコードを分けて利用している。

  • api.{appA}.{my-domain}
  • iot.{appA}.{my-domain}
  • api.{appB}.{my-domain}
  • iot.{appB}.{my-domain}

このレコードのうち、「appA」で利用しているレコードのみを移行先アカウントで管理することとなった。
つまり、本作業完了後は移行元、移行先アカウントのRoute53で以下のようにドメインを管理する。

移行元

ホストゾーン レコード
{my-domain} api.{appA}.{my-domain}
{my-domain} iot.{appA}.{my-domain}
{my-domain} api.{appB}.{my-domain}
{my-domain} iot.{appB}.{my-domain}

↓作業実施後

ホストゾーン レコード 備考
{my-domain} api.{appB}.{my-domain}
{my-domain} iot.{appB}.{my-domain}
{my-domain} {appA}.{my-domain} 移行先アカウントに権限移譲するために必要

移行先

何も登録されていない(新規アカウント)

↓作業実施後

ホストゾーン レコード
{appA}.{my-domain} api.{appA}.{my-domain}
{appA}.{my-domain} iot.{appA}.{my-domain}

なお、ここまでは説明をシンプルにするためのURL構成でしたが、以降の手順で登場するURLは以下の通りです。
(今まで{appA}と表現していた箇所が「my-service」になっています)

  • api.my-service.{my-domain}
  • iot.my-service.{my-domain}

また、以降の手順ではACM証明書のレコードも登場します。

2.事前確認

まずは作業開始前の状況を確認します。
移行元アカウントのホストゾーンには以下のようにレコードが登録されています。
ACM証明書のためのレコードも登録されていますが、このレコードもまとめて移行します。

「api.my-service.{my-domain}」はAPIGatewayのカスタムドメインに、「iot.my-service.{my-domain}」は「IoT Core」のデバイスデータエンドポイントを参照しています。
digコマンドで名前解決ができていることを事前に確認しておきます。

# 名前解決できていることを確認
$ dig api.my-service.{my-domain}

# 以下のような結果が取得できる
;; ANSWER SECTION:
api.my-service.{my-domain}. 60 IN A     13.113.185.19
api.my-service.{my-domain}. 60 IN A     54.250.212.68
api.my-service.{my-domain}. 60 IN A     54.65.241.117

また、移行先アカウントのRoute53にはまだ何も登録されていない状態です。

3.やってみた

3-1.移行先アカウントにホストゾーンを登録

移行先アカウントのRoute53にて、以下の通り今回のアプリケーションで採用するドメインをホストゾーンとして登録します。
この時点では、既存の「api.my-service.{my-domain}」、「iot.my-service.{my-domain}」に影響はないです。
(「2.事前確認」と同様にdigコマンドを実行すれば、影響を受けていないことが確認できます)

3-2.移行元レコードの情報を取得

移行元レコードの情報を取得します。
レコード量が少ないのでAWSコンソール画面上から確認してもいいのですが、量が多い場合は以下のようなコマンドでまとめて取得し、移行が必要なレコードのみに絞り込みましょう。

$ aws route53 list-resource-record-sets --hosted-zone-id ZXXXXXXXXXXXXXX | jq -r -s '.[].ResourceRecordSets[] | select (.Name | endswith("my-service.{my-domain}."))' > yoshim_delegate_domain.json

以下のようなjsonファイルが取得できます。

{
  "Name": "api.my-service.{my-domain}.",
  "Type": "A",
  "AliasTarget": {
    "HostedZoneId": "ZXXXXXXXX",
    "DNSName": "APIGatewayのカスタムドメインのエンドポイント設定の「APIGatewayドメイン名」",
    "EvaluateTargetHealth": true
  }
}
{
  "Name": "_XXXXXXXXXXXXXXXX.api.my-service.{my-domain}.",
  "Type": "CNAME",
  "TTL": 60,
  "ResourceRecords": [
    {
      "Value": "_XXXXXXXXXXXXXXXX.XXXXXXX.acm-validations.aws."
    }
  ]
}
{
  "Name": "iot.my-service.{my-domain}.",
  "Type": "CNAME",
  "TTL": 60,
  "ResourceRecords": [
    {
      "Value": "IoTCoreのデバイスデータエンドポイント"
    }
  ]
}
{
  "Name": "_XXXXXXXXXXXXXXXX.iot.my-service.{my-domain}.",
  "Type": "CNAME",
  "TTL": 60,
  "ResourceRecords": [
    {
      "Value": "_XXXXXXXXXXXXXXXX.XXXXXXX.acm-validations.aws."
    }
  ]
}

3-3.レコード情報のフォーマットを編集

先ほど取得したレコード情報のフォーマットを変更します。

{
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "api.my-service.{my-domain}.",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "ZXXXXXXXX",
          "DNSName": "APIGatewayのカスタムドメインのエンドポイント設定の「APIGatewayドメイン名」",
          "EvaluateTargetHealth": true
        }
      }
    },
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "_XXXXXXXXXXXXXXXX.api.my-service.{my-domain}.",
        "Type": "CNAME",
        "TTL": 60,
        "ResourceRecords": [
          {
            "Value": "_XXXXXXXXXXXXXXXX.XXXXXXX.acm-validations.aws."
          }
        ]
      }
    },
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "iot.my-service.{my-domain}.",
        "Type": "CNAME",
        "TTL": 60,
        "ResourceRecords": [
          {
            "Value": "IoTCoreのデバイスデータエンドポイント"
          }
        ]
      }
    },
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "_XXXXXXXXXXXXXXXX.iot.my-service.{my-domain}.",
        "Type": "CNAME",
        "TTL": 60,
        "ResourceRecords": [
          {
            "Value": "_XXXXXXXXXXXXXXXX.XXXXXXX.acm-validations.aws."
          }
        ]
      }
    }
  ]
}

以下が参考になります。

3-4.移行先アカウントにレコードを作成する

フォーマット修正後、移行先アカウントのホストゾーンにレコードを登録します。

$ aws route53 change-resource-record-sets --hosted-zone-id ZXXXXXXX --change-batch file://yoshim_delegate_domain.json

無事登録できていることが確認できます。

本処理が完了しても、まだこのレコードに基づいて名前解決がされているわけではなく、「api.my-service.{my-domain}」、「iot.my-service.{my-domain}」には影響は出ていません。

3-5.「my-service.{my-domain}」の権限を移行先アカウントに移譲

移行先アカウントのRoute53にて、「my-service.{my-domain}」ホストゾーンのネームサーバーを確認します。

続いて、移行元アカウントのRoute53にて、「{my-domain}」ホストゾーンに「my-service.{my-domain}」のNSレコードを作成します。
(「値」に「my-service.{my-domain}」ホストゾーンのネームサーバーを登録)

これで移行先アカウントでドメインが管理できている状態になります。
ただし、反映に少し時間がかかるので、少し待ってから疎通確認をします。

Amazon Route 53 は、通常の条件では 60 秒以内に DNS レコードへのアップデートを全世界の権威 DNS サーバーのネットワークに反映するよう設計されています。

参照: Amazon Route 53 のよくある質問

3-6.疎通確認

「2.事前確認」と同様にdigコマンドを実行し、疎通できていることを確認しました。

$ dig api.my-service.{my-domain}

# 以下のような結果が取得できる
;; ANSWER SECTION:
api.my-service.{my-domain}. 60 IN A     13.113.185.19
api.my-service.{my-domain}. 60 IN A     54.250.212.68
api.my-service.{my-domain}. 60 IN A     54.65.241.117

3-7.古いレコードの削除

移行元アカウントのRoute53に残っているレコードを削除します。

削除後、削除間違いがないことを確認するために十分に時間をおいた後、「2.事前確認」と同様にdigコマンドを実行し、疎通できていることを確認しました。

4.まとめ

以上で確認を終わります。
本手順の通りにやることで、ダウンタイムなしで既存ドメインを移行できます。
ただ、作業ミスが発生した場合の影響が怖いので、やはり事前に関係者と調整をしておくことが重要です。
長くなりましたが、ご覧いただきありがとうございました。

参照