DNS внутри кластера: короткое имя, namespace и FQDN
Как resolv.conf, search-домены и ndots превращают curl http://web в адрес Service.
CoreDNS - DNS-сервер кластера
CoreDNS - DNS-сервер кластера, который переводит имена Service в их IP.
Он работает как Deployment в namespace kube-system. Namespace -
логический раздел кластера для группировки объектов.
Перед CoreDNS стоит Service kube-dns с фиксированным ClusterIP
(обычно 10.43.0.10). ClusterIP - внутренний адрес Service.
Этот IP kubelet прописывает каждому новому Pod в файл
/etc/resolv.conf. kubelet - агент Kubernetes на ноде, который
запускает Pod.
nameserver 10.43.0.10
search demo.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
Разберём три строки этого файла.
nameserver
nameserver - адрес, куда Pod шлёт DNS-запросы. Все запросы Pod летят сначала в CoreDNS. Если имя не из кластерных зон, CoreDNS пересылает запрос наружу, на DNS ноды.
search
search - список доменов, которые автоматически дописываются к коротким именам. Порядок важен: первым стоит namespace самого Pod.
Клиент пишет curl http://web/. Резолвер по очереди пробует варианты.
web.demo.svc.cluster.local.- сработало, вернул ClusterIP.- Если не нашлось -
web.svc.cluster.local. - Если не нашлось -
web.cluster.local. - Если не нашлось -
web., тогда вопрос уйдёт на внешний DNS.
Поэтому из Pod в demo короткое имя web находит Service web
того же namespace. Из Pod в other короткое web не находит
ничего: первый search-домен другой.
options ndots:5
ndots:5 говорит резолверу так. Если в имени меньше пяти точек,
сначала пробуй search-домены, и только потом считай имя абсолютным.
В web.demo одна точка, поэтому оно тоже проходит через search.
Реально резолвится web.demo.svc.cluster.local.
Какие имена работают
| Из какого ns | Какое имя | Резолвится? |
|---|---|---|
demo | web | да (search дописывает свой ns) |
demo | web.demo | да |
demo | web.demo.svc.cluster.local | да |
other | web | нет (Service web в other отсутствует) |
other | web.demo | да |
other | web.demo.svc.cluster.local | да |
Правило простое: внутри своего namespace хватает короткого имени. Из
чужого добавляй <svc>.<ns>. FQDN (полное имя) работает всегда, но
писать его руками долго.
Что отдаёт DNS
Для обычного Service резолвится A-запись на ClusterIP Service.
A-запись - это соответствие имени одному IP-адресу.
web.demo.svc.cluster.local. 5 IN A 10.43.123.45
TTL равен 5 секундам по умолчанию. TTL - время, которое клиент кеширует ответ. При пересоздании Service клиенты быстро подхватят новый IP.
У Headless Service (поле clusterIP: None) DNS вернёт сразу IP-адреса
Pod, без распределения нагрузки. Это нужно для StatefulSet (контроллер
для приложений с состоянием, где у каждого Pod стабильное имя и адрес).
Headless разбирается дальше в треке.
Кто-то делает curl http://web-7d4f-abcde к имени Pod. DNS на имена
обычных Pod не отвечает, только на Service.
Как посмотреть DNS изнутри
В образе busybox есть утилита nslookup, она делает DNS-запрос.
Короткое имя резолвится в том namespace, где запущен Pod.
kubectl run probe --rm -it --image=busybox:1.36 --restart=Never -- \
nslookup web
Вывод будет такой:
Server: 10.43.0.10
Address: 10.43.0.10:53
Name: web.demo.svc.cluster.local
Address: 10.43.123.45
Server - это сам CoreDNS. Address под строкой Name - это
ClusterIP Service, результат резолва.
Если подходящий Pod уже запущен, новый создавать не нужно: kubectl exec делает резолв прямо в нём.
kubectl exec probe -- nslookup web
kubectl exec probe -- cat /etc/resolv.conf
Второй командой смотрят nameserver, search и options ndots
конкретного Pod.
Что обычно ломается
- Pod в чужом namespace стучится по короткому имени. Решение: писать
<svc>.<ns>или собирать FQDN. - Образ
alpineиспользует библиотеку musl (компактная замена стандартной C-библиотеки glibc), которая раньше плохо работала с ndots и search. Если короткое имя не резолвится из alpine, бери FQDN или busybox. - ndots:5 замедляет внешний DNS: каждый запрос к публичному домену
сначала проходит четыре search-варианта. На большом трафике это
иногда настраивают через поле
dnsConfigв spec Pod.
Домашка
Теорию закрепляет задание на своём кластере: 1 шаг с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.
./run.sh start k8s-dns-internal # развернуть стартовое состояние
./run.sh verify k8s-dns-internal # проверить текущий шаг
Коротко
- Имена Service резолвит CoreDNS, его адрес kubelet кладёт в
/etc/resolv.confкаждого Pod. - Строка
searchдописывает<ns>.svc.cluster.localк коротким именам, поэтому свой namespace работает без префикса. - Из чужого namespace нужен как минимум
<svc>.<ns>, FQDN работает всегда. ndots:5заставляет проходить search-домены перед внешним запросом и потому замедляет резолв публичных имён.- DNS отвечает на имена Service, а не на имена обычных Pod.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс