← Kubernetes: сеть
6 мин · просто · Урок 3 из 8

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 - список доменов, которые автоматически дописываются к коротким именам. Порядок важен: первым стоит namespace самого Pod.

Клиент пишет curl http://web/. Резолвер по очереди пробует варианты.

  1. web.demo.svc.cluster.local. - сработало, вернул ClusterIP.
  2. Если не нашлось - web.svc.cluster.local.
  3. Если не нашлось - web.cluster.local.
  4. Если не нашлось - 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Какое имяРезолвится?
demowebда (search дописывает свой ns)
demoweb.demoда
demoweb.demo.svc.cluster.localда
otherwebнет (Service web в other отсутствует)
otherweb.demoда
otherweb.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.

Что обычно ломается

Домашка

Теорию закрепляет задание на своём кластере: 1 шаг с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-dns-internal     # развернуть стартовое состояние
./run.sh verify k8s-dns-internal    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.