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 у якасці сервера імёнаў у файлах /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 змяшчаецца наступная інфармацыя:

  • сервер імёнаў: сервер, на які будуць накіроўвацца DNS-запыты. У нашым выпадку гэта адрас сэрвісу CoreDNS;
  • пошук: вызначае шлях пошуку вызначанага дамена. Цікаўна, што google.com або mrkaran.dev не з'яўляюцца FQDN (поўнымі даменнымі імёнамі). Згодна са стандартнай дамовай, якой ідуць большасць resolver’аў DNS, поўнымі (FDQN) даменамі лічацца толькі тыя, якія сканчаюцца кропкай «.», уяўлялай каранёвую зону. Некаторыя resolver’ы ўмеюць дадаваць кропку самастойна. Такім чынам, 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:

[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

Фух. Дзве рэчы тут прыцягваюць увагу:

  • Запыт праходзіць па ўсіх этапах пошуку да таго часу, пакуль адказ не будзе змяшчаць код NOERROR (DNS-кліенты яго разумеюць і захоўваюць як вынік). NXDOMAIN азначае, што для дадзенага даменнага імя запіс не знойдзены. Паколькі mrkaran.dev не з'яўляецца FQDN-імем (у адпаведнасці з ndots=5), resolver глядзіць на пошукавы шлях і вызначае парадак запытаў;
  • Запісу А и АААА паступаюць паралельна. Справа ў тым, што разавыя запыты ў /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
Server: 10.152.183.10
Address: 10.152.183.10#53

** server can't find mrkaran: NXDOMAIN

Логі 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

паколькі ў mrkaran няма ніводнай кропкі, пошук праводзіўся па ўсім спісе суфіксаў.

Заўвага: на практыцы максімальнае значэнне ndots абмежавана 15; па змаўчанні ў Kubernetes яно роўна 5.

Ужыванне ў production

Калі прыкладанне выконвае мноства вонкавых сеткавых выклікаў, DNS можа стаць вузкім месцам у выпадку актыўнага трафіку, паколькі пры дазволе імя выконваецца мноства лішніх запытаў (перш чым сістэма дабярэцца да патрэбнага). Прыкладанні звычайна не дадаюць каранёвую зону да даменных імёнаў, аднак гэта цалкам цягне на хак. Гэта значыць замест таго, каб запытваць api.twitter.com, вы можаце за’hardcode’іць api.twitter.com. (з кропкай) у дадатку, што заахвоціць DNS-кліентаў выконваць аўтарытэтны пошук адразу ў абсалютным дамене.

Акрамя таго, пачынаючы з версіі Kubernetes 1.14, пашырэння dnsConfig и dnsPolicy атрымалі статус стабільных. Такім чынам, пры разгортванні pod’а можна паменшыць значэнне. ndots, скажам, да 3 (і нават да 1!). З-за гэтага кожнае паведамленне ўсярэдзіне вузла павінна будзе ўключаць поўны дамен. Гэта адзін з класічных кампрамісаў, калі даводзіцца выбіраць паміж прадукцыйнасцю і пераноснасцю. Мне здаецца, што перажываць пра гэта варта толькі ў выпадку, калі звышнізкія затрымкі жыццёва важныя для вашага дадатку, паколькі вынікі DNS таксама кэшуюцца ўнутры.

Спасылкі

Упершыню пра гэтую асаблівасць я даведаўся на K8s-meetup'е, які прайшоў 25 студзеня. Там ішла размова, у тым ліку, і аб гэтай праблеме.

Вось некалькі спасылак для далейшага вывучэння:

Заўвага: Я палічыў за лепшае не выкарыстоўваць dig у гэтым артыкуле. dig аўтаматычна дадае кропку (ідэнтыфікатар каранёвай зоны), робячы дамен "поўным" (FQDN), ня праганяючы яго папярэдне праз спіс пошуку. Пісаў пра гэта ў адной з папярэдніх публікацый. Тым не менш, даволі дзіўны той факт, што, увогуле, для стандартных паводзін даводзіцца задаваць асобны сцяг.

Добрага DNS’інгу! Да хуткага!

PS ад перакладчыка

Чытайце таксама ў нашым блогу:

Крыніца: habr.com

Дадаць каментар