Kubernetes 1.11: мигрируем с kube-dns на CoreDNS и настраиваем split-horizon
Обновляемся до Kubernetes 1.11: CoreDNS становится DNS по умолчанию. Разбираем миграцию с kube-dns и настройку split-horizon DNS для корпоративной среды через Corefile.
Kubernetes 1.11 - CoreDNS становится DNS-сервисом по умолчанию вместо kube-dns
Kubernetes 1.11 вышел на прошлой неделе, и главная новость которая непосредственно касается каждого кластера - CoreDNS становится DNS-сервисом по умолчанию. kube-dns никуда не делся и продолжает поддерживаться, но новые кластеры поднятые через kubeadm теперь получают CoreDNS из коробки. Мы обновили несколько managed-кластеров и параллельно мигрировали часть из них с kube-dns - вот что получилось.
Почему меняют DNS
kube-dns - это три контейнера в одном Pod: kubedns, dnsmasq и sidecar для мониторинга. Конфигурировать его было неудобно: кастомные настройки пробрасывались через ConfigMap в довольно ограниченном формате, любая нетривиальная логика (форвардинг конкретных доменов, особые TTL, split-horizon) требовала либо патчить dnsmasq-аргументы, либо городить отдельный Pod рядом.
CoreDNS - это один бинарник с цепочкой плагинов. Конфигурируется через Corefile - простой текстовый формат где каждый блок описывает зону и набор плагинов для неё. Хочешь форвардить .corp.example.com на внутренний резолвер - один блок. Хочешь кешировать с другим TTL - один параметр. Хочешь добавить кастомные A-записи без перезапуска - есть плагин hosts. Поддерживается Prometheus-метрики нативно, без отдельного sidecar.
Архитектурно это шаг в сторону предсказуемости: вместо трёх процессов с разными жизненными циклами - один, который легко читать и отлаживать.
Что происходит при обновлении до 1.11
Если кластер уже работает с kube-dns - обновление само по себе ничего не меняет. kube-dns продолжает работать, поды его используют. CoreDNS становится дефолтом только для новых кластеров создаваемых через kubeadm.
Для явной миграции на существующем кластере нужно:
- Развернуть CoreDNS - создать Deployment, ConfigMap с Corefile и Service (в kubeadm 1.11 это делает
kubeadm upgradeс флагом, либо вручную по официальным манифестам). - Переключить Service - CoreDNS должен забрать тот же ClusterIP что раньше был у kube-dns, иначе менять DHCP на всех нодах и пересоздавать поды.
- Убрать kube-dns - после того как убедились что CoreDNS резолвит корректно.
Переключение ClusterIP - самое щекотливое место: Service нельзя просто переименовать, нужно удалить старый и создать новый с тем же адресом. Это несколько секунд недоступности DNS в кластере. Мы делали это в часы минимальной нагрузки, и ничего критичного не произошло, но стресс есть стресс.
Split-horizon DNS: зачем и как
У нескольких клиентов есть требование которое с kube-dns решалось костыльно: поды в кластере должны резолвить корпоративные домены через внутренний DNS-сервер компании, а не через внешние резолверы. При этом cluster.local и служебные домены Kubernetes должны резолвиться как обычно - через CoreDNS. Внешние домены - через внешний DNS.
Это называют split-horizon или split-brain DNS. С CoreDNS конфигурируется в Corefile элегантно:
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
proxy corp.example.com 10.0.0.5
proxy . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
Здесь proxy corp.example.com 10.0.0.5 говорит CoreDNS: всё что заканчивается на corp.example.com форвардировать на корпоративный DNS 10.0.0.5. Всё остальное - по resolv.conf ноды. Kubernetes-домены обрабатываются плагином kubernetes в первую очередь.
С kube-dns примерно то же самое достигалось через stubDomains в ConfigMap, но синтаксис был менее явным и отлаживать было неудобно - смотришь в аргументы dnsmasq и гадаешь почему конкретный домен резолвится не туда.
Что мы поймали при миграции
Пара наблюдений из реальной практики.
Плагин loop спасает от петель. CoreDNS по умолчанию включает детектор петель маршрутизации DNS. Если /etc/resolv.conf на ноде случайно указывает на сам CoreDNS (такое бывает когда кластерный DNS прописывается в системный resolv), CoreDNS это замечает и падает с понятной ошибкой. kube-dns в такой ситуации просто зависал. Поначалу испугались - конечно лучше чем тихое зависание.
Метрики из коробки. У kube-dns Prometheus-экспортер был в sidecar и иногда рассинхронизировался. CoreDNS отдаёт метрики на :9153 сам, без дополнительных контейнеров. Подключили к существующему стеку мониторинга за пять минут.
ConfigMap перечитывается без перезапуска. Плагин reload в Corefile позволяет менять конфигурацию на ходу - CoreDNS следит за изменениями ConfigMap и перечитывает Corefile. Удобно когда нужно добавить новый корпоративный домен во время работы.
Старые поды кешируют старый DNS. При переключении ClusterIP длинноживущие поды несколько минут продолжают резолвить через старый адрес - до истечения DNS-кеша. В нашем случае всё само выровнялось за пару минут, но при планировании это стоит держать в голове.
Где мы сейчас
На обновлённых до 1.11 кластерах CoreDNS работает неделю - стабильно. Split-horizon для нескольких клиентских доменов работает через proxy-директивы. Конфигурация читается и понимается с первого взгляда, что само по себе уже ценность.
Клиентам которые ещё на 1.10 с kube-dns - переходить не срочно, но при следующем плановом обновлении кластера мы будем сразу ставить CoreDNS. Дополнительной возни немного, а возможности для настройки заметно шире.