
Не толкова отдавна стартирахме Kubernetes 1.9 на AWS с помощта на Kops. Вчера, по време на плавно разгръщане на нов трафик в най-големия от нашите Kubernetes клъстери, започнах да забелязвам необичайни грешки при разрешаване на имена DNS, регистрирани от нашето приложение.
В GitHub за това се говори от известно време , затова и аз реших да се запозная с темата. В крайна сметка разбрах, че в нашия случай това е причинено от повишеното натоварване на kube-dns и dnsmasq. Най-интересното и ново за мен беше самата причина за значителното увеличение на трафика на DNS заявки. За това и какво може да се направи по въпроса, е темата на моя пост.
Разрешаването на DNS в контейнер, подобно на всяка Linux система, се определя от конфигурационния файл /etc/resolv.conf. По подразбиране Kubernetes dnsPolicy е ClusterFirst, което означава, че всяка DNS заявка ще бъде пренасочена към dnsmasq, стартиран в пода kube-dns вътре в клъстера, който от своя страна пренасочва заявката към приложението kube-dns, ако името завършва с суфикса на клъстера, или в противен случай, към DNS сървър на по-високо ниво.
файл /etc/resolv.conf всеки контейнер по подразбиране ще изглежда така:
nameserver 100.64.0.10
search namespace.svc.cluster.local svc.cluster.local cluster.local
eu-west-1.compute.internal
options ndots:5Както може да се забележи, тук има три директиви:
- Именен сървър — това е IP адресът на услугата
kube-dns - Посочени са 4 локални търсени домейна
search - Има опция
ndots:5
Интересна част от тази конфигурация е как локалните търсени домейни и настройките ndots:5 съществуват заедно. За да разберем това, е необходимо да се запознаем как работи разрешаването на DNS за непълни имена.
Какво е пълно име?
Пълно определено име — това е име, за което няма да се извършва локално търсене, и името ще се счита за абсолютен по време на разрешаване на имената. По подразбиране софтуерът на DNS счита името за напълно определено, ако завършва с точка (.), А иначе не е напълно определено. Тоест google.com. пълно е определено, а google.com — не е.
Как се обработва непълно име?
Когато приложението се свързва с отдалечен хост, посочен в името, разрешаването на DNS имена обикновено се извършва чрез системен повик, например, getaddrinfo(). Но ако името е непълно (не завършва на .), интересно е дали системното повикване първо ще се опита да разреши името като абсолютен адрес или първо ще премине през локалните търсени домейни? Това зависи от опцията ndots.
От ръководството за resolv.conf:
ndots:n
определяема прага за броя на точки, които трябва да се появят в името, преди да бъде направено начално абсолютно запитване. Стойността по подразбиране за n е 1, което означава, че ако в името има някакви точки, името ще бъде първо тествано като абсолютно име, преди към него да бъдат добавени някакви елементи от списъка за търсене.Това означава, че ако за ndots е зададена стойност 5, а името съдържа по-малко от 5 точки, системният повик ще опита да го разреши последователно, първо преминавайки през всички локални търсителни домейни и, ако не успее, в крайна сметка ще го разреши като абсолютно име.
Защо тогава ndots:5 може да се отрази негативно на производителността на приложението?
Както разбирате, ако вашето приложение използва много външен трафик, за всяко установено TCP свързване (или, по-точно, за всяко разрешено име) ще генерира 5 DNS запитвания, преди името да бъде правилно разрешено, тъй като първо преминава през 4 локални търсителни домейни и накрая издава запитване за разрешаване на абсолютно име.
На следната диаграма е показан сумарният трафик на нашите 3 модула kube-dns преди и след като преминахме на няколко имена на хостове, настроени в нашето приложение, на напълно определени.

На следната диаграма е показано закъснението на приложението преди и след като преминахме на няколко имена на хостове, настроени в нашето приложение, на пълни (вертикалната синя линия е разгръщането):

Решение #1 — използване на напълно определени имена
Ако имате малко статични външни имена (т.е. определени в конфигурацията на приложението), към които създавате голямо количество свързвания, може би най-простото решение е да ги смените на напълно определени, просто добавяйки. в края.
Това не е окончателно решение, но помага бързо, макар и не перфектно, да подобри ситуацията. Този патч прилагахме за разрешаване на нашия проблем, резултатите от което бяха показани на горните скрийншотове.
Решение #2 — персонализиране ndots в dnsConfig
В Kubernetes 1.9 в алфа режим се появи функционалност (бета версия v1.10), която позволява по-добър контрол върху параметрите на DNS чрез свойството на пода в dnsConfig. Между другото, той позволява настройването на стойност ndots за конкретен под, т.е.
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsConfig:
options:
- name: ndots
value: "1"Източници
Също така прочетете и други статии в нашия блог:
Източник: habr.com
