DNS в контейнерных средах представляет собой принципиально иную парадигму по сравнению с традиционными виртуальными машинами или физическими серверами. Технология контейнеризации формирует специфические задачи разрешения имён, обусловленные тремя ключевыми аспектами: изоляцией, динамической природой среды и требованиями масштабируемости.
Изоляция означает, что каждый контейнер существует в собственном сетевом пространстве имён с индивидуальной DNS-конфигурацией, что требует специальных механизмов для обеспечения связности. Динамичность подразумевает, что сервисы постоянно создаются и уничтожаются, IP-адреса меняются, а традиционные статические DNS-записи становятся неэффективными. Масштабирование - необходимость обработки тысяч DNS-запросов в секунду без единых точек отказа, что требует распределённых и отказоустойчивых архитектур.
В отличие от традиционных сред, где DNS-конфигурация наследуется от хоста, контейнерные платформы создают собственные DNS-экосистемы с автоматическим обнаружением сервисов, динамическим обновлением записей и сложными политиками разрешения имен. Эта сложность усугубляется необходимостью поддержки как “внутрикластерного”, так и внешнего разрешения имён, обеспечения производительности при высоких нагрузках и интеграции с существующими корпоративными DNS-инфраструктурами
Каждая контейнерная платформа — Docker, Podman, Kubernetes — реализует собственную DNS-архитектуру со специфическими особенностями, преимуществами и подводными камнями. Понимание этих различий критически важно для построения надежных и производительных контейнерных инфраструктур. С чем мы и попробуем разобраться в этой статье.
Это четвертая статья в цикле разбора механизмов разрешения имен и работы DNS. Предыдущие три можно найти по этим ссылкам:
- Как работает DNS в Linux. Часть 1: от getaddrinfo до resolv.conf
- Как работает DNS в Linux. Часть 2: все уровни DNS-кэширования
А теперь перейдем к контейнерам, где последовательно рассмотрим платформы Docker, Podman и Kubernetes.
Docker: эволюция DNS от простоты к сложности
Docker использует встроенный DNS-прокси для каждой пользовательской сети, что обеспечивает автоматическое разрешение имен контейнеров. Этот прокси работает по адресу 127.0.0.11 и выполняет две основные функции: разрешает имена контейнеров в рамках одной сети и пересылает внешние запросы на DNS-серверы, настроенные в daemon.json или resolv.conf хоста.
Архитектура DNS в rootful режиме
В классическом rootful режиме Docker создает стандартную конфигурацию DNS для контейнеров:
# Типичный /etc/resolv.conf в контейнере
nameserver 127.0.0.11
options ndots:0
DNS-прокси Docker принимает запросы от контейнеров и обрабатывает их следующим образом:
внутренние имена: разрешает имена контейнеров и сервисов в рамках пользовательских сетей Docker
внешние имена: пересылает запросы на DNS-серверы, указанные в конфигурации демона или хостовом resolv.conf
область действия: работает во всех типах сетей Docker, включая bridge-сеть по умолчанию, но с разной функциональностью:
В пользовательских сетях предоставляет встроенное разрешение имен контейнеров
В default bridge-сети автоматическое разрешение имен контейнеров НЕ работает; доступен только устаревший механизм
--link, который добавляет записи в/etc/hosts
Глобальные настройки Docker можно задать в /etc/docker/daemon.json:
{
"dns": ["<dns1>", "<dns2>"],
"dns-opts": ["use-vc", "rotate"],
"dns-search": ["example.com"]
}
Особенности rootless режима
Rootless Docker кардинально меняет сетевую архитектуру. Вместо прямого доступа к сетевому стеку хоста используется user namespace с изолированной сетевой средой. Основные отличия включают:
Сетевой стек: используется slirp4netns или RootlessKit для эмуляции сетевого стека в пользовательском пространстве.
DNS-конфигурация: контейнеры получают DNS-сервер 10.0.2.3 вместо традиционного 127.0.0.11.
```bash
# В rootless контейнере
nameserver 10.0.2.3
```
Проблемы производительности: rootless режим показывает значительно худшую сетевую производительность из-за накладных расходов на трансляцию пакетов.
Проброс source IP: по умолчанию source IP адреса не передаются корректно, что критично для сетевых сервисов вроде DNS или прокси. Для решения требуется специальная конфигурация:
```bash
# В ~/.config/systemd/user/docker.service.d/override.conf
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns"
```
Известные проблемы Docker DNS
Конфликт с systemd-resolved: автоматическая подстановка 127.0.0.53 может нарушить работу DNS в контейнерах.
Решение: Настройка /etc/docker/daemon.json с явными DNS-серверами:
{
"dns": ["<dns1>", "<dns2>"],
"dns-opts": [],
"dns-search": []
}
Проблемы с VPN: DNS-запросы могут не проходить через VPN-туннель, что приводит к утечкам DNS.
Решение: Принудительная маршрутизация DNS через VPN:
# Использование VPN DNS-серверов
docker run --dns 10.8.0.1 --dns-search vpn.local myimage
# Или также глобально в daemon.json для всех контейнеров
{
"dns": ["10.8.0.1"] # IP DNS-сервера в VPN сети
}
Устаревшие копии resolv.conf: изменения хостового файла не влияют на запущенные контейнеры до их перезапуска.
https://github.com/moby/moby/issues/23910
# Вариант 1: Перезапуск контейнеров после изменения хостового DNS
docker restart $(docker ps -q)
# Вариант 2: Монтирование resolv.conf как volume (обновления в реальном времени)
docker run -v /etc/resolv.conf:/etc/resolv.conf:ro myimage
# Вариант 3: Использование --dns флага с явными серверами, или также указанием в daemon.json
Podman: от CNI к современному Netavark
Podman представляет наиболее динамичную эволюцию DNS-архитектур в контейнерном мире, совершив переход от устаревшего CNI к современному решению Netavark/aardvark-dns. Эта трансформация отражает общую тенденцию индустрии к более производительным и функциональным DNS-решениям.
Архитектура CNI (Legacy режим)
До версии 4.0 Podman использовал CNI (Container Network Interface) с плагином dnsname для разрешения имен контейнеров. Эта архитектура включала:
dnsmasq как DNS-сервер: для каждой CNI-сети создавался отдельный экземпляр dnsmasq
файловое хранилище записей: DNS-записи хранились в файлах в директории
/run/containers/cni/dnsnameили$XDG_RUNTIME_DIR/containers/cni/dnsnameограниченную функциональность: поддерживалось только базовое разрешение A-записей без PTR и других типов записей
Конфигурация CNI сети с dnsname выглядела следующим образом:
{
"cniVersion": "0.4.0",
"name": "cni-bridge-network",
"plugins": [
{
"type": "bridge",
"bridge": "cni0"
},
{
"type": "dnsname",
"domainName": "foobar.com",
"capabilities": {
"aliases": true
}
}
]
}
Максимально подробн�� про работу Podman с бэкендом CNI описано в этой статье на Хабре.
Основными недостатками CNI подхода были низкая производительность dnsmasq при высоких нагрузках, отсутствие поддержки современных DNS-функций, сложность конфигурации и обслуживания и ограниченная интеграция с современными контейнерными оркестраторами.
Переход к Netavark и aardvark-dns
Начиная с Podman 4.0 по умолчанию используется новый сетевой стек Netavark с DNS-сервером aardvark-dns. Это революционное изменение принесло множество улучшений:
Aardvark-dns как авторитетный сервер: написанный на Rust авторитетный DNS-сервер для A/AAAA записей контейнеров
поддержка PTR-записей: автоматическое создание обратных DNS-записей для упрощения диагностики
улучшенная производительность: значительно более высокая производительность по сравнению с dnsmasq
лучшая поддержка IPv6: особенно в области NAT и port forwarding
Типичная конфигурация Netavark сети:
{
"name": "mynetwork",
"id": "3977b0c90383b8460b75547576dba6ebcf67e815f0ed0c4b614af5cb329ebb83",
"driver": "bridge",
"network_interface": "podman1",
"created": "2022-09-06T12:08:12.853219229Z",
"subnets": [{
"subnet": "10.89.0.0/24",
"gateway": "10.89.0.1"
}],
"ipv6_enabled": false,
"internal": false,
"dns_enabled": true,
"ipam_options": {
"driver": "host-local"
}
}
В отличие от CNI, Netavark предоставляет нативную интеграцию с container runtime, автоматическое управление DNS-записями при создании и удалении контейнеров и современные возможности мониторинга и отладки.
# Проверить используемый сетевой бэкенд
podman info --format '{{.Host.NetworkBackend}}'
DNS в rootless Podman
Rootless режим Podman формирует особые требования для DNS-архитектуры, поскольку отсутствуют привилегии для создания полноценных bridge-сетей.
slirp4netns: традиционный rootless networking
В классическом rootless режиме с slirp4netns Podman создаёт изолированную сетевую среду:
# DNS в rootless контейнере (slirp4netns)
nameserver 10.0.2.3
options edns0 trust-ad
search
Архитектура DNS в slirp4netns:
• DNS-сервер 10.0.2.3 — встроенный DNS-прокси slirp4netns
• Автоматическая трансляция DNS-запросов через user-mode NAT
• Изолированное пространство имён с собственным routing table
• Предсказуемая, но ограниченная сетевая конфигурация
Ключевые ограничения slirp4netns:
• Невозможность использования Netavark в полном объёме из-за отсутствия привилегий
• Дополнительный overhead на трансляцию пакетов в user-space
• Проблемы с разрешением локальных имён хоста
• Ограниченная поддержка IPv6 DNS-запросов
• Производительность значительно хуже native networking
Революция с pasta/passt: новый стандарт rootless DNS
Начиная с Podman 5.3, pasta/passt становится стандартным сетевым бэкендом для новых установок во многих дистрибутивах, вытесняя slirp4netns, кардинально изменяя подход к DNS.
# DNS в rootless контейнере (pasta/passt)
nameserver 192.168.1.1 # Реальный DNS хоста
nameserver <dns1> # Upstream DNS с хоста
search home.local # Search domains с хоста
options edns0 trust-ad
Pasta (Pack A Subtle Tap Abstraction) работает на основе passt (Plug A Simple Socket Transport) — современного сетевого драйвера, который обеспечивает “quasi-native” сетевую связность для виртуальных машин и контейнеров в пользовательском режиме без требования привилегий.
Ключевое отличие от slirp4netns — pasta не использует Network Address Translation (NAT) по умолчанию и копирует IP-адреса с основного интерфейса хоста в namespace контейнера.
Translation layer architecture: pasta реализует слой трансляции между виртуальным Layer-2 сетевым интерфейсом и нативными Layer-4 сокетами (TCP, UDP, ICMP) на хосте. Это создаёт иллюзию, что процессы приложений в контейнере выполняются на локальном хосте с сетевой точки зрения.
Встроенные сетевые сервисы: pasta включает собственные реализации ARP, DHCP, NDP, и DHCPv6, предоставляющие контейнеру сетевую конфигурацию, максимально близкую к нативной конфигурации хоста.
Архитектурные улучшения:
Использует IP-адрес хоста вместо предопределённого container IP (10.0.2.x)
Использует имя сетевого интерфейса с хоста вместо стандартного
tap0Использует gateway адрес с хоста вместо собственного gateway с
NAT
Ключевые преимущества pasta для DNS:
Прямое наследование DNS-конфигурации: pasta копирует /etc/resolv.conf хоста в контейнер, обеспечивая идентичную DNS-конфигурацию. Это кардинально отличается от slirp4netns, который использует собственный DNS-прокси.
Встроенные DNS-сервисы: pasta включает собственные реализации:
DHCP-сервер для автоматической настройки DNS
DNS forwarder для эффективной пересылки запросов
ARP resolver для разрешения локальных имён
NDP (IPv6) для modern dual-stack environments
Quasi-native DNS resolution: pasta имитирует выполнение DNS-запросов напрямую на хосте, устраняя промежуточные proxy layers.
Управление DNS в Netavark
Netavark предоставляет современные возможности управления DNS, которые по-разному взаимодействуют с rootless сетевыми бэкендами.
В rootful режиме (полная функциональность Netavark)
# Создание сети с кастомными DNS-настройками
podman network create --driver bridge \
--dns <dns2> \
--dns <dns1> \
--dns-search company.local \
custom-dns-net
# Динамическое обновление DNS для существующей сети
podman network update custom-dns-net --dns-add 9.9.9.9
podman network update custom-dns-net --dns-search-add internal.local
# Доступ к aardvark-dns с хоста
nslookup webapp.dns.podman 10.89.0.1
В rootless режиме с slirp4netns
slirp4netns не поддерживает полную функциональность Netavark. DNS-настройки ограничены:
• Невозможность создания кастомных bridge-сетей с DNS-настройками
• Aardvark-dns недоступен из-за изоляции user namespace
• DNS-конфигурация определяется исключительно slirp4netns
# Ограниченные возможности в slirp4netns режиме
podman run --dns <dns1> --dns-search company.local alpine
# DNS настройки применяются к /etc/resolv.conf, но без aardvark-dns
В rootless режиме с pasta/passt
Pasta обеспечивает расширенную совместимость с Netavark:
• Поддержка кастомных DNS-настроек через pasta options
• Частичная поддержка network management команд
• Автоматическая интеграция с хостовой DNS-конфигурацией
# Эмуляция slirp4netns поведения в pasta
podman run --network pasta:-a,10.0.2.0,-n,24,-g,10.0.2.2,--dns-forward,10.0.2.3 alpine
# Кастомизация DNS в pasta режиме
podman run --dns <dns2> --dns-search internal.local \
--network pasta:--map-guest-addr=172.16.1.100 alpine
Известные проблемы Podman DNS
Aardvark-DNS не может разрешить имена
Сбои разрешения имен в Podman 4.x с Netavark/aardvark-dns.
https://access.redhat.com/solutions/7094253
Решается обновлением до последней версии и перенастройкой сетей.
Долгие задержки при разрешении DNS между контейнерами
DNS-запросы между peer pods зависали на длительное время в версиях aardvark-dns 1.1.x-1.5.x.
https://github.com/containers/podman/issues/15972
Исправлено в версиях 1.6+
DNS resolution по умолчанию использует 8.8.8.8 в rootful режиме
Podman rootful CNI DNS resolution неправильно настраивал DNS-серверы по умолчанию.
https://github.com/containers/podman/issues/10570
Решено в GitHub Issue containers/podman#10570
DNS настройки игнорируются в podman run
DNS параметры, заданные в podman run, не применялись к /etc/resolv.conf в ранних версиях Netavark.
https://github.com/containers/netavark/issues/855
Исправлено в версиях aardvark-dns 1.6.0+ и netavark 1.6.0+
Podman демонстрирует наиболее активную эволюцию DNS-архитектур среди контейнерных платформ, с успешным переходом от CNI к Netavark в rootful режиме и революционным внедрением pasta/passt для rootless containers. Большинство критических DNS-проблем решены в последних версиях, что делает Podman привлекательной альтернативой Docker для production deployment с хорошей производительностью DNS и расширенными возможностями управления.

Kubernetes: сложность корпоративного DNS
Kubernetes представляет наиболее сложную и функциона��ьную DNS-архитектуру среди контейнерных платформ. Центральным компонентом является CoreDNS — модульный DNS-сервер, обслуживающий домены *.cluster.local и пересылающий остальные запросы на внешние DNS-серверы.
Базовая архитектура CoreDNS
CoreDNS развертывается как Deployment в namespace kube-system и доступен через Service с именем kube-dns:
# Типичная DNS-конфигурация в поде
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
IP-адрес 10.96.0.10 соответствует ClusterIP сервиса kube-dns:
$ kubectl get svc -n kube-system -l k8s-app=kube-dns
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP
CoreDNS настраивается через ConfigMap с Corefile — конфигурационным файлом, определяющим поведение DNS:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . <dns1> <dns2> {
except cluster.local in-addr.arpa ip6.arpa
}
cache 30
loop
reload
loadbalance
}
Основные плагины CoreDNS:
kubernetes: обрабатывает запросы для cluster.local
forward: пересылает внешние запросы на upstream DNS
cache: кэширует ответы на 30 секунд
health: предоставляет health checks на порту 8080
prometheus: экспортирует метрики на порту 9153
Kubernetes поддерживает несколько DNS Policy для управления разрешением имен в подах. Политики - это параметр конфигурации, который определяет, откуда и как поды получают настройки DNS для разрешения имен. Это критически важная настройка, влияющая на способность подов обращаться как к кластерным сервисам, так и к внешним ресурсам.
ClusterFirst (по умолчанию): использует кластерный DNS (CoreDNS).
ClusterFirstWithHostNet: комбинирует кластерный DNS с hostNetwork.
Default: наследует DNS-конфигурацию хоста.
None: требует ручной настройки DNS.
Пример пода с ручной настройкой DNS для dnsPolicy: None:
spec:
dnsPolicy: "None"
dnsConfig:
nameservers:
- <dns1>
- <dns2>
searches:
- ns1.svc.cluster.local
- my.dns.search.suffix
options:
- name: ndots
value: "2"
- name: edns0
Диагностика DNS проблем в Kubernetes
Kubernetes предоставляет специальные инструменты для диагностики DNS:
# Развертывание диагностического пода
kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
# Создаёт pod 'dnsutils' с nslookup, dig, host и другими DNS-утилитами
# Тестирование разрешения кластерных имен
kubectl exec -i -t dnsutils -- nslookup kubernetes.default
# Должен вернуть ClusterIP сервиса kubernetes (обычно 10.96.0.1)
# Если не работает — проблема с CoreDNS или kube-dns Service
# Проверка внешних имен
kubectl exec -i -t dnsutils -- nslookup google.com
# Проверяет способность CoreDNS пересылать запросы на внешние DNS
# Если не работает — проблема с upstream DNS или network policies
Типичные ошибки, известные проблемы и решения
SERVFAIL: CoreDNS недоступен или перегружен — проверить статус подов CoreDNS.
# определить DNS-компоненты
kubectl get pods -n kube-system -l k8s-app=coredns
kubectl get pods -n kube-system -l k8s-app=kube-dns
# проверить статус сервиса DNS
kubectl get svc -n kube-system -l k8s-app=kube-dns
kubectl get svc -n kube-system -l k8s-app=coredns
# Проверка логов
kubectl logs -n kube-system -l k8s-app=coredns
NXDOMAIN: неполные или устаревшие DNS-записи — проверить конфигурацию сервисов.
kubectl get endpoints <service-name> -n <namespace>
kubectl describe service <service-name> -n <namespace>
kubectl get pods -n <namespace> -l <selector-from-service>
Медленные ответы: возможно это проблемы с ndots или перегрузка CoreDNS.
# Измерить время DNS-запроса
kubectl exec dnsutils -- sh -c "time nslookup google.com" 2>&1
# Проверить настройки resolv.conf (ndots)
kubectl exec dnsutils -- cat /etc/resolv.conf
Поды с hostNetwork: true используют сетевое пространство имен хоста, что приводит к проблемам с DNS.
Суть проблемы: под не может разрешать кластерные сервисы, так как использует хостовую DNS-конфигурацию.
Решение: использование dnsPolicy: ClusterFirstWithHostNet:
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
Альтернативное решение - iptables правила для перенаправления трафика:
# Перенаправление DNS-трафика на ClusterIP
iptables -t nat -A OUTPUT -p tcp --dport 53 -d external-ip \
-j DNAT --to-destination cluster-ip:53
Одна из ключевых проблем Kubernetes DNS — параметр ndots:5, который заставляет резолвер проверять неполные имена (содержащие меньше чем 5 точек) сначала среди внутренних доменов кластера, и только потом делать запрос на внешний DNS:
# При запросе www.google.com с ndots:5 происходят попытки:
www.google.com.default.svc.cluster.local
www.google.com.svc.cluster.local
www.google.com.cluster.local
www.google.com. # только потом прямой запрос
Это приводит к множественным DNS-запросам и значительным задержкам.
Решения включают:
Использование FQDN с точкой: www.google.com. для пропуска поисковых доменов.
Настройка ndots для отдельных подов:
spec:
dnsConfig:
options:
- name: ndots
value: "1"
Оптимизация CoreDNS для улучшения производительности и отказоустойчивости
CoreDNS в Kubernetes часто становится узким местом при большом количестве сервисов и внешних DNS-запросов. Понимание тонкостей настройки CoreDNS становится критически важным для поддержания стабильности production кластеров.
Кэширование
По умолчанию плагин cache установлен на 30 секунд. Для крупных кластеров можно увеличить TTL и размеры кэша:
cache {
success 10000 60 # до 10k успешных ответов, TTL 60s
denial 10000 15 # NXDOMAIN до 10k, TTL 15s
}
Success cache: увеличение до 60-120 секунд снижает нагрузку на upstream на 70-80%
Denial cache: NXDOMAIN должны кэшироваться меньше (10-15 секунд)
Prefetch mechanism: автоматическое обновление записей за 10% до истечения TTL.
Политика форвардинга
В плагине forward можно выбирать стратегию обращения к upstream DNS:
random — распределяет запросы равномерно по серверам (улучшает балансировку);
sequential — всегда опрашивает сервера в порядке списка (по умолчанию).
Для кластеров с несколькими внешними DNS рекомендуется использовать random:
forward . <dns1> <dns2> {
policy random
}
Протокольная оптимизация
Директива prefer_udp снижает overhead при большом числе коротких запросов.
forward . <dns1> <dns2> {
prefer_udp
max_concurrent 1000
}
Указание force_tcp может быть полезно, если есть проблемы с фрагментацией UDP пакетов (часто в облаках и VPN).
Масштабирование
Горизонтальное масштабирование CoreDNS — не опция, а необходимость для production кластеров. Типичная конфигурация с 1-2 репликами совершенно неадекватна при нагрузке в десятки тысяч DNS-запросов в секунду. Каждая реплика CoreDNS способна обрабатывать 5000-10000 QPS до деградации производительности, а в кластере на 100+ нод и 1000+ подов пиковая нагрузка легко достигает 50000-100000 QPS, особенно во время:
Массовых deployments, когда сотни новых подов одновременно начинают разрешать DNS-имена сервисов
Rolling updates приложений, создающих временные пики DNS-активности
Автомасштабирования приложений на основе HPA
Startup burst — когда приложения делают множество DNS-запросов при инициализации
Недостаточное количество CoreDNS реплик приводит к:
Высокой латентности DNS (>100ms вместо <10ms)
Timeouts и SERVFAIL ответам
Перегрузке CPU и memory на CoreDNS подах
Каскадным отказам приложений, которые не могут обнаружить зависимые сервисы
Ручное масштабирование CoreDNS
Простейший способ увеличить количество реплик CoreDNS:Критически важно распределить CoreDNS реплики по разным нодам для обеспечения отказоустойчивости. Если все реплики CoreDNS находятся на одной ноде, ее отказ приведет к полному DNS outage.
# Anti-affinity для распределения по нодам
kubectl patch deployment coredns -n kube-system -p '
{
"spec": {
"template": {
"spec": {
"affinity": {
"podAntiAffinity": {
"preferredDuringSchedulingIgnoredDuringExecution": [{
"weight": 100,
"podAffinityTerm": {
"labelSelector": {
"matchLabels": {"k8s-app": "kube-dns"}
},
"topologyKey": "kubernetes.io/hostname"
}
}]
}
}
}
}
}
}'
При масштабировании критически важно настроить PodDisruptionBudget для предотвращения одновременного удаления слишком многих CoreDNS реплик.
NodeLocal DNSCache: современное решение
NodeLocal DNSCache представляет современный подход к оптимизации DNS в Kubernetes. Это DaemonSet, который запускает DNS-кэш на каждой ноде кластера.
Преимущества NodeLocal DNSCache:
Снижение среднего времени DNS-разрешения (Поды обращаются к локальному кэшу на той же ноде вместо прохождения через kube-dns Service)
Устранение conntrack записей для DNS-соединений (Прямое обращение к локальному кэшу избегает iptables DNAT правил и connection tracking)
Прямое обращение к Cloud DNS, минуя kube-dns для внешних запросов (Это снижает нагрузку на центральный CoreDNS и улучшает латентность.)
Автоматическое наследование stub domains и upstream nameservers
Архитектура: поды обращаются к DNS-кэшу на той же ноде, избегая iptables DNAT правил и connection tracking.
Конфигурация NodeLocal DNSCache:
apiVersion: v1
kind: ConfigMap
metadata:
name: node-local-dns
namespace: kube-system
data:
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30
denial 9984 5
}
reload
loop
bind 169.254.20.25 10.96.0.10
forward . __PILLAR__CLUSTER__DNS__ {
force_tcp
}
prometheus :9253
health 169.254.20.25:8080
}
NodeLocal DNSCache работает на специальном link-local IP-адресе 169.254.20.25 на каждой ноде. Поды автоматически настраиваются для использования этого адреса как primary nameserver.

Кастомизация для корпоративных сред
Корпоративные окружения предъявляют особые требования к DNS-инфраструктуре: интеграция с существующими системами разрешения имён, разделение внутренних и внешних зон, соблюдение политик безопасности и compliance требований. CoreDNS предоставляет гибкие механи��мы для реализации этих требований через stub domains, split-horizon DNS, network policies и encrypted DNS.
CoreDNS поддерживает гибкую настройку upstream серверов и stub domains для интеграции с корпоративными DNS-инфраструктурами:
# Конфигурация для корпоративного DNS
consul.local:53 {
errors
cache 30
forward . 10.150.0.1
}
# Принудительное использование конкретного upstream
forward . 172.16.0.1 # вместо /etc/resolv.conf
Split-horizon DNS: различные ответы для внутренних и внешних запросов:
# Пример split-brain конфигурации в CoreDNS
internal.company.com:53 {
hosts {
192.168.1.10 api.internal.company.com
fallthrough
}
forward . 192.168.1.1 # внутренний DNS
}
external.company.com:53 {
hosts {
203.0.113.10 api.external.company.com
fallthrough
}
forward . <dns1> # внешний DNS
}
Ограничение доступа к DNS-серверам: использование network policies.
Kubernetes Network Policies позволяют реализовать fine-grained контроль доступа к CoreDNS, ограничивая, какие поды могут выполнять DNS-запросы и откуда CoreDNS может получать запросы.
Пример базовой NetworkPolicy для защиты CoreDNS:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
meta
name: coredns-network-policy
namespace: kube-system
spec:
podSelector:
matchLabels:
k8s-app: kube-dns
policyTypes:
- Ingress
ingress:
# Разрешить DNS-запросы от всех подов в кластере
- from:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Разрешить health-checks (для liveness/readiness проб)
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 8080 # health
- protocol: TCP
port: 8181 # ready
# Разрешить Prometheus метрики от мониторинга
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9153
Мониторинг и логирование DNS
Эффективный мониторинг CoreDNS критически важен для обеспечения стабильности всего Kubernetes кластера. Проблемы с DNS могут привести к каскадным отказам, когда сервисы не могут обнаруживать друг друга, что делает систему мониторинга первой линией защиты от серьезных инцидентов.
CoreDNS предоставляет богатые возможности мониторинга:
Prometheus метрики: доступны на порту 9153 для каждого пода CoreDNS.
Ключевые метрики включают:
- Время ответа DNS
- Процент успешных запросов
- Cache hit ratio
- Количество upstream запросов
Логирование запросов:
добавление плагина log в Corefile для детального логирования:
Corefile: |
.:53 {
log # добавить для логирования всех запросов
errors
# остальная конфигурация
}
Health checks и автоматическое восстановление
CoreDNS предоставляет два endpoint для health checking:
Health endpoint (/health:8080)
# пример liveness probe
livenessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
Ready endpoint (/ready:8181)
# пример readiness probe
readinessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
Интеграция с облачными платформами
Kubernetes DNS-архитектура в production среде редко существует изолированно. Интеграция с облачными DNS-сервисами, системами автоматического управления записями и service mesh решениями создаёт комплексную экосистему, обеспечивающую высокую доступность, безопасность и автоматизацию DNS-управления.
Cloud DNS интеграция
Использование управляемых DNS-сервисов облачных провайдеров. Google Cloud DNS, Amazon Route 53 и Azure DNS предоставляют высокодоступные и масштабируемые решения для внешних запросов.
External DNS
External DNS выводит управление DNS в Kubernetes на новый уровень, автоматически создавая и обновляя DNS-записи на основе Kubernetes ресурсов. Это устраняет необходимость ручного управления DNS и обеспечивает полную синхронизацию состояния кластера с внешними DNS-провайдерами.
Архитектура и принцип работы
External DNS работает как controller, который:
Мониторит Kubernetes ресурсы (Service, Ingress)
Извлекает DNS-аннотации из ресурсов
Синхронизирует записи с внешним DNS-провайдером через API
Поддерживает актуальность записей при изменениях
Service mesh интеграция
Istio использует Envoy proxies для перехвата всего трафика, включая DNS-запросы. В такой архитектуре DNS становится частью service mesh control plane.
Архитектура Istio DNS:
Sidecar Envoy перехватывает DNS-запросы от приложений
Pilot предоставляет service registry через xDS API
DNS proxy в Envoy разрешает имена на основе Istio service registry
Внешние домены по-прежнему разрешаются через CoreDNS
Практические рекомендации и выводы
Рекомендации по платформам
Если вы используете Docker — обратите внимание на различия между rootful и rootless режимами.
В rootful режиме
мониторьте стабильность DNS-прокси 127.0.0.11
настройте альтернативные DNS-серверы в daemon.json
при использовании systemd-resolved создайте симлинк на
/run/systemd/resolve/resolv.confвместоstub-resolver
В rootless режиме
учитывайте ограничения производительности из-за slirp4netns
учитывайте, что DNS-сервер 10.0.2.3 является частью изолированного сетевого стека
Если переходите на современный Podman
мигрируйте с CNI на Netavark/aardvark-dns для улучшения производительности.
Используйте возможности динамического управления DNS через
podman network update.
В rootless режиме
учитывайте ограничения slirp4netns
держите в голове, что Podman 5.3+ использует pasta по умолчанию, но при проблемах с pasta можно вернуться к slirp4netns через
containers.conf
Если используете Kubernetes
обязательно рассмотрите внедрение NodeLocal DNSCache для снижения задержек.
оптимизируйте ndots для приложений, делающих много внешних запросов.
настройте правильную dnsPolicy для подов с hostNetwork.
мониторьте производительность CoreDNS и планируйте масштабирование
Заключение
DNS в контейнерных средах представляет собой многослойную архитектуру со значительными различиями между платформами. Docker обеспечивает простоту использования с встроенным DNS-прокси, но требует особого внимания в rootless режиме. Podman демонстрирует активную эволюцию от устаревшего CNI к современному Netavark с aardvark-dns, обеспечивая лучшую производительность и функциональность. Kubernetes предлагает наиболее сложную и мощную DNS-систему с CoreDNS, но требует глубокого понимания особенностей конфигурации и оптимизации.
Контейнерные DNS-архитектуры представляют собой быстро развивающуюся область с постоянными улучшениями производительности, безопасности и функциональности. Понимание особенностей каждой платформы и применение современных практик обеспечивает надежную и масштабируемую DNS-инфраструктуру для контейнерных приложений. Инвестиции в правильную архитектуру DNS окупаются через улучшение производительности приложений, снижение операционных затрат и повышение общей надежности системы.