Kubernetes болон OpenVPN sidecar хооронд DNS-ийг хэрхэн хуваах вэ
Sidecar под-д хоёр нэрийн ертөнц хэрэгтэй. Нэг loopback resolver-ийг кластер болон туннель руу чиглүүлж, засварласан resolv.conf-оос хамааралтай байхаа болино уу.
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 болгож тохируул, под-д тэр нэг хаягийг өг, 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-д хүрдэг. Corefile-ийг ConfigMap-аас mount хийх нь түүнийг газар дээр засварладаг файл биш, хувилбарласан оролт болгон хадгаладаг. Үүссэн resolv.conf дараа нь нэг нэрийн сервер, өөр юу ч агуулахгүй бөгөөд энэ нь тухай санаа гаргаж болох төлөв юм.
Энд хоёр зүйл хазуулна. Албан ёсны image 53 портыг root болгож холбодог, зарим кластерийн бодлого үүнийг тодорхой бичихийг шаарддаг. Под-ын контейнер бүр одоо тэр нэг контейнерийн ажиллаж байгаахаас хамааралтай тул хор хөнөөлгүй нэр руу readiness probe нэмж, аппликейшнд эхлэх үеийн алдааг тэвчээрэхийг зөвшөөр.
Хувь бүс бүрт өөрийн upstream-ийг өг
Corefile бол бүсүүдийн жагсаалт бөгөөд тус бүр нь хариулж чадах серверийг нэрлэдэг. Нэг блок туннелийн бүсийг хамаардаг, харин бүхнийг барьдаг блок хамгийн сүүлд ирж, ямар ч тодорхой блок шаардаагүй бүхнийг авдаг. Бүхнийг барьдаг блок бодит upstream руу чиглэх ёстой, хэзээ ч под руу буцах ёсгүй: .:53 { forward . 10.100.0.10 } кластерийн resolver-ийг дахин ашигладаг, учир нь тэр resolver нийтийн нэрүүдийг зангилааны өөрийн resolver руу дамжуулж байдаг. Под-д өөр юу ч нэр аль сүлжээнд хамаарахыг мэдэх шаардлагагүй.
.: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 утгаас, эсвэл тэр бүсийн эрх бүхий серверээс ирдэг. Хэрэв чиний кластерийн resolver нийтийн нэрэд хариулахгүй бол зангилааны resolver-ийн хаягийг бүхнийг барьдаг блокт хий, үүнийг зангилаа дээр уншсан байх ёстой, под дотор биш.
Бүхнийг барьдаг блокыг /etc/resolv.conf руу чиглүүлэх хэрэггүй, энэ нь урьдаж байгаа нэг мөр бөгөөд яг энэ тохиргоонд урхийг болдог. dnsPolicy: None дор подын өөрийн файл ганц нэрийн сервер 127.0.0.1-г агуулдаг тул тэр зорилго нь CoreDNS өөрөө байгаад тохирохгүй асуулга бүр хугацаа дуустал давтагдана. svc.acme.internal нэртэй блок тэр нэр болон түүний доорх нэр бүрт тохирч, db.svc.acme.internal-г хамраад svc.acme.internal.example.net-г хасдаг. Төгсгөлийн цэг нь гадаадуурын зүйл, учир нь бүсийн нэрүүд бүрэн мэргэжсэн хэлбэрт хэвийн болдог; дагаварын хил нь асуулга хаана буухыг шийддэг.
Дамжуулалт кластерийн resolver-т хамаарах эсэхийг шийд
Хэрэв нэрийн огторгуйн ажлын ачаалал бүрт туннелийн бүс хэрэгтэй бол kube-system дорх CoreDNS ConfigMap дахь дамжуулалтын блок под бүрд sidecar-аас хямд байдаг. Энэ өөрчлөлт кластерийн түвшний: администраторын эрх, бүгдээс хамааралтай deployment-ийг дахин ачаалах шаардлагатай. Үүнийг тэр нэг бүсээр хагалзаарай, хэзээ ч үндсээр биш. Нэг ажлын ачаалалын туннелийн хаяг дараа нь тэр бүсийн хувьд под бүрийн resolver болж, туннель унах өдөр бүх кластер нэрээ алдана.
Sidecar дэлбэрэлтийн радиусыг нэг под дотор барьдаг, энэ нь алслагдсан сүлжээ хэдэн хэдэн үйлчилгээнд л хэрэгтэй үед илүү сайн өгөгдмөл юм. Ямар ч сонгосон ч бүсийг аль resolver эзэмшдэг боломыг бичиж хадгал, учир нь дараагийн хүн timeout-ыг дибаг хийхдээ асуух болно.
Холбоос одоохон бүтэлгүй байхад шийдэгддэг нэрүүд
Шийдвэрлэлт нь туннель зөөх ёстой хоёр зүйлийн нэг; нөгөө нь буцах зам, подын сүлжээ үүнийг сайтаар нуудаг. Хэрэв OpenVPN сервер өөрөө под болж ажилладаг бол тэр контейнерт нэмсэн дүрмүүд зангилаагаар гардаг трафикийг удирдахгүй. Энэ алдаа нарийн: зөвхөн серверийг мөн ажиллуулсан зангилааны подууд л хариу аваж, бусад бүхэн хугацаа хэтэрсэн.
Серверийг hostNetwork: true-тэй ажиллуулах нь түүнийг зангилааны нэрийн огторгуй руу буцааж, тэнд FORWARD дүрэм болон эх бусадын орчуулга үйлчилдэг. Гарахдаа клиентийн савыг орчуул, эсвэл 10.8.0.6 жишиг туннелийн хаяг руу буцах зам ямар ч алс зангилаанд байхгүй. Corefile-д дахин хүрэхийн өмнө хоёр чиглэлийг шалга. Асуулгыг зөөж, хариуыг зөөдэггүй туннель асуулгыг хэзээ ч аваагүй resolver-тэй яг ижил timeout үүсгэдэг.
Засварласан сессээс биш, шинэ подоос шалга
Хоёр бүсийг тодорхой асууж, дараа нь под солигдсны дараа асуулгыг давта. Зөвхөн ажиллаж байгаа контейнерт байдаг тохиргоо нь тохиргоо биш:
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-ийн гаралтыг тикетэд хадгал, учир нь энэ нь нэрийн проблемыг маршрутын проблемээс тусгаарлах артефакт юм.