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 задає граничне число точок в імені запиту, при досягненні якого воно розглядається як «повне» доменне ім'я. Докладніше про це ми поговоримо пізніше, коли аналізуватимемо послідовність 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

Додати коментар або відгук