Route 53 Alias vs CNAME: Khi Nào Dùng Alias Record Cho Zone Apex?
Bạn vừa tạo xong một Application Load Balancer và cần trỏ domain về đó — nhưng Route 53 hiện ra hai lựa chọn: CNAME và Alias. Nếu domain là example.com (zone apex), CNAME sẽ không hoạt động theo đúng nghĩa bạn mong đợi, và đây là lý do nhiều kỹ sư mất thời gian debug một vấn đề tưởng như đơn giản.
TL;DR — Route 53 Alias vs CNAME
| Tiêu chí | CNAME | Alias Record |
|---|---|---|
Dùng được ở zone apex (example.com) | ❌ Không | ✅ Có |
| Phí DNS query | Tính phí | Miễn phí (với AWS targets) |
| Trả về IP hay hostname | Hostname | IP trực tiếp (resolved nội bộ) |
| Tích hợp health check Route 53 | Hạn chế | Tích hợp native |
| TTL do người dùng kiểm soát | ✅ Có | ❌ AWS quản lý |
| Targets hỗ trợ | Bất kỳ hostname nào | Chỉ AWS resources được liệt kê |
Cơ Chế Hoạt Động: Route 53 Alias Record Là Gì?
Alias record là một extension độc quyền của Route 53, không phải một loại DNS record chuẩn trong RFC. Về mặt kỹ thuật, nó hoạt động như một CNAME nội bộ được Route 53 resolve trước khi trả lời client — nhưng khác CNAME ở chỗ nó trả về địa chỉ IP cuối cùng, không phải hostname trung gian.
Khi một client query example.com trỏ đến ALB qua Alias, Route 53 tự resolve hostname của ALB thành danh sách IP và trả thẳng A record về cho client. Client không bao giờ thấy hostname của ALB. Điều này giải quyết đúng vấn đề của zone apex: RFC 1034 cấm CNAME tồn tại cùng SOA/NS record tại root của zone, nhưng Alias không phải CNAME theo nghĩa DNS chuẩn nên không vi phạm ràng buộc này.
(DNS lookup)"] IP["IP Address"] subgraph CNAME_FLOW ["CNAME Flow — 2 round-trips"] C1(["Client"]) -->|"query example.com"| C2["Route 53"] C2 -->|"CNAME: alb.amazonaws.com"| C3(["Client"]) C3 -->|"query alb.amazonaws.com"| C4["Resolver"] C4 -->|"A: 1.2.3.4"| C3 end subgraph ALIAS_FLOW ["Alias Flow — 1 round-trip"] A1(["Client"]) -->|"query example.com"| A2["Route 53"] A2 -->|"resolve ALB internally"| A3["ALB DNS"] A3 -->|"IP list"| A2 A2 -->|"A: 1.2.3.4"| A1 end
- CNAME flow: Client nhận hostname của ALB, phải tự resolve thêm một bước — tốn thêm một DNS round-trip và bị tính phí query Route 53.
- Alias flow: Route 53 resolve nội bộ, trả thẳng IP về client — không tốn thêm round-trip, không tính phí query khi target là AWS resource.
- Zone apex constraint: CNAME tại
example.comvi phạm RFC 1034 vì xung đột với SOA/NS record. Alias không bị ràng buộc này.
Tại Sao CNAME Không Dùng Được Ở Zone Apex?
Đây là điểm hay bị hiểu nhầm nhất. RFC 1034 quy định rằng nếu một node trong DNS có CNAME record, node đó không được có bất kỳ record nào khác. Nhưng zone apex (example.com) bắt buộc phải có SOA và NS record — đây là yêu cầu cứng của DNS protocol. Hai ràng buộc này xung đột trực tiếp, nên CNAME tại zone apex là invalid về mặt kỹ thuật.
Hình dung zone apex như tòa nhà chính của công ty — nó phải có biển tên (SOA) và danh bạ nội bộ (NS). CNAME giống như dán tờ giấy 'chuyển đến địa chỉ khác' lên cửa chính — bạn không thể vừa có biển tên vừa dán tờ giấy đó.
Nhiều kỹ sư thử dùng CNAME cho www.example.com (subdomain) và thấy hoạt động bình thường, rồi nghĩ có thể làm tương tự cho example.com. Subdomain không có SOA/NS nên không có xung đột — đó là lý do subdomain dùng CNAME được còn apex thì không.
Alias Record Hỗ Trợ Những AWS Targets Nào?
Alias record không phải dùng được với mọi endpoint. Route 53 chỉ hỗ trợ Alias cho một danh sách cụ thể các AWS resource types. Tính đến thời điểm viết bài, các targets được hỗ trợ bao gồm:
- Elastic Load Balancers (ALB, NLB, CLB)
- CloudFront distributions
- API Gateway (Regional và Edge-Optimized)
- S3 website endpoints (không phải S3 REST API endpoints)
- Elastic Beanstalk environments
- VPC Interface Endpoints
- Global Accelerator accelerators
- Route 53 record sets trong cùng hosted zone
Nếu bạn cần trỏ đến một hostname bên ngoài AWS hoặc một AWS resource không có trong danh sách trên, bạn phải dùng CNAME (hoặc A record nếu biết IP tĩnh).
Cấu Hình Alias Record Cho ALB Qua AWS CLI
Trước khi tạo record, bạn cần hosted zone ID của ALB — đây là một giá trị cố định theo region, khác với hosted zone ID của Route 53 domain của bạn. Tra cứu giá trị này trong tài liệu AWS chính thức theo region ALB của bạn.
Lấy hosted zone ID của Route 53 hosted zone:
aws route53 list-hosted-zones-by-name \
--dns-name example.com \
--query 'HostedZones[0].Id' \
--output text
Lấy DNS name và hosted zone ID của ALB:
aws elbv2 describe-load-balancers \
--names my-application-lb \
--query 'LoadBalancers[0].{DNSName:DNSName,CanonicalHostedZoneId:CanonicalHostedZoneId}' \
--output json
Tạo Alias A record cho zone apex trỏ đến ALB:
🔽 Xem change batch JSON và lệnh upsert
aws route53 change-resource-record-sets \
--hosted-zone-id Z1234567890ABCDEF \
--change-batch '{
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z35SXDOTRQ7X7K",
"DNSName": "my-application-lb-1234567890.us-east-1.elb.amazonaws.com",
"EvaluateTargetHealth": true
}
}
}
]
}'
Lưu ý quan trọng: HostedZoneId trong AliasTarget là hosted zone ID của ALB (lấy từ CanonicalHostedZoneId ở bước trên), không phải hosted zone ID của Route 53 domain bạn. Đây là điểm hay nhầm nhất khi cấu hình bằng tay.
Xác minh record đã được tạo đúng:
aws route53 list-resource-record-sets \
--hosted-zone-id Z1234567890ABCDEF \
--query "ResourceRecordSets[?Name=='example.com.']"
EvaluateTargetHealth — Tính Năng Hay Bị Bỏ Qua
Khi set EvaluateTargetHealth: true, Route 53 sẽ kiểm tra health của ALB target trước khi trả DNS response. Nếu ALB không healthy, Route 53 có thể failover sang record khác (nếu bạn có cấu hình routing policy như failover hoặc weighted). Đây là tính năng chỉ có ở Alias record, không có ở CNAME.
example.com"] --> R53["Route 53"] R53 --> ETH{"EvaluateTargetHealth
= true?"} ETH -->|"No"| RETURN_IP["Trả IP của ALB"] ETH -->|"Yes"| CHECK["Kiểm tra health
của ALB target"] CHECK --> HEALTHY{"ALB Healthy?"} HEALTHY -->|"Yes"| RETURN_IP HEALTHY -->|"No — có failover record"| FAILOVER["Trả Failover Record"] HEALTHY -->|"No — không có failover"| SERVFAIL["SERVFAIL"]
- Route 53 nhận DNS query từ client.
- Nếu
EvaluateTargetHealthbật, Route 53 kiểm tra health của ALB. - ALB healthy → trả IP về client.
- ALB unhealthy → nếu có failover record, Route 53 trả record thay thế; nếu không, trả SERVFAIL.
Symptom → Misdiagnosis → Root Cause: Case Thực Tế
Một team setup example.com bằng CNAME trỏ đến ALB hostname. Mọi thứ hoạt động bình thường trong môi trường dev — vì họ test qua www.example.com (subdomain). Khi deploy production với bare domain, một số DNS resolver trả về kết quả không nhất quán, một số client không resolve được.
Chẩn đoán ban đầu sai: Team nghĩ do TTL cache chưa expire sau khi thay đổi record, nên chờ thêm vài giờ.
Nguyên nhân thực sự: Một số authoritative DNS resolver từ chối phục vụ CNAME tại zone apex vì vi phạm RFC 1034, trả về SERVFAIL hoặc NOERROR với empty answer. Behavior này phụ thuộc vào implementation của từng resolver — không phải tất cả đều xử lý giống nhau, nên kết quả không nhất quán giữa các client ở các ISP khác nhau.
Fix: Xóa CNAME, tạo Alias A record cho example.com trỏ đến ALB. Vấn đề biến mất ngay lập tức vì Alias không vi phạm RFC constraint.
Log để nhận biết: nếu bạn thấy SERVFAIL hoặc empty answer khi query zone apex nhưng subdomain resolve bình thường, đây là dấu hiệu đầu tiên cần kiểm tra CNAME-at-apex.
dig example.com A +short
dig www.example.com A +short
Nếu www.example.com trả IP nhưng example.com trả rỗng hoặc lỗi, kiểm tra ngay loại record đang dùng cho zone apex.
Khi Nào Vẫn Nên Dùng CNAME?
Alias record không phải lúc nào cũng là lựa chọn đúng. Dùng CNAME khi:
- Target là hostname bên ngoài AWS (ví dụ: Heroku, Vercel, hostname của bên thứ ba).
- Bạn cần kiểm soát TTL thủ công — Alias TTL do AWS quản lý, bạn không set được.
- Record là subdomain (không phải zone apex) và target không thuộc danh sách Alias-supported resources.
example.com"} APEX -->|"Có"| AWS_TARGET{"Target là AWS resource
được Alias hỗ trợ?"} APEX -->|"Không — subdomain"| OUTSIDE{"Target ngoài AWS?"} AWS_TARGET -->|"Có"| USE_ALIAS["✅ Dùng Alias Record"] AWS_TARGET -->|"Không"| PROBLEM["⚠️ Không thể dùng CNAME
Cân nhắc lại kiến trúc"] OUTSIDE -->|"Có"| USE_CNAME["✅ Dùng CNAME"] OUTSIDE -->|"Không"| TTL{"Cần kiểm soát TTL?"} TTL -->|"Có"| USE_CNAME TTL -->|"Không"| USE_ALIAS
IAM Permissions Cần Thiết Để Quản Lý Route 53 Records
Để thực hiện các lệnh CLI ở trên, IAM principal cần tối thiểu các quyền sau. Lưu ý rằng Route 53 là global service, ARN không chứa region.
🔽 Xem IAM policy mẫu
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Route53RecordManagement",
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets",
"route53:ListHostedZonesByName",
"route53:GetHostedZone"
],
"Resource": "arn:aws:route53:::hostedzone/Z1234567890ABCDEF"
},
{
"Sid": "ELBDescribe",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:DescribeLoadBalancers"
],
"Resource": "*"
}
]
}
elasticloadbalancing:DescribeLoadBalancers yêu cầu Resource: * vì đây là List/Describe action không hỗ trợ resource-level restriction theo Service Authorization Reference.
Wrap-Up: Route 53 Alias Record Và Bước Tiếp Theo
Với bất kỳ domain nào trỏ đến AWS resource — đặc biệt là zone apex — Alias record là lựa chọn đúng về mặt kỹ thuật và vận hành. Nó giải quyết RFC constraint của zone apex, không tốn phí DNS query, và tích hợp native với health check của Route 53. CNAME vẫn có chỗ đứng khi target nằm ngoài hệ sinh thái AWS hoặc khi bạn cần kiểm soát TTL.
Kiểm tra lại toàn bộ hosted zone của bạn để xem có CNAME nào đang dùng ở zone apex không — đây là technical debt phổ biến trong các account AWS lâu năm.
- AWS Docs: Choosing between alias and non-alias records
- AWS Docs: Routing traffic to an ELB load balancer
Glossary — Thuật Ngữ Chính
| Thuật ngữ | Giải thích |
|---|---|
| Zone Apex | Root domain của hosted zone, ví dụ example.com — không có subdomain prefix. Còn gọi là naked domain hoặc bare domain. |
| Alias Record | Extension độc quyền của Route 53 cho phép trỏ đến AWS resource mà không vi phạm RFC 1034. Không phải DNS record type chuẩn. |
| CNAME | Canonical Name record — DNS record chuẩn trỏ một hostname đến hostname khác. Không dùng được ở zone apex. |
| CanonicalHostedZoneId | Hosted zone ID của ALB/ELB, khác với hosted zone ID của Route 53 domain. Dùng trong AliasTarget khi tạo Alias record. |
| EvaluateTargetHealth | Tham số Alias record cho phép Route 53 kiểm tra health của AWS target trước khi trả DNS response. |
Nhận xét
Đăng nhận xét