Route 53 AliasレコードとCNAMEレコードの違い — ALBへのドメイン接続で迷ったときの判断基準

ALBをデプロイしてドメインを向けようとしたとき、多くのエンジニアが最初にCNAMEレコードを設定しようとする。しかしexample.comのようなゾーンの頂点(Zone Apex)でCNAMEを設定しようとすると、Route 53のコンソールがそれを拒否する。これはDNS仕様の制約であり、Route 53のAliasレコードがその解決策として設計されている。

TL;DR — AliasとCNAMEの比較

比較軸CNAMEレコードRoute 53 Aliasレコード
ゾーンの頂点(example.com)での使用❌ 不可(RFC 1034制約)✅ 可能
DNSクエリ料金通常のクエリ料金が発生Route 53リソースへのクエリは無料
TTL制御任意に設定可能Route 53が自動管理(設定不可)
ヘルスチェック統合制限ありターゲットリソースのヘルスチェックと統合可能
IPアドレスの自動追従不可(CNAMEが指すホスト名のAレコードに依存)ALBのIPが変わっても自動的に追従
対応ターゲット任意のホスト名ALB、CloudFront、S3、API Gatewayなど特定AWSリソース

Route 53 AliasレコードとCNAMEレコードの仕組み

CNAMEレコードはDNSの標準機能で、あるホスト名を別のホスト名に対応付ける。クライアントがCNAMEを解決するとき、DNSリゾルバーは最終的なAレコード(IPアドレス)に到達するまで複数回のクエリを実行する。この仕組み自体は問題ないが、RFC 1034の規定により、ゾーンの頂点(ネイキッドドメイン)にはCNAMEを設定できない。ゾーンの頂点にはSOAレコードとNSレコードが必ず存在しなければならず、CNAMEは他のレコードと共存できないためだ。

Route 53のAliasレコードはAWSが独自に実装したDNS拡張機能で、外部から見るとAレコード(またはAAAAレコード)として振る舞う。Route 53の権威DNSサーバーがAliasを解決するとき、ターゲットリソース(ALBなど)の現在のIPアドレスを直接返す。クライアント側には追加のCNAMEホップが発生しない。

CNAMEを使ったALB接続は、転送先の住所を書いた紙を渡すようなもの。Aliasは転送先の住所を直接書いた封筒に相当する。ゾーンの頂点では、封筒に住所を直接書かなければならない。
graph TD Client["クライアント"] subgraph CNAME_Flow ["CNAMEフロー(www.example.com)"] R53C["Route 53 CNAMEレコード返却"] Resolver["リゾルバー ALB DNS名を再解決"] ALB_IP1["ALBのIPアドレス"] end subgraph Alias_Flow ["Aliasフロー(example.com)"] R53A["Route 53 ALB IPを内部解決"] ALB_IP2["ALBのIPアドレス"] end subgraph Blocked ["ゾーン頂点CNAME(不可)"] Error["❌ RFC 1034制約 設定自体が拒否される"] end Client -->|"www.example.com 問い合わせ"| R53C R53C -->|"CNAMEレコード返却"| Resolver Resolver -->|"ALB DNS名解決"| ALB_IP1 Client -->|"example.com 問い合わせ"| R53A R53A -->|"Aレコードとして返却"| ALB_IP2 Client -->|"example.com CNAME試行"| Error
  1. CNAMEフロー(サブドメイン): クライアントがwww.example.comを問い合わせると、Route 53はCNAMEレコードを返し、リゾルバーがALBのDNS名を再度解決してIPを取得する。2段階のクエリが発生する。
  2. Aliasフロー(ゾーンの頂点): クライアントがexample.comを問い合わせると、Route 53がAliasを内部解決してALBの現在のIPを直接返す。クライアントから見ると単純なAレコード応答に見える。
  3. ゾーン頂点でのCNAME: RFC 1034の制約により設定自体が拒否される。Route 53コンソールでもCLIでもエラーになる。

なぜゾーンの頂点でAliasレコードが必要なのか

ALBにはEIPを割り当てられない。ALBのIPアドレスはAWSが管理し、スケーリングやメンテナンスに伴って変化する。そのため、ALBへの接続は必ずDNS名(my-alb-1234567890.us-east-1.elb.amazonaws.comのような形式)を経由しなければならない。

サブドメイン(www.example.com)であればCNAMEでALBのDNS名を指定できる。しかしexample.comそのものにはCNAMEを設定できないため、Aliasレコードが唯一の実用的な選択肢になる。

Aliasレコードのもう一つの実用的な利点は料金だ。Route 53のAliasレコードがAWS管理リソース(ALB、CloudFront、S3 Webサイトエンドポイントなど)を指す場合、そのDNSクエリに対してRoute 53のクエリ料金は発生しない。高トラフィックのドメインでは無視できないコスト差になる。料金の詳細は常にRoute 53公式料金ページで確認すること。

ALBへのAliasレコード設定手順

以下の手順でRoute 53 HostedゾーンにAliasレコードを作成する。事前にALBのDNS名とHosted Zone IDが必要になる。

Step 1: ALBの情報を取得する

AliasレコードにはALBのDNS名と、ALBが属するRoute 53 Hosted Zone IDの両方が必要だ。ALBのDNS名は単なるホスト名だが、Hosted Zone IDはリージョンごとに異なるAWS管理の値で、自分のアカウントのHosted Zone IDとは別物であることに注意する。

# ALBのDNS名とHosted Zone IDを取得
aws elbv2 describe-load-balancers \
  --names your-alb-name \
  --query 'LoadBalancers[0].{DNSName:DNSName,CanonicalHostedZoneId:CanonicalHostedZoneId}' \
  --output json \
  --region us-east-1

出力例:

{
  "DNSName": "my-alb-1234567890.us-east-1.elb.amazonaws.com",
  "CanonicalHostedZoneId": "Z35SXDOTRQ7X7K"
}

CanonicalHostedZoneIdがALBのHosted Zone IDだ。これはリージョンとロードバランサータイプによって決まるAWS管理の値で、自分のRoute 53 Hosted Zone IDとは異なる。

Step 2: 自分のHosted Zone IDを確認する

Route 53で管理しているドメインのHosted Zone IDを取得する。

aws route53 list-hosted-zones-by-name \
  --dns-name example.com \
  --query 'HostedZones[0].Id' \
  --output text

Step 3: Aliasレコードを作成するためのJSONを準備する

以下のJSONファイル(alias-record.json)を作成する。HostedZoneId(AliasTarget内)にはStep 1で取得したALBのCanonicalHostedZoneIdを使用する。

🔽 alias-record.json(クリックして展開)
{
  "Comment": "Create Alias record for zone apex pointing to ALB",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "example.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "DNSName": "my-alb-1234567890.us-east-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    }
  ]
}

Step 4: レコードを適用する

EvaluateTargetHealth: trueを設定しておくと、ALBのヘルスチェックが失敗した場合にRoute 53がそのエンドポイントへのルーティングを停止できる。フェイルオーバールーティングポリシーと組み合わせると特に有効だ。

aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABCDEF \
  --change-batch file://alias-record.json

Step 5: 伝播を確認する

# 権威DNSサーバーに直接問い合わせて確認
dig example.com A +short

# Route 53の変更ステータスを確認
aws route53 get-change \
  --id /change/CHANGEID_FROM_PREVIOUS_OUTPUT \
  --query 'ChangeInfo.Status' \
  --output text

よくある誤診断 — CNAMEで設定できると思っていた

本番環境でよく見るパターンがある。www.example.comはCNAMEでALBに向けていて正常動作している。次にexample.comも同じようにCNAMEで設定しようとしてRoute 53コンソールがエラーを返す。エラーメッセージを見て「Route 53のバグか権限の問題」と判断してIAMポリシーを調べ始める。

実際の原因はDNS仕様の制約だ。Route 53はRFC 1034に準拠しており、ゾーンの頂点へのCNAME設定を意図的に拒否している。IAMとは無関係で、Aliasレコードに切り替えることが唯一の解決策になる。

もう一つの落とし穴は、Aliasレコードを作成するときにAliasTarget.HostedZoneIdに自分のHosted Zone IDを誤って入力するケースだ。ここにはALBのCanonicalHostedZoneIdを入れなければならない。自分のHosted Zone IDを入れるとレコードは作成されるが、DNSが正しく解決されない。

graph LR S["症状 ゾーン頂点でCNAME設定エラー"] M["誤診断 IAM権限不足と判断"] C["実際の原因 RFC 1034 DNS仕様制約"] F["正しい対処 Aliasレコード(タイプA)に切り替え"] S --> M M -->|"IAM調査しても解決しない"| C C --> F
  1. 症状: ゾーン頂点でCNAME設定を試みるとRoute 53がエラーを返す。
  2. 誤診断: IAM権限不足またはRoute 53コンソールのバグと判断してしまう。
  3. 実際の原因: RFC 1034によるDNS仕様の制約。ゾーン頂点にはCNAMEを設定できない。
  4. 正しい対処: AliasレコードタイプAでALBのDNS名とCanonicalHostedZoneIdを指定する。

Aliasレコードが使えるAWSリソース

Aliasレコードはすべてのホスト名を指定できるわけではない。Route 53がサポートするターゲットは以下のAWSリソースに限定される。

  • Application Load Balancer / Network Load Balancer / Classic Load Balancer
  • Amazon CloudFront ディストリビューション
  • AWS Elastic Beanstalk 環境
  • Amazon S3 静的ウェブサイトエンドポイント(バケットウェブサイトエンドポイント形式のみ)
  • Amazon API Gateway カスタムドメイン
  • 同一Hosted Zone内の別のRoute 53レコード
  • AWS Global Accelerator アクセラレーター
  • Amazon VPC インターフェースエンドポイント

任意の外部ホスト名(他社CDNなど)を指定したい場合はCNAMEを使う必要がある。その場合はゾーンの頂点では使えないため、wwwサブドメインを主ドメインとして扱うか、別の回避策を検討することになる。

必要なIAM権限

Route 53のレコード操作に必要な最小権限は以下の通り。読み取り操作(ListHostedZonesGetChangeなど)はリソースレベルの制限が難しいためResource: "*"が必要になるケースがある。Service Authorization Referenceで各アクションのリソースレベルサポートを確認すること。

🔽 IAMポリシー例(クリックして展開)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets"
      ],
      "Resource": "arn:aws:route53:::hostedzone/Z1234567890ABCDEF"
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ListHostedZones",
        "route53:ListHostedZonesByName",
        "route53:GetChange",
        "route53:ListResourceRecordSets"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:DescribeLoadBalancers"
      ],
      "Resource": "*"
    }
  ]
}

まとめとNext Steps — Route 53 Aliasレコードの選択基準

Route 53 AliasレコードとCNAMEレコードの選択は単純だ。ALBやCloudFrontなどのAWSリソースを指す場合は常にAliasレコードを使う。ゾーンの頂点では選択の余地がなくAliasレコード一択になる。サブドメインであってもAWSリソースを指すならAliasレコードの方がクエリ料金とヘルスチェック統合の面で有利だ。

外部の任意ホスト名(AWSリソース以外)を指定する必要がある場合のみCNAMEを使う。その場合はゾーンの頂点では設定できないことを前提に設計する。

用語集

用語説明
Zone Apex(ゾーンの頂点)DNSゾーンのルートドメイン(例: example.com)。サブドメインを含まない裸のドメイン名。ネイキッドドメインとも呼ばれる。
AliasレコードRoute 53固有のDNS拡張機能。外部からはAレコードとして見えるが、内部でAWSリソースのDNS名を解決する。
CanonicalHostedZoneIdALBなどのAWSリソースに割り当てられたRoute 53 Hosted Zone ID。リージョンとロードバランサータイプで決まるAWS管理の値。
EvaluateTargetHealthAliasレコードのオプションでALBなどターゲットリソースのヘルスチェック結果をDNSルーティングに反映させる設定。
RFC 1034DNSの基本仕様を定めたRFC。ゾーンの頂点にCNAMEを設定できない制約の根拠となる標準。

コメント

このブログの人気の投稿

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み

EC2インスタンスIDをメタデータから取得する方法 — IMDSv2が安全な理由