سجلات Route 53 Alias مقابل CNAME: متى تستخدم كلاً منهما وتوجيه النطاق إلى ALB
عند ربط نطاقك الرئيسي example.com بـ Application Load Balancer، يقع كثير من المهندسين في فخ استخدام سجل CNAME — ثم يكتشفون لاحقاً أن المتصفح يُعيد خطأ أو أن الطلبات لا تصل أصلاً. السبب الجذري هو قيد DNS أساسي يتعلق بـ zone apex، وهو ما يحله سجل Alias في Route 53 بشكل كامل.
TL;DR: Alias مقابل CNAME في Route 53
| المعيار | CNAME | Route 53 Alias |
|---|---|---|
| يعمل على zone apex (example.com) | ❌ ممنوع بمعيار DNS | ✅ مدعوم بالكامل |
| يشير إلى ALB / CloudFront / S3 | ✅ (subdomain فقط) | ✅ (apex + subdomain) |
| رسوم الاستعلام | تُحتسب كاستعلام عادي | مجاني للموارد AWS المدعومة |
| يتابع تغييرات IP للـ ALB تلقائياً | ✅ (عبر TTL) | ✅ (Route 53 يتابع داخلياً) |
| يظهر في استجابة DNS كـ A/AAAA | ❌ يظهر كـ CNAME | ✅ يُحلَّل مباشرة إلى IP |
| Health Check integration | محدود | ✅ مدمج مع Route 53 Health Checks |
كيف يعمل DNS وأين تكمن مشكلة Zone Apex
معيار DNS (RFC 1034) يمنع وضع سجل CNAME على نفس الاسم الذي يحمل سجلات SOA أو NS — وهذا بالضبط ما يحدث على example.com (الـ apex). إذا حاولت إضافة CNAME على الـ apex، فإن خادم DNS سيرفض الإدخال لأن وجود CNAME مع SOA/NS على نفس الاسم يُعدّ تعارضاً في المعيار.
Route 53 Alias ليس سجل DNS قياسياً — إنه امتداد خاص بـ Route 53. عندما يستقبل Route 53 استعلاماً على اسم مُعرَّف بـ Alias، يُحلّ الهدف داخلياً ويُعيد سجل A أو AAAA مباشرة للعميل. العميل لا يرى CNAME أبداً.
- CNAME على subdomain: المتصفح يسأل عن
www.example.com، يحصل على CNAME يشير إلى اسم ALB، ثم يُحلّ ALB إلى IP. - Alias على apex: المتصفح يسأل عن
example.com، Route 53 يُحلّ الـ Alias داخلياً ويُعيد IP مباشرة — لا CNAME في الاستجابة. - CNAME على apex (محظور): خادم DNS يرفض الإدخال لتعارضه مع SOA/NS على نفس الاسم.
لماذا ALB يحتاج Alias وليس A Record ثابتاً
الـ ALB لا يملك عنوان IP ثابتاً — عناوين IP تتغير عند scaling أو عند أحداث داخلية في البنية التحتية لـ AWS. لهذا السبب AWS تُعطيك اسم DNS للـ ALB (my-alb-123456789.us-east-1.elb.amazonaws.com) وليس IP ثابتاً.
إذا استخدمت A Record ثابتاً بـ IP مُستخرج يدوياً، ستنكسر الخدمة عند أول تغيير في البنية التحتية. سجل Alias يحل هذه المشكلة لأن Route 53 يتابع اسم DNS للـ ALB داخلياً ويُحدّث الاستجابة تلقائياً.
فكّر في Alias كـ symlink داخل Route 53 — عندما يتغير الهدف، كل من يشير إليه يحصل على العنوان الجديد تلقائياً دون أي تدخل منك.
إعداد سجل Alias لتوجيه النطاق إلى ALB
الخطوات التالية تُغطي إنشاء سجل Alias على الـ apex (example.com) وعلى subdomain (www.example.com) باستخدام AWS CLI.
الخطوة 1: استخراج معرّف Hosted Zone للنطاق
قبل أي شيء، تحتاج إلى HostedZoneId الخاص بنطاقك في Route 53. هذا المعرّف مطلوب في كل عملية تعديل على السجلات.
aws route53 list-hosted-zones-by-name \
--dns-name example.com \
--query 'HostedZones[0].Id' \
--output text
الناتج سيكون بصيغة /hostedzone/Z1234567890ABC — احتفظ بالجزء بعد /hostedzone/.
الخطوة 2: استخراج HostedZoneId الخاص بالـ ALB
سجل Alias يتطلب HostedZoneId الخاص بالـ ALB نفسه — وهو مختلف عن Hosted Zone النطاق. هذا المعرّف ثابت لكل region وموثّق في AWS documentation. استخرجه مباشرة من بيانات الـ ALB.
aws elbv2 describe-load-balancers \
--names my-application-load-balancer \
--query 'LoadBalancers[0].{DNSName:DNSName,CanonicalHostedZoneId:CanonicalHostedZoneId}' \
--output table
ستحصل على DNSName (اسم DNS للـ ALB) وCanonicalHostedZoneId (المطلوب لسجل Alias).
الخطوة 3: إنشاء سجل Alias على الـ apex
الآن ننشئ السجل الفعلي. لاحظ أن AliasTarget يحتوي على EvaluateTargetHealth — تفعيله يجعل Route 53 يتوقف عن الإجابة بـ IP إذا كان الـ ALB غير صحي، مما يُحسّن سلوك failover.
🔽 اضغط لعرض ملف change-batch JSON
{
"Comment": "Alias record for apex pointing to ALB",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z35SXDOTRQ7X7K",
"DNSName": "my-alb-123456789.us-east-1.elb.amazonaws.com",
"EvaluateTargetHealth": true
}
}
}
]
}
aws route53 change-resource-record-sets \
--hosted-zone-id Z1234567890ABC \
--change-batch file://alias-apex.json
الخطوة 4: إنشاء سجل Alias لـ www كـ subdomain
نفس المنطق ينطبق على www.example.com، مع الفارق أن CNAME كان سيعمل هنا — لكن Alias أفضل لأنه مجاني الاستعلام ويُحلَّل مباشرة إلى IP.
aws route53 change-resource-record-sets \
--hosted-zone-id Z1234567890ABC \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "www.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z35SXDOTRQ7X7K",
"DNSName": "my-alb-123456789.us-east-1.elb.amazonaws.com",
"EvaluateTargetHealth": true
}
}
}]
}'
الخطوة 5: التحقق من انتشار السجل
بعد إنشاء السجل، تحقق من حالة التغيير أولاً — Route 53 يُعيد ChangeId في كل عملية تعديل، واستخدامه يُخبرك متى انتشر التغيير عبر خوادم DNS لـ Route 53.
aws route53 get-change \
--id /change/C1234567890ABC \
--query 'ChangeInfo.Status' \
--output text
عندما تُصبح القيمة INSYNC، السجل منتشر. للتحقق الفعلي من الاستجابة:
dig example.com A +short
يجب أن يُعيد عناوين IP مباشرة — لا CNAME في الاستجابة.
تشخيص مشكلة شائعة: CNAME على apex يعمل في بعض الأدوات لكن يفشل في الإنتاج
المشكلة التي رأيتها أكثر من مرة: مهندس يختبر CNAME على apex باستخدام nslookup أو أداة DNS عبر الإنترنت ويرى أنه 'يعمل' — ثم يُفاجأ بأن Route 53 يرفض حفظ السجل أو أن بعض resolvers ترفض الاستجابة.
السبب: بعض أدوات الاختبار تتسامح مع انتهاكات معيار DNS وتُعيد نتيجة — لكن resolvers الإنتاج (خاصة المُقيّدة بـ RFC) ترفض استجابة CNAME على apex أو تتجاهلها. Route 53 نفسه يمنعك من حفظ CNAME على apex في hosted zone.
- المحاولة الخاطئة: إضافة CNAME على
example.com— Route 53 يرفض الحفظ لوجود SOA/NS على نفس الاسم. - التشخيص الخاطئ: المهندس يختبر بأداة خارجية تتسامح مع الانتهاك وتُعيد نتيجة — يظن المشكلة في مكان آخر.
- السبب الفعلي: قيد RFC 1034 على zone apex، وليس مشكلة في الـ ALB أو الشبكة.
- الحل: استبدال CNAME بـ Alias record من نوع A.
متى تستخدم CNAME بدلاً من Alias
ليس كل شيء يحتاج Alias. CNAME مناسب في حالتين محددتين:
- الهدف خارج AWS: إذا كنت تُشير إلى خدمة خارجية (مثل Heroku أو GitHub Pages)، Alias لا يدعم أهدافاً خارج AWS — استخدم CNAME على subdomain.
- التوافق مع أدوات DNS خارجية: إذا كنت تُدير DNS خارج Route 53 وتحتاج سجلاً قياسياً يفهمه أي خادم DNS، CNAME هو الخيار الوحيد (على subdomain).
في كل حالة أخرى داخل Route 53 — خاصة عند الإشارة إلى ALB أو CloudFront أو S3 website endpoint أو API Gateway — Alias هو الخيار الصحيح.
IAM: الصلاحيات المطلوبة لإدارة سجلات Route 53
إذا كنت تُشغّل هذه الأوامر من pipeline أو من role محدود الصلاحيات، تأكد من وجود الصلاحيات التالية كحد أدنى:
🔽 اضغط لعرض IAM Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets",
"route53:GetChange"
],
"Resource": "arn:aws:route53:::hostedzone/Z1234567890ABC"
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZonesByName",
"route53:ListHostedZones"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:DescribeLoadBalancers"
],
"Resource": "*"
}
]
}
لاحظ أن route53:ListHostedZones وelasticloadbalancing:DescribeLoadBalancers تتطلب Resource: "*" لأنها لا تدعم تقييد الموارد على مستوى ARN وفقاً لـ Service Authorization Reference.
الخلاصة والخطوات التالية لإعداد Route 53 Alias
القاعدة بسيطة: على zone apex استخدم دائماً Alias، وعلى subdomain يشير إلى خدمة AWS استخدم Alias أيضاً للاستفادة من المجانية وتكامل Health Checks. CNAME احتفظ به للأهداف خارج AWS أو عند الحاجة لسجل DNS قياسي.
الخطوات التالية الموصى بها:
- فعّل
EvaluateTargetHealth: trueفي كل سجلات Alias المرتبطة بـ ALB لتحسين سلوك failover. - إذا كنت تستخدم Route 53 Routing Policies (Weighted, Latency, Failover)، تأكد من أن Alias مدعوم مع السياسة التي تختارها — راجع AWS Documentation: Choosing Between Alias and Non-Alias Records.
- للنطاقات التي تستخدم HTTPS، تأكد من أن شهادة ACM مُصدرة للـ apex والـ www معاً (
example.comو*.example.comأو كلاهما بشكل صريح).
مسرد المصطلحات
| المصطلح | التعريف |
|---|---|
| Zone Apex | الاسم الجذري للنطاق (example.com) دون أي subdomain — يحمل سجلات SOA وNS التي تمنع وضع CNAME عليه. |
| Alias Record | امتداد خاص بـ Route 53 يُحلّ هدفاً داخلياً ويُعيد A/AAAA مباشرة — غير موجود في معيار DNS القياسي. |
| CanonicalHostedZoneId | معرّف Hosted Zone الخاص بمورد AWS (مثل ALB) — مطلوب في تعريف AliasTarget ومختلف عن Hosted Zone النطاق. |
| EvaluateTargetHealth | خيار في Alias يجعل Route 53 يتحقق من صحة الهدف — عند تفعيله، يتوقف Route 53 عن الإجابة إذا كان الهدف غير صحي. |
| UPSERT | عملية في Route 53 تُنشئ السجل إذا لم يكن موجوداً أو تُحدّثه إذا كان موجوداً — بديل آمن لـ CREATE في الأتمتة. |
تعليقات
إرسال تعليق