Kubernetes आणि OpenVPN साइडकारमध्ये DNS कसे विभाजित करावे
साइडकार पॉडला दोन नामविश्वे लागतात. एक लूपबॅक रिझोल्व्हर क्लस्टर आणि टनेलकडे निर्देशित करा, आणि संपादित resolv.conf वर अवलंबून राहणे थांबवा.
OpenVPN साइडकार चालवणारे पॉड नाव निराकरणात ओळखीच्या पद्धतीने अयशस्वी होतात: क्लस्टर नावे लटकतात, दूरची नावे पॉड पुन्हा सुरू होईपर्यंत प्रतिसाद देतात, आणि तुम्ही संपादित केलेली रिझोल्व्हर फाइल परत जाते। त्या क्रमात काहीही टनेलचा दोष नाही। पॉडला एक रिझोल्व्हर फाइल आणि दोन नामविश्वे असतात, आणि फाइल सर्व्हर क्रमाने सूचीबद्ध करू शकते पण झोन व्यक्त करू शकत नाही। टिकाऊ उपाय म्हणजे पॉडच्या आत चालणारा आणि विभाजनाचा मालक असलेला रिझोल्व्हर, त्यामुळे फाइल साधी राहते आणि कोणत्याही धोरणाला ती पुन्हा लिहिण्याचे कारण नसते।
तुम्ही केलेला बदल सतत का अदृश्य होतो
फाइल kubelet ची आहे, तुमची नाही। dnsPolicy: ClusterFirst अंतर्गत kubelet ती क्लस्टर DNS कडे निर्देशित करण्यासाठी तयार करते आणि कंटेनर सुरू होताच पुन्हा तयार करते। kubectl exec द्वारे तुम्ही बदलता ते कंटेनरच्या लिहिण्यायोग्य स्तरात राहते, म्हणून पुन्हा सुरू करणे, बाहेर काढणे किंवा रोलआउट ते टाकून टाकतात। पॉड स्पेसिफिकेशन अजूनही तेच धोरण घेऊन असते, म्हणूनतीर्थ आताच फाइल परत येते।
dnsPolicy: None सेट केल्याने पुनर्निर्मिती थांबते आणि क्लस्टर निराकरण देखील काढून टाकते। तुम्हाला नियंत्रित फाइल मिळते आणि आवश्यक असलेली नावे जातात। ही देवाणघेवाण संपूर्ण समस्या आहे: resolv.conf ला झोनची संकल्पना नाही, फक्त क्रमाने प्रयत्न करायचे सर्व्हर, म्हणून ते cluster.local एका पत्त्यावर आणि खाजगी झोन दुसर्या पत्त्यावर पाठवू शकत नाही।
पॉडमध्ये एक रिझोल्व्हर चालवा, लूपबॅकवर
पॉडला लूपबॅकवरील एका नेमसर्व्हरकडे निर्देशित करा, नंतर पॉडची नेटवर्क नामजागा सामायिक करणार्या CoreDNS कंटेनरला पोर्ट 53 वर प्रतिसाद देऊ द्या। धोरण None वर सेट करा, पॉडला तो एकच पत्ता द्या आणि VPN व अॅप्लिकेशनच्या शेजारी DNS कंटेनर जोडा:
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 सेवेशिवाय, port-forward शिवाय आणि क्लस्टर नेटवर्कमधून वळसा न घालता CoreDNS पर्यंत पोहोचते। ConfigMap मधून Corefile माउंट केल्याने ती जागेवरच संपादित होणार्या फाइलऐवजी आवृत्तीबद्ध इनपुट म्हणून राहते। तयार झालेल्या resolv.conf मध्ये नंतर एकच नेमसर्व्हर आणि इतर काहीही नसते, ही अशी स्थिती आहे ज्याबद्दल तर्क करता येतो।
येथे दोन तपशील चावतात। अधिकृत इमेज पोर्ट 53 ला root म्हणून बांधते, आणि काही क्लस्टर धोरणे ते स्पष्टपणे लिहिण्याची मागणी करतात। पॉडमधील प्रत्येक कंटेनर आता तो एकच कंटेनर सुरू असण्यावर अवलंबून आहे, म्हणून निरुपद्रवी नावावर readiness प्रोब जोडा आणि अॅप्लिकेशनला सुरुवातीच्या अयशस्वीतेचा सहन करू द्या।
प्रत्येक खाजगी झोनला स्वत:हा upstream द्या
Corefile म्हणजे झोनची यादी, प्रत्येक तिला उत्तर देऊ शकणार्या सर्व्हरचे नाव सांगते। एक ब्लॉक टनेल झोन व्यापतो, आणि सर्व पकडणारा ब्लॉक शेवटी येतो आणि कोणत्याही स्पष्ट ब्लॉकने दावा न केलेले सर्व घेतो। सर्व पकडणार्या ब्लॉकने खर्या upstream कडे लक्ष देवे, कधीही पॉडकडे परत नाही: .: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-system मधील kube-dns सेवेवरून वाचा, कारण सेवा CIDR वेगळे असतात। टनेलचा पत्ता OpenVPN सर्व्हर पाठवतो त्या dhcp-option DNS मूल्यातून किंवा त्या झोनच्या अधिकृत सर्व्हरकडून येतो। तुमचा क्लस्टर रिझोल्व्हर सार्वजनिक नावांना उत्तर देत नसेल, तर नोडच्या रिझोल्व्हरचा पत्ता सर्व पकडणार्या ब्लॉकमध्ये ठेवा, तो नोडवर वाचलेला असावा, पॉडमध्ये नाही।
सर्व पकडणारा ब्लॉक /etc/resolv.conf कडे निर्देशित करू नका, ती मोहक एक ओळ आणि याच नेमक्या संरचनेत सापळा आहे। dnsPolicy: None अंतर्गत पॉडच्या स्वतःच्या फाइलमध्ये एकमेव नेमसर्व्हर 127.0.0.1 असतो, म्हणून ते लक्ष्य CoreDNS स्वतःच आहे आणि जुळत नसलेली प्रत्येक क्वेरी कालबाह्य होईपर्यंत पुनरावृत्ती होते। svc.acme.internal नावाचा ब्लॉक त्या नावाशी आणि त्याखालील प्रत्येक नावाशी जुळतो, ज्यात db.svc.acme.internal येते आणि svc.acme.internal.example.net वगळले जाते। शेवटचा बिंदू दृश्यात्मक आहे, कारण झोन नावे पूर्ण पात्र स्वरूपात सामान्यीकृत होतात; प्रत्ययाची सीमा क्वेरी कुठे उतरते हे ठरवते।
फॉरवर्डिंग क्लस्टर रिझोल्व्हरचे आहे का नाही ते ठरवा
जर नामजागेतील प्रत्येक वर्कलोडला टनेल झोन हवा असेल, तर kube-system अंतर्गत CoreDNS ConfigMap मधील फॉरवर्डिंग ब्लॉक प्रत्येक पॉडला साइडकारपेक्षा स्वस्त आहे। तो बदल क्लस्टर-स्तरीय आहे: त्याला प्रशासकीय अधिकार आणि सर्व अवलंबून असलेल्या डिप्लॉयमेंटची पुन्हा सुरुवात लागते। तो त्या एका झोनपुरता मर्यादित ठेवा, कधीही मूळापर्यंत नाही। एका वर्कलोडचा टनेल पत्ता नंतर त्या झोनसाठी प्रत्येक पॉडचा रिझोल्व्हर होतो, आणि टनेल पडल्या दिवशी संपूर्ण क्लस्टर नाव गमावतो।
साइडकार स्फोट त्रिज्या एका पॉडमध्ये ठेवतो, जे फक्त काही सेवांना दूरचे नेटवर्क लागत असताना चांगले डीफॉल्ट आहे। तुम्ही काहीही निवडा, कोणता रिझोल्व्हर झोनचा मालक आहे ते लिहून ठेवा, कारण पुढची व्यक्ती टाइमआउट डीबग करताना विचारेल।
जोडण्या अजून अयशस्वी होत असताना सुटणारी नावे
निराकरण हे टनेलने वाहून नेण्याच्या दोन गोष्टींपैकी एक आहे; दुसरे म्हणजे परतीचा मार्ग, आणि पॉड नेटवर्क तो चांगला लपवते। 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 डीबग करणे थांबवा आणि कंटेनरच्या आतून nc -vz db.svc.acme.internal 5432 ने TCP मार्ग तपासा। dig चे आउटपुट तिकिटमध्ये ठेवा, कारण तेच नावाची समस्या राउटिंगच्या समस्येपासून वेगळी करणारे कलाकृती आहे।