نظام DNS في الكلاستر واكتشاف الخدمات
نظام DNS في الكلاستر واكتشاف الخدمات
يمرّ كل حركة المرور الداخلية في كلاستر Kubernetes الإنتاجي عبر نظام فرعي واحد بالغ الأهمية: CoreDNS. حين تستدعي الـ pod الخاصة بك العنوان http://payment-svc:8080، فهي لا تتصل بـ IP ثابت — بل تُحلِّل اسم DNS تترجمه CoreDNS إلى الـ ClusterIP الخاص بالـ Service في اللحظة ذاتها. إتقان هذا المسار من البداية إلى النهاية هو الفارق بين التخمين عند التعامل مع أعطال الشبكة وإصلاحها في أقل من خمس دقائق.
CoreDNS: المحلِّل الموثوق للكلاستر
حلّت CoreDNS محل kube-dns بوصفها إضافة DNS الافتراضية منذ الإصدار 1.13 من Kubernetes. تعمل كـ Deployment (عادةً نسختان لضمان التوافر العالي) في نيمسبيس kube-system، ويُعرِّضها الـ Service المسمى kube-dns عبر ClusterIP ثابت — عادةً 10.96.0.10. يكتب kubelet هذا العنوان في ملف /etc/resolv.conf داخل كل pod.
تُضبَط CoreDNS عبر ConfigMap باسم coredns في kube-system. لغة الإعداد تُسمى Corefile. يبدو Corefile الافتراضي كالتالي:
الإضافات الأساسية التي يجب فهمها: kubernetes — تُجيب على استعلامات نطاق الكلاستر؛ forward — ترسل كل ما سواها إلى المحلِّل الأعلى (محلِّل العقدة نفسها)؛ cache — تخزين مؤقت بـ TTL لتجنّب الوصول للـ API Server عند كل استعلام؛ loop — يكتشف حلقات التوجيه وينهار بأمان؛ health/ready — يُعرِّضان نقطتي نهاية للـ liveness والـ readiness.
الأسماء الكاملة (FQDNs)
يتبع نظام DNS في Kubernetes اصطلاح تسمية هرمياً صارماً. تحصل كل Service على إدخال DNS ضمن نطاق الكلاستر المُعدَّل (الافتراضي: cluster.local).
تتيح لك نطاقات البحث المُعرَّفة في /etc/resolv.conf داخل كل pod استخدام الأسماء المختصرة. يمكن لـ pod في نيمسبيس payments الوصول إلى Service باسم api فقط، إذ يجرّب المحلِّل api.payments.svc.cluster.local. أولاً. للوصول عبر النيمسبيسات، استخدم api.payments. النموذج الكامل المنتهي بنقطة يتجاوز توسيع نطاقات البحث دائماً.
nginx— داخل النيمسبيس نفسه فقطnginx.default— اختصار عبر النيمسبيساتnginx.default.svc— تضمين القطعة svc صراحةًnginx.default.svc.cluster.local— FQDN الكاملnginx.default.svc.cluster.local.— المطلق (النقطة تمنع نطاقات البحث)
الـ Headless Services وسجلات DNS للـ Pods
حين تضبط clusterIP: None، تصبح الـ Service بلا رأس (headless). تُعيد CoreDNS عناوين IP الـ pods فردياً (سجلات A لكل pod) بدلاً من VIP واحد. تستثمر StatefulSets هذا الأمر: تحصل كل pod على اسم DNS ثابت بالشكل <pod-name>.<service-name>.<namespace>.svc.cluster.local. على سبيل المثال، postgres-0.postgres-headless.data.svc.cluster.local يُحلَّل دائماً إلى IP الـ pod الرئيسية — حتى بعد إعادة التشغيل، طالما ظل اسم الـ pod ثابتاً.
تشخيص مشكلات تحليل DNS
تتجلى أعطال DNS في Kubernetes بأشكال خفية: اتصال مرفوض (IP خاطئ)، لا مضيف بهذا الاسم (NXDOMAIN)، أو مهل منتهية (pods CoreDNS غير سليمة). تعتمد سير العمل المعيارية للتشخيص على pod مؤقتة تشغّل dnsutils.
ndots:5 فخ أداء إنتاجي. مع ndots:5، أي اسم يحتوي على أقل من 5 نقاط يُطلِق ما يصل إلى 6 استعلامات DNS قبل الوصول للشكل المطلق. للأسماء الخارجية مثل api.stripe.com، يجرّب المحلِّل api.stripe.com.default.svc.cluster.local. أولاً، ثم api.stripe.com.svc.cluster.local. وهكذا. على نطاق واسع، يضاعف هذا معدل استعلامات DNS أو يضاعفه ثلاثاً. الحل: أضف نقطة في النهاية للأسماء الخارجية في إعدادات تطبيقك، أو اضبط dnsConfig.options[ndots: 1] على pods تُجري استدعاءات خارجية فقط.
تخصيص DNS لكل Pod
يمكنك تجاوز سلوك DNS لكل pod باستخدام حقلَي dnsConfig وdnsPolicy. dnsPolicy: ClusterFirst هو الافتراضي (استخدم CoreDNS، ارجع لمحلِّل العقدة عند الفشل). dnsPolicy: None يتيح تحديد محلِّل مخصص بالكامل.
ضبط ConfigMap لـ CoreDNS في الإنتاج
على نطاق واسع (500+ عقدة، عشرات الآلاف من الـ pods)، يمكن أن تصبح CoreDNS عنق زجاجة. أفضل الممارسات الإنتاجية:
- تشغيل نسختين على الأقل، يُفضَّل 3-4، موزّعة عبر عقد مختلفة بـ pod anti-affinity.
- زيادة TTL للتخزين المؤقت — الافتراضي
cache 30متحفظ. ارفعه إلىcache 120للـ Services الثابتة لتقليل حركة المرور الصاعدة 4 مرات. - Horizontal Pod Autoscaler — اربط CoreDNS بـ HPA يقيس على عدد استعلامات DNS عبر Prometheus adapter.
- NodeLocal DNSCache — DaemonSet يشغّل cache محلياً على كل عقدة، يعترض استعلامات DNS قبل وصولها لـ Service الـ CoreDNS. يُقلّص زمن الاستجابة من ~2ms إلى ~0.1ms للمُدخلات المخزّنة ويزيل الضغط على جدول conntrack من UDP DNS.
reload التغييرات كل 30 ثانية افتراضياً. إذا غيّرت Corefile ورأيت سلوكاً غير متوقع، انتظر 30 ثانية أو احذف pods CoreDNS لإجبارها على إعادة التشغيل. تحذير إضافي: تعديل ConfigMap بينما يحتوي على Corefile معطوب سيُعطّل CoreDNS عند إعادة التحميل — تحقق دائماً من الصحة البنيوية بـ corefile-tool validate قبل التطبيق.
اكتشاف الخدمات خارج DNS
يُعدّ DNS الآلية الرئيسية للاكتشاف، لكن Kubernetes يُعرِّض الـ Services أيضاً عبر متغيرات بيئة تُحقن عند إنشاء الـ pod (مثل NGINX_SERVICE_HOST وNGINX_SERVICE_PORT). هذه آلية قديمة: تعكس فقط الـ Services التي كانت موجودة قبل بدء الـ pod، وتنمو قائمة المتغيرات بلا حدود في الكلاسترات الكبيرة. افضل دائماً DNS لاكتشاف الخدمات في الكود الجديد.
على مستوى التطبيق، تُطبّق الأنظمة الإنتاجية خدمة mesh (Istio أو Linkerd) فوق DNS تعترض الاتصالات بعد التحليل وتُطبّق mTLS والإعادة وقطع الدائرة بشفافية. تظل CoreDNS نفسها الجهة الموثوقة للتحليل؛ تلتف الـ mesh على الاتصال فقط بعد التحليل.