Wyszukiwanie DNS w Kubernetes

Przyp. tłum.: Problem DNS w Kubernetes, a dokładniej — konfiguracja parametru ndots, — jest zaskakująco popularny, i to już nie pierwszy rok. W kolejnym artykule na ten temat autor — inżynier DevOps z dużej firmy brokerskiej w Indiach — w bardzo prosty i zwięzły sposób opisuje, co warto wiedzieć kolegom korzystającym z Kubernetes.

Wyszukiwanie DNS w Kubernetes

Jedną z głównych zalet wdrażania aplikacji w Kubernetes jest bezproblemowe wykrywanie aplikacji. Wewnętrzna komunikacja klastra jest znacznie uproszczona dzięki koncepcji usługi (Service), która stanowi wirtualny adres IP, wspierający zbiór adresów IP podów. Na przykład, jeśli usługa vanilla chce połączyć się z usługą chocolate, może bezpośrednio zwrócić się do wirtualnego adresu IP dla chocolate. Pojawia się pytanie: kto w tym przypadku rozwiąże zapytanie DNS do chocolate i jak?

Rozwiązywanie nazw DNS jest konfigurowane w klastrze Kubernetes za pomocą CoreDNS. Kubelet dodaje pod z CoreDNS jako serwer nazw w plikach /etc/resolv.conf wszystkich podów. Jeśli spojrzymy na zawartość /etc/resolv.conf dowolnego podu, będzie ona wyglądać mniej więcej tak:

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

Ta konfiguracja jest używana przez klientów DNS do kierowania zapytań do serwera DNS. W pliku resolv.conf znajduje się następująca informacja:

  • nameserver: serwer, do którego będą kierowane zapytania DNS. W naszym przypadku to adres usługi CoreDNS;
  • search: definiuje ścieżkę wyszukiwania dla danego domeny. Ciekawe, że google.com lub mrkaran.dev nie są FQDN (pełnymi nazwami domenowymi). Zgodnie z standardowym porozumieniem, którego przestrzegają większość resolverów DNS, pełne (FDQN) domeny to tylko te, które kończą się kropką „.”, reprezentującą strefę główną. Niektóre resolvery potrafią samodzielnie dodać kropkę. W ten sposób mrkaran.dev. — to pełna nazwa domenowa (FQDN), a mrkaran.dev — nie;
  • ndots: Najciekawszy parametr (ten artykuł jest o nim). ndots ustala próg liczby kropek w nazwie zapytania, po osiągnięciu którego jest ona traktowana jako „pełna” nazwa domenowa. Więcej na ten temat porozmawiamy później, gdy będziemy analizować sekwencję wyszukiwania DNS.

Wyszukiwanie DNS w Kubernetes

Zobaczmy, co się dzieje, gdy żądamy mrkaran.dev w podzie:

$ 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

Dla tego eksperymentu ustawiłem poziom logowania CoreDNS na wszystko (co czyni go dość rozwlekłym). Przyjrzyjmy się logom pod'a coredns:

[INFO] 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
[INFO] 10.1.28.1:34040 - 36853 "A IN mrkaran.dev.svc.cluster.local. udp 47 false 512" NXDOMAIN qr,aa,rd 140 0.000214201s
[INFO] 10.1.28.1:33468 - 29482 "A IN mrkaran.dev.cluster.local. udp 43 false 512" NXDOMAIN qr,aa,rd 136 0.000156107s
[INFO] 10.1.28.1:58471 - 45814 "A IN mrkaran.dev. udp 29 false 512" NOERROR qr,rd,ra 56 0.110263459s
[INFO] 10.1.28.1:54800 - 2463 "AAAA IN mrkaran.dev. udp 29 false 512" NOERROR qr,rd,ra 68 0.145091744s

Uf. Dwie rzeczy zwracają uwagę:

  • Żądanie przechodzi przez wszystkie etapy wyszukiwania, aż odpowiedź nie zawiera kodu NOERROR (klienci DNS rozumieją to i przechowują jako wynik). NXDOMAIN oznacza, że dla tej nazwy domeny nie znaleziono rekordu. Ponieważ mrkaran.dev nie jest nazwą FQDN (zgodnie z ndots=5), resolver przegląda ścieżkę wyszukiwania i ustala kolejność zapytań;
  • Rekordy A i AAAA są przetwarzane równolegle. Problem w tym, że jednorazowe zapytania w /etc/resolv.conf są w domyślnym ustawieniu tak skonfigurowane, że wykonuje się równoległe wyszukiwanie w protokołach IPv4 i IPv6. Można wyłączyć to zachowanie, dodając opcję single-request do resolv.conf.

Uwaga: glibc może być skonfigurowany do sekwencyjnego wysyłania tych zapytań, a musl — nie, więc użytkownicy Alpine powinni to wziąć pod uwagę.

Eksperymentujemy z ndots

Spróbujmy jeszcze raz z ndots i zobaczmy, jak ten parametr się zachowuje. Idea jest prosta: ndots określa, czy klient DNS uzna domenę za absolutną czy względną. Na przykład, jak w przypadku prostego google, klient DNS dowiaduje się, czy ta domena jest absolutna? Jeśli ustawić ndots na 1, klient powie: „O, w google nie ma żadnej kropki; pewnie przejrzę cały listę wyszukiwania”. Jednak jeśli zapytamy google.com, lista sufiksów zostanie całkowicie zignorowana, ponieważ zapytana nazwa spełnia próg ndots (przynajmniej jedna kropka).

Upewnijmy się o tym:

$ cat /etc/resolv.conf
options ndots:1
$ nslookup mrkaran
Serwer: 10.152.183.10
Adres: 10.152.183.10#53

** serwer nie może znaleźć mrkaran: NXDOMAIN

Logi CoreDNS:

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

Ponieważ w mrkaran nie ma żadnej kropki, wyszukiwanie odbywało się przez cały list sufiksów.

Uwaga: w praktyce maksymalna wartość ndots jest ograniczona do 15; domyślnie w Kubernetes wynosi 5.

Zastosowanie w produkcji

Jeśli aplikacja wykonuje wiele zewnętrznych wywołań sieciowych, DNS może stać się wąskim gardłem w przypadku aktywnego ruchu, ponieważ podczas rozwiązywania nazw wykonuje się wiele zbędnych zapytań (zanim system dotrze do właściwego). Aplikacje zazwyczaj nie dodają strefy korzeniowej do nazw domen, jednak można to uznać za teoretyczny hack. To znaczy, zamiast żądać api.twitter.com, możesz 'hardcodować' api.twitter.com. (z kropką) w aplikacji, co skłoni klientów DNS do wykonania autorytatywnego wyszukiwania od razu w absolutnej domenie.

Ponadto, począwszy od wersji Kubernetes 1.14, rozszerzenia dnsConfig i dnsPolicy uzyskały status stabilny. W związku z tym podczas wdrażania poda można zmniejszyć wartość ndots, powiedzmy, do 3 (a nawet do 1!). W związku z tym każda wiadomość wewnątrz węzła musi zawierać pełną domenę. To jeden z klasycznych kompromisów, gdy trzeba wybierać między wydajnością a przenośnością. Wydaje mi się, że warto się tym przejmować tylko wtedy, gdy wyjątkowo niskie opóźnienia są żywotne dla Twojej aplikacji, ponieważ wyniki DNS są również buforowane wewnątrz.

Linki

Po raz pierwszy dowiedziałem się o tej funkcji na K8s-meetupie, który odbył się 25 stycznia. Tam poruszano, w tym także, ten problem.

Oto kilka linków do dalszego zgłębiania tematu:

Uwaga: postanowiłem nie używać dig w tym artykule. dig automatycznie dodaje kropkę (identyfikator strefy korzeniowej), czyniąc domenę „pełną” (FQDN), nie przechodząc ją wstępnie przez listę wyszukiwania. Pisałem o tym w jednej z poprzednich publikacji. Niemniej jednak dość zdumiewające jest to, że w ogóle, aby uzyskać standardowe zachowanie, trzeba ustawić osobny znacznik.

Dobrej obsługi DNS! Do zobaczenia!

P.S. od tłumacza

Przeczytaj także na naszym blogu:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster