تفشل البودات التي تشغل سايدكار OpenVPN في حل الأسماء بنمط قابل للتعرف: أسماء العنقود تتعلق، والأسماء البعيدة تجيب حتى يعاد تشغيل البود، وملف المحلل الذي عدّلته يعود. لا شيء في هذا التسلسل عطل في النفق. للبود ملف محلل واحد وعالما أسماء، والملف يستطيع سرد الخوادم بالترتيب لكنه لا يستطيع التعبير عن المناطق. الحل الدائم هو محلل يعمل داخل البود ويملك التقسيم، فيبقى الملف بسيطًا ولا يجد أي سياسة سببًا لإعادة كتابته.

لماذا يختفي التعديل الذي أجريته دائمًا

الملف ملك kubelet لا ملكك. تحت dnsPolicy: ClusterFirst ينشئه kubelet ليشير إلى DNS العنقود ويعيد إنشاءه في كل بدء لحاوية. كل ما تغيره عبر kubectl exec يعيش في طبقة الحاوية القابلة للكتابة، لذا يطرحه إعادة التشغيل أو الإخلاء أو rollout. مواصفات البود ما زالت تحمل السياسة نفسها، لذا يعود الملف نفسه.

ضبط dnsPolicy: None يوقف إعادة الإنشاء ويزيل أيضًا حل العنقود. تحصل على ملف تتحكم به وتفقد الأسماء التي احتجت إليها. هذا المقايضة هي المشكلة كلها: resolv.conf لا يعرف مفهوم المناطق، بل خوادم تجرب بالترتيب، فلا يستطيع إرسال cluster.local إلى عنوان ومنطقة خاصة إلى آخر.

شغّل محللًا واحدًا داخل البود، على loopback

وجّه البود إلى خادم أسماء واحد على loopback، ثم اترك حاوية CoreDNS التي تشارك فضاء أسماء شبكة البود تجيب على المنفذ 53. اضبط السياسة على None، وأعط البود هذا العنوان الوحيد، وأضف حاوية DNS بجانب VPN والتطبيق:

spec:
  dnsPolicy: None
  dnsConfig:
    nameservers:
      - 127.0.0.1
    options:
      - name: ndots
        value: "5"
  containers:
    - name: dns
      image: coredns/coredns
      args: ["-conf", "/etc/coredns/Corefile"]
      volumeMounts:
        - {name: corefile, mountPath: /etc/coredns, readOnly: true}
    - name: vpn
      image: your-openvpn-client-image
    - name: app
      image: your-app-image
  volumes:
    - name: corefile
      configMap:
        name: split-dns-corefile

الحاويات الثلاث تشارك فضاء أسماء شبكة واحدًا، لذا يصل 127.0.0.1:53 من حاوية التطبيق إلى CoreDNS دون خدمة ودون port-forward ودون التفاف عبر شبكة العنقود. تركيب Corefile من ConfigMap يبقيه مدخلًا منسوخًا بدل ملف يعدّل في موضعه. الـ resolv.conf المولّد يحتوي حينئذ خادم أسماء واحدًا ولا شيء آخر، حالة يمكن التفكير فيها.

تعضّ هنا تفصيلان. الصورة الرسمية تربط المنفذ 53 كجذر، وبعض سياسات العنقود تطلب كتابة ذلك صراحة. كل حاوية في البود تعتمد الآن على عمل تلك الحاوية الواحدة، لذا أضف readiness probe على اسم غير ضار واترك التطبيق يتحمل أخطاء البدء.

أعط كل منطقة خاصة upstream خاصًا بها

Corefile قائمة مناطق، كل منطقة تسمي الخادم الذي يستطيع الإجابة عنها. كتلة واحدة تغطي منطقة النفق، وتأتي كتلة catch-all أخيرًا وتأخذ كل ما لم تطالب به أي كتلة صريحة. يجب أن تستهدف كتلة catch-all مصدرًا حقيقيًا، ولا تعود أبدًا إلى البود: .:53 { forward . 10.100.0.10 } يعيد استخدام محلل العنقود لأنه يرسل الأسماء العامة بالفعل إلى محللات العقدة نفسها. لا يحتاج أي شيء آخر في البود إلى معرفة أي شبكة ينتمي إليها الاسم.

.:53 {
  errors
  cache 30
  forward . 10.100.0.10
}

svc.acme.internal:53 {
  errors
  cache 30
  forward . 192.168.240.1
}

اقرأ عنوان العنقود من خدمة kube-dns في kube-system بدل نسخه من مقال، لأن CIDR الخدمة تختلف. يأتي عنوان النفق من قيمة dhcp-option DNS التي يرسلها خادم OpenVPN، أو من الخادم المخول لتلك المنطقة. إذا كان محلل العنقود لديك لا يجيب على الأسماء العامة، فضع عنوان محلل العقدة في كتلة catch-all، مقروءًا على العقدة وليس داخل البود.

لا توجّه كتلة catch-all إلى /etc/resolv.conf، فهو السطر الواحد المغري وفخ في هذا الإعداد بالضبط. تحت dnsPolicy: None يحتوي ملف البود نفسه على خادم الأسماء الوحيد 127.0.0.1، لذا فإن هذا الهدف هو CoreDNS نفسه وكل استعلام غير مطابق يتكرر حتى تنتهي المهلة. الكتلة المسماة svc.acme.internal تطابق ذلك الاسم وكل اسم تحته، مما يغطي db.svc.acme.internal ويستثني svc.acme.internal.example.net. النقطة النهائية شكلية، لأن أسماء المناطق تُطبّع إلى الشكل المؤهّل الكامل؛ حد اللاحقة هو ما يقرر أين تهبط الاستعلامات.

قرّر هل ينتمي التوجيه إلى محلل العنقود

إذا كان كل عبء عمل في فضاء الأسماء يحتاج منطقة النفق، فإن كتلة توجيه في ConfigMap الـ CoreDNS تحت kube-system أرخص من سايدكار لكل بود. هذا التغيير على مستوى العنقود: يتطلب حقوق المسؤول وإعادة تشغيل نشر يعتمد عليه الجميع. اقصره على تلك المنطقة واحدة، ولا تطلقًا على الجذر. يصبح عنوان نفق عبء عمل واحد حينئذ محلل كل بود للمنطقة، وفي يوم سقوط النفق يفقد العنقود كله الاسم.

يبقي السايدكار نطاق الانفجار داخل بود واحد، وهو الاختيار الأفضل عندما تحتاج خدمات قليلة فقط إلى الشبكة البعيدة. مهما اخترت، دوّن أي محلل يملك المنطقة، لأن الشخص التالي الذي يصحّح مهلة سيسأل.

أسماء تُحل بينما تفشل الاتصالات بعد

الحل واحد من شيئين على النفق حملهما؛ الآخر هو مسار العودة، وشبكة البود تخفيه جيدًا. إذا كان خادم OpenVPN نفسه يعمل كبود، فإن القواعد التي تضيفها في تلك الحاوية لا تحكم الحركة الخارجة عبر العقدة. هذا العطل ضيق: بودات العقدة التي شغّلت الخادم أيضًا هي وحدها من حصل على إجابات، وانتهت مهلة كل ما عدا ذلك.

تشغيل الخادم مع hostNetwork: true يعيده إلى فضاء أسماء العقدة، حيث تعمل قاعدة FORWARD وترجمة المصدر. ترجم مجموعة العملاء عند الخروج، وإلا فليس لأي عقدة بعيدة مسار عودة إلى عنوان نفق مثل 10.8.0.6. افحص الاتجاهين قبل لمس Corefile مجددًا. النفق الذي يحمل الاستعلام دون الإجابة ينتج المهلة نفسها التي ينتجها محلل لم يتلق الاستعلام أبدًا.

تحقّق من بود جديد، لا من الجلسة التي أصلحتها

اسأل المنطقتين صراحة، ثم أعد الاستعلام بعد استبدال البود. الإعداد الموجود فقط في حاوية تعمل ليس إعدادًا:

kubectl exec -it deploy/app -- dig @127.0.0.1 kubernetes.default.svc.cluster.local +short
kubectl exec -it deploy/app -- dig @127.0.0.1 db.svc.acme.internal +short
kubectl delete pod -l app=your-app
kubectl wait --for=condition=Ready pod -l app=your-app --timeout=90s
kubectl exec -it deploy/app -- dig @127.0.0.1 db.svc.acme.internal +short

إذا أجاب الزوج الأول ولم يجب الزوج بعد الاستبدال، فالـ Corefile سليم ومواصفات البود ليست كذلك. إذا أجاب الاثنان ولم يتصل التطبيق بعد، فأوقف تنقيح DNS واختبر مسار TCP بـ nc -vz db.svc.acme.internal 5432 من داخل الحاوية. احفظ خرج dig في التذكرة، لأنه الدليل الذي يفصل مشكلة الاسم عن مشكلة التوجيه.

مقالات ذات صلة