พอดที่รัน OpenVPN sidecar ล้มเหลวในการแปลชื่อตามรูปแบบที่รู้จักได้: ชื่อของคลัสเตอร์ค้างอยู่ ชื่อระยะไกลตอบจนกว่าพอดจะเริ่มใหม่ และไฟล์ resolver ที่คุณแก้ไขก็ย้อนกลับ. ไม่มีอะไรในลำดับนั้นที่เป็นความผิดพลาดของอุโมงค์. พอดมีไฟล์ resolver หนึ่งไฟล์และสองโลกของชื่อ และไฟล์สามารถเรียงเซิร์ฟเวอร์ตามลำดับได้ แต่ไม่สามารถแสดงโซนได้. การแก้ไขที่ยั่งยืนคือ resolver ที่รันอยู่ในพอดและเป็นเจ้าของการแยก ดังนั้นไฟล์จึงคงอยู่ง่าย และไม่มีนโยบายใดมีเหตุผลให้เขียนทับได้อีก.

ทำไมการแก้ไขของคุณจึงหายไปเรื่อยๆ

ไฟล์เป็นของ kubelet ไม่ใช่ของคุณ. ภายใต้ dnsPolicy: ClusterFirst kubelet สร้างมันเพื่อชี้ไปยัง DNS ของคลัสเตอร์ และสร้างใหม่ทุกครั้งที่คอนเทนเออร์เริ่มทำงาน. ทุกอย่างที่คุณเปลี่ยนผ่าน kubectl exec อยู่ในชั้นที่เขียนได้ของคอนเทนเออร์ ดังนั้นการเริ่มใหม่ การเอาออก หรือ rollout จึงทิ้งมันไป. สเปกของพอดยังคงพานโยบายเดิม นั่นคือเหตุผลที่ไฟล์เดิมกลับมา.

การตั้ง dnsPolicy: None หยุดการสร้างใหม่ และยังลบการแปลคลัสเตอร์ด้วย. คุณได้ไฟล์ที่ควบคุมและเสียชื่อที่คุณต้องการ. การแลกเปลี่ยนนี้คือปัญหาทั้งหมด: resolv.conf ไม่มีแนวคิดเรื่องโซน มีเพียงเซิร์ฟเวอร์ที่ลองตามลำดับ ดังนั้นจึงส่ง cluster.local ไปยังหนึ่งที่อยู่และโซนส่วนตัวไปยังอีกที่อยู่ไม่ได้.

รัน resolver หนึ่งตัวในพอด บน 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 ในฐานะ root และนโยบายคลัสเตอร์บางอย่างกำหนดให้คุณระบุไว้อย่างชัดเจน. ตอนนี้ทุกคอนเทนเออร์ในพอดขึ้นกับความที่คอนเทนเออร์ตัวนั้นทำงาน ดังนั้นเพิ่ม readiness probe ต่อชื่อที่ไม่มีผลกระทบ และปล่อยให้แอปพลิเคชันทนความล้มเหลวตอนเริ่มต้นได้.

ให้ upstream แก่โซนส่วนตัวแต่ละโซน

Corefile คือรายการโซน แต่ละรายการระบุเซิร์ฟเวอร์ที่ตอบได้. หนึ่งบล็อกครอบโซนของอุโมงค์ และบล็อก catch-all มาสุด ทำหน้าที่รับทุกอย่างที่ไม่มีบล็อกใดอ้างสิทธิ์. catch-all ต้องชี้ไปยัง upstream จริง ห้ามชี้กลับไปยังพอด: .:53 { forward . 10.100.0.10 } ใช้ resolver ของคลัสเตอร์ซ้ำ เพราะมันส่งชื่อสาธารณะไปยัง resolver ของโนดอยู่แล้ว. สsิ่งอื่นในพอดไม่ต้องรู้ว่าชื่ออยู่ในเครือข่ายใด.

.: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 ส่งมา หรือจากเซิร์ฟเวอร์ที่มีอำนาจของโซนนั้น. ถ้า resolver ของคลัสเตอร์ไม่ตอบชื่อสาธารณะ ให้ใส่ที่อยู่ของ resolver ของโนดลงในบล็อก 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. จุดท้ายเป็นเรื่องรูปลักษณ์ เพราะชื่อโซนถูกปรับให้อยู่ในรูปแบบที่มีคุณสมบัติเต็มที่ ขอบเขตของสัฟฟิกซ์เป็นตัวกำหนดว่าควอรีจะลงจอดที่ใด.

ตัดสินว่าการส่งต่อเป็นของ resolver คลัสเตอร์หรือไม่

ถ้าทุกงานในนามสเปคต้องการโซนของอุโมงค์ บล็อกส่งต่อใน ConfigMap ของ CoreDNS ภายใต้ kube-system จะถูกกว่า sidecar ต่อพอด. การเปลี่ยนแปลงนั้นอยู่ระดับคลัสเตอร์: ต้องมีสิทธิ์ผู้ดูแลและเริ่ม deployment ที่ทุกคนพิ่งใหม่. จำกัดเพียงโซนเดียวนั้น ไม่ใช่ราก. ที่อยู่ของอุโมงค์ของงานหนึ่งจะกลายเป็น resolver ของทุกพอดสำหรับโซนนั้น และในวันที่อุโมงค์ล้มทั้งคลัสเตอร์จะเสียชื่อนั้น.

sidecar รักษารัศมีการระเบิดไว้ภายในพอดเดียว ซึ่งเป็นค่าเริ่มต้นที่ดีกว่าเมื่อมีเพียงไม่กี่บริการที่ต้องใช้เครือข่ายระยะไกล. ไม่ว่าคุณจะเลือกอย่างไร ให้บันทึกว่า resolver ตัวไหนเป็นเจ้าของโซน เพราะคนต่อไปที่จะแก้ปัญหา timeout จะถาม.

ชื่อที่แปลได้ขณะที่การเชื่อมต่อยังล้มเหลว

การแปลคือหนึ่งในสองอย่างที่อุโมงค์ต้องนำไป อีกอย่างคือ เส้นทางขากลับ และเครือข่ายของพอดซ่อนมันได้ดี. ถ้าเซิร์ฟเวอร์ OpenVPN เองรันเป็นพอด กฎที่คุณเพิ่มในคอนเทนเออร์นั้นจะไม่ควบคุมทราฟฟิกที่ออกทางโนด. ความล้มเหลวนั้นแคบแบบ: มีเพียงพอดบนโนดที่รันเซิร์ฟเวอร์ด้วยที่ได้รับคำตอบ และอย่างอื่นหมดเวลาหมดอยู่.

การรันเซิร์ฟเวอร์ด้วย hostNetwork: true จะนำมันกลับไปยังนามสเปคของโนด ซึ่งกฎ FORWARD และการแปลต้นทางจะทำงาน. แปลพูลลูกข่ายตอนออก ไม่เช่นนั้นจะไม่มีโนดระยะไกลใดมีเส้นทางกลับไปยังที่อยู่ของอุโมงค์เช่น 10.8.0.6. ตรวจสองทิศทางก่อนแตะ Corefile อีกครั้ง. อุโมงค์ที่นำควอรีไปแต่ไม่นำคำตอบกลับจะทำให้เกิด timeout เหมือน resolver ที่ไม่เคยได้รับควอรีเลย.

ตรวจสอบจากพอดใหม่ ไม่ใช่จากเซสชันที่คุณแก้

ถามทั้งสองโซนอย่างชัดเจน แล้วทำควอรีซ้ำหลังจากพอดถูกแทนที่. การตั้งค่าที่มีอยู่เฉพาะในคอนเทนเออร์ที่กำลังทำงานไม่ถือเป็นการตั้งค่า:

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 ไว้ในตั๋ว เพราะนั่นคือสิ่งที่แยกปัญหาชื่อออกจากปัญหาการเส้นทาง.

บทความที่เกี่ยวข้อง