DNS търсене в Kubernetes

Прим. прев.: Проблемата с DNS в Kubernetes, а именно — настройването на параметъра ndots, — изненадващо популярна, и то вече не за пръв година. В поредната статия по темата нейният автор — DevOps-инженер от голяма брокерска компания в Индия — по много прост и сбит начин разказва какво е полезно да знаят колегите, експлоатиращи Kubernetes.

DNS търсене в Kubernetes

Едно от основните предимства на разгръщането на приложения в Kubernetes — безпроблемното откриване на приложения. Вътрешноклъстерната комуникация се опростява значително благодарение на концепцията за услуга (Услуга), която представлява виртуален IP, поддържащ набор от IP адреси на pod-ове. Например, ако услугата vanilla желая да се свърже с услугата chocolate, тя може да се обърне директно към виртуалния IP за chocolate. Възниква въпросът: кой в този случай ще разреши DNS запитването към chocolate и как?

Разрешаването на DNS имена се настройва в клъстера Kubernetes с помощта на CoreDNS. Kubelet записва pod с CoreDNS като DNS сървър в файловете на /etc/resolv.conf всички pod-ове. Ако погледнем съдържанието на /etc/resolv.conf някой pod, то ще изглежда приблизително по следния начин:

search hello.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.152.183.10
options ndots:5

Тази конфигурация се използва от DNS клиенти за пренасочване на запитванията към DNS сървъра. В файла resolv.conf се съдържа следната информация:

  • nameserver: сървърът, към който ще бъдат насочвани DNS запитванията. В нашия случай това е адресът на услугата CoreDNS;
  • search: определя пътя на търсене на определен домейн. Интересно е, че google.com или mrkaran.dev не са FQDN (пълни домейн имена). Според стандартното споразумение, следвано от повечето DNS резолвери, пълните (FDQN) домейни се считат само тези, които завършват с точка «.», представляваща кореновата зона. Някои резолвери могат да добавят точката сами. По този начин, mrkaran.dev. е пълно домейн име (FQDN), а mrkaran.dev не е;
  • ndots: Най-интересният параметър (тази статия е точно за него). ndots определя прага на точките в името на запитването, при достигането на който то се счита за «пълно» домейн име. По-подробно за това ще говорим по-късно, когато анализираме последователността на DNS търсенето.

DNS търсене в Kubernetes

Нека да видим какво се случва, когато запитваме mrkaran.dev в pod:

$ nslookup mrkaran.dev
Server: 10.152.183.10
Address: 10.152.183.10#53

Non-authoritative answer:
Name: mrkaran.dev
Address: 157.230.35.153
Name: mrkaran.dev
Address: 2400:6180:0:d1::519:6001

За този експеримент настроих нивото на логиране на CoreDNS на all (което го прави доста многословен). Нека разгледаме логовете на pod'а coredns:

[ИНФО] 10.1.28.1:35998 - 11131 "A IN mrkaran.dev.hello.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000263728s
[ИНФО] 10.1.28.1:34040 - 36853 "A IN mrkaran.dev.svc.cluster.local. udp 47 false 512" NXDOMAIN qr,aa,rd 140 0.000214201s
[ИНФО] 10.1.28.1:33468 - 29482 "A IN mrkaran.dev.cluster.local. udp 43 false 512" NXDOMAIN qr,aa,rd 136 0.000156107s
[ИНФО] 10.1.28.1:58471 - 45814 "A IN mrkaran.dev. udp 29 false 512" NOERROR qr,rd,ra 56 0.110263459s
[ИНФО] 10.1.28.1:54800 - 2463 "AAAA IN mrkaran.dev. udp 29 false 512" NOERROR qr,rd,ra 68 0.145091744s

Уф. Две неща тук привлекат вниманием:

  • Запитването преминава през всички етапи на търсене, докато отговорът не съдържа код NOERROR (DNS клиентите го разбират и го съхраняват като резултат). NXDOMAIN означава, че за това доменно име записа не е намерен. Тъй като mrkaran.dev не е FQDN име (съгласно ndots=5), резолверът гледа на пътя за търсене и определя реда на запитванията;
  • Записите А и AAAAA поступват паралелно. Става въпрос, че единичните запитвания в /etc/resolv.conf по подразбиране са настроени по такъв начин, че се извършва парален търсене по протоколите IPv4 и IPv6. Такова поведение може да бъде отменено, добавяйки опция single-request в resolv.conf.

Бележка: glibc може да бъде настроено за последователно изпращане на тези запитвания, а musl — не, така че потребителите на Alpine трябва да имат предвид.

Експериментираме с ndots

Нека експериментираме още малко с ndots и да видим как се държи този параметър. Идеята е проста: ndots определя, дали DNS клиентът ще счита домена за абсолютен или относителен. Например, как в случай на прост google DNS клиент, той установява, че доменът е абсолютен? Ако зададете ndots равен на 1, клиентът ще каже: „О, в google няма нито една точка; вероятно ще прегледам целия списък за търсене“. Обаче, ако поискате google.com, списъкът с суфикси ще бъде напълно игнориран, тъй като запитаното име удовлетворява прага ndots (има поне една точка).

Нека се уверим в това:

$ cat /etc/resolv.conf
options ndots:1
$ nslookup mrkaran
Сървър: 10.152.183.10
Адрес: 10.152.183.10#53

** сървърът не може да намери mrkaran: NXDOMAIN

Логове на CoreDNS:

[ИНФО] 10.1.28.1:52495 - 2606 "A IN mrkaran.hello.svc.cluster.local. udp 49 false 512" NXDOMAIN qr,aa,rd 142 0.000524939s
[ИНФО] 10.1.28.1:59287 - 57522 "A IN mrkaran.svc.cluster.local. udp 43 false 512" NXDOMAIN qr,aa,rd 136 0.000368277s
[ИНФО] 10.1.28.1:53086 - 4863 "A IN mrkaran.cluster.local. udp 39 false 512" NXDOMAIN qr,aa,rd 132 0.000355344s
[ИНФО] 10.1.28.1:56863 - 41678 "A IN mrkaran. udp 25 false 512" NXDOMAIN qr,rd,ra 100 0.034629206s

Тъй като в mrkaran няма нито една точка, търсенето се извършва по целия списък от суфикси.

Забележка: на практика максималната стойност ndots е ограничена до 15; по подразбиране в Kubernetes е 5.

Приложение в production

Ако приложението извършва множество външни мрежови извиквания, DNS може да се превърне в тясно място при активен трафик, тъй като при разрешаване на името се извършват множество излишни запитвания (преди системата да стигне до необходимото). Приложенията обикновено не добавят кореновата зона към домейн имената, но това определено е вариант. Тоест вместо да запитвате api.twitter.com, можете да 'hardcode'нете api.twitter.com. (с точка) в приложението, което ще накара DNS клиентите да извършат авторитетно търсене веднага в абсолютния домейн.

Освен това, от версия 1.14 на Kubernetes, разширенията dnsConfig и dnsPolicy получиха статус стабилни. По този начин при разгръщане на pod можете да намалите стойността ndots, да речем, на 3 (даже до 1!). Поради това всяко съобщение в рамките на възела трябва да включва пълния домейн. Това е един от класическите компромиси, когато се налага да избирате между производителност и преносимост. Мисля, че трябва да се притеснявате само в случаи, когато свръхниските закъснения са жизненоважни за вашето приложение, тъй като резултатите от DNS също се кешират вътре.

Връзки

За първи път узнах за тази функция на K8s-meetup, проведен на 25 януари. Там беше обсъдено, включително и този проблем.

Ето няколко линка за по-нататъшно проучване:

Забележка: Предпочетох да не използвам dig в тази статия. dig автоматично добавя точка (идентификатор на кореновата зона), правейки домейна 'пълен' (FQDN), не пропускайки го първо през списъка за търсене. Писах за това в една от предишните публикации. Все пак е доста удивително, че за стандартното поведение трябва да се задава отделен флаг.

Хубав DNS! До скоро!

P.S. от преводача

Прочетете също в нашия блог:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster