MAATRIX / Блог / Плагины вместо зон-файлов: что меняется при переходе с BIND9 на CoreDNS

Плагины вместо зон-файлов: что меняется при переходе с BIND9 на CoreDNS

MAATRIX

Если у вас уже стоит BIND9 и он работает годами без нареканий, повод для миграции на CoreDNS обычно один — вы либо разворачиваете Kubernetes и получаете CoreDNS «в комплекте», либо устали вручную редактировать зона-файлы под динамическую инфраструктуру, где серверы появляются и исчезают за минуты. CoreDNS решает эту задачу иначе, чем BIND9, — но не бесплатно: часть многолетней экосистемы вокруг BIND придётся либо заменить самостоятельно, либо просто прожить без неё. Разберём по пунктам, что вы получаете и что теряете.

Разная философия: текстовые зоны против модульных плагинов на Go

BIND9 (Berkeley Internet Name Domain) — сервер с историей на десятилетия, построенный вокруг идеи авторитетной зоны как текстового файла в формате RFC 1035: записи A, MX, CNAME, TXT перечислены построчно, файл читается и парсится демоном named, изменения применяются через rndc reload или инкрементально через журнал (.jnl). Вся логика — резолвинг, кэш, авторитетная отдача, DNSSEC-подпись — реализована внутри одного монолитного бинарника на C, поведение которого настраивается директивами named.conf.

CoreDNS устроен принципиально иначе. Это не сервер с фиксированным набором функций, а рантайм на Go, который сам по себе ничего не делает — вся логика собрана из цепочки плагинов, перечисленных в конфигурационном файле Corefile. Хотите отдавать зону из файла — подключаете плагин file. Нужен кэш — добавляете cache. Нужна интеграция с Kubernetes API — плагин kubernetes. Каждый плагин обрабатывает DNS-запрос по очереди в порядке объявления и либо отвечает сам, либо передаёт запрос дальше по цепочке. Это архитектура middleware, знакомая по веб-фреймворкам (Caddy, из проекта которого CoreDNS вырос, устроен точно так же), а не классическая модель DNS-сервера.

Разница не косметическая. В BIND9 вы настраиваете уже готовый набор возможностей — они либо есть, либо их нет. В CoreDNS набор возможностей — то, что вы сами собрали из плагинов на этапе компиляции или выбора готовой сборки. Официальный бинарник включает не все существующие плагины, а только те, что перечислены в plugin.cfg — если нужен нестандартный плагин, придётся пересобирать CoreDNS из исходников со своим списком, обычной установкой пакета это не решается.

От named.conf к Corefile: как выглядит конфигурация на практике

Классический фрагмент named.conf для авторитетной зоны с разрешёнными трансферами на вторичный сервер:

zone "example.com" {
    type master;
    file "/etc/bind/zones/db.example.com";
    allow-transfer { 203.0.113.10; };
    also-notify { 203.0.113.10; };
};

Применение изменений — без остановки процесса:

named-checkzone example.com /etc/bind/zones/db.example.com
rndc reload example.com
rndc zonestatus example.com

Аналогичная по смыслу конфигурация в Corefile — авторитетная зона из файла плюс отдельный блок для рекурсивного форвардинга остального трафика:

example.com:53 {
    file /etc/coredns/zones/db.example.com
    log
    errors
    prometheus :9153
}

. {
    forward . 1.1.1.1 8.8.8.8 {
        max_concurrent 1000
    }
    cache 300
    log
    errors
}

Формат самого файла зоны в плагине file — стандартный RFC 1035, тот же синтаксис, что и в BIND9, так что готовые db.example.com переносятся почти без изменений. Ключевое отличие в применении конфигурации: у CoreDNS нет команды, аналогичной rndc reload. Штатно процесс перечитывает Corefile только при рестарте. Если добавить плагин reload, он периодически (по умолчанию раз в 30 секунд) сверяет хэш файла конфигурации и перезапускает внутренний обработчик запросов сам, без даунтайма — но это отложенное автоматическое действие, а не мгновенная команда по требованию администратора:

. {
    forward . 1.1.1.1
    cache 300
    reload
}

Установка бинарника — не через системный пакетный менеджер (готовых пакетов CoreDNS в репозиториях большинства дистрибутивов мало, и они быстро устаревают), а скачиванием актуального релиза с GitHub:

curl -s https://api.github.com/repos/coredns/coredns/releases/latest \
  | grep browser_download_url | grep linux_amd64

tar -xzf coredns_*_linux_amd64.tgz
sudo mv coredns /usr/local/bin/
coredns -version

Юнит для systemd, чтобы CoreDNS поднимался как обычный демон на VPS вне Kubernetes:

[Unit]
Description=CoreDNS DNS server
After=network.target

[Service]
ExecStart=/usr/local/bin/coredns -conf=/etc/coredns/Corefile
Restart=on-failure
User=coredns
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Плагины CoreDNS: что реально даёт модульная экосистема

Сила CoreDNS не в списке плагинов как таковом, а в том, что каждый решает узкую задачу и комбинируется с остальными без побочных эффектов на код, который вы не трогали. Из практически полезных для эксплуатационной работы:

  • kubernetes — резолвит DNS-имена сервисов и подов прямо из Kubernetes API, без отдельного хранилища записей. Именно поэтому CoreDNS — DNS-аддон по умолчанию в kubeadm и в большинстве managed Kubernetes уже много лет.
  • etcd — отдаёт записи из etcd в формате, совместимом с SkyDNS (проектом-предшественником CoreDNS), удобно для интеграций, где источник истины об инфраструктуре — уже etcd, а не отдельная база DNS.
  • forward — рекурсивный форвардинг с поддержкой нескольких upstream, health-check и балансировкой между ними — без отдельного резолвера рядом.
  • cache, prometheus, health, ready — кэш ответов, метрики в формате Prometheus на отдельном порту (по умолчанию 9153) и HTTP-эндпоинты для проверок живости — то, что в оркестраторе нужно из коробки для liveness/readiness проб.
  • rewrite и template — переписывание запросов и генерация ответов по шаблону без отдельного зона-файла — полезно для заглушек, редиректов и синтетических ответов на лету.
  • secondary — приём зоны по AXFR/IXFR от мастера, включая BIND9 в роли мастера, если нужен гибридный сетап на переходный период.

Порядок плагинов в Corefile — не эстетика: он определяет порядок обработки запроса, и неверный порядок (например, cache до kubernetes) реально ломает логику. Это одна из первых вещей, о которую спотыкаются, перенося в CoreDNS интуицию из линейного named.conf.

Динамическое обновление и service discovery: где CoreDNS выигрывает

Это главная причина, ради которой вообще стоит менять BIND9 на CoreDNS. У BIND9 динамическое обновление записей существует — протокол RFC 2136 через nsupdate с TSIG-аутентификацией:

key "ddns-key" {
    algorithm hmac-sha256;
    secret "BASE64ENCODEDSECRETHERE==";
};

zone "example.com" {
    type master;
    file "/etc/bind/zones/db.example.com";
    allow-update { key ddns-key; };
};
nsupdate -k ddns.key <<EOF
server ns1.example.com
zone example.com
update add app.example.com 300 A 203.0.113.55
send
EOF

Рабочий и проверенный десятилетиями механизм — но каждое изменение состояния инфраструктуры кто-то должен явно отправить как отдельную DNS-транзакцию. Если сервис перезапустился с новым IP, а обновляющий скрипт упал — запись протухнет молча.

В CoreDNS с плагином kubernetes такой синхронизации не требуется вообще — DNS-имя пода или сервиса всегда отражает текущее состояние Kubernetes API, потому что CoreDNS сам подписан на изменения через API-сервер, а не хранит отдельную копию записей, которую нужно обновлять:

.:53 {
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        fallthrough in-addr.arpa ip6.arpa
        ttl 30
    }
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
}

Для сценариев вне Kubernetes похожий эффект даёт etcd — источником записей выступает существующее хранилище состояния кластера, а не отдельно поддерживаемая зона:

etcd skydns.local {
    endpoint http://127.0.0.1:2379
    fallthrough
}
etcdctl put /skydns/local/skydns/app '{"host":"203.0.113.55","ttl":300}'

Разница по существу: BIND9 в модели RFC 2136 остаётся источником истины, который кто-то обновляет снаружи. CoreDNS в модели kubernetes/etcd — проекция чужого источника истины в DNS-протокол: как только меняется оригинал (под пересоздан, ключ в etcd переписан), меняется и ответ, без дополнительного шага. Для статичной инфраструктуры на десяток серверов это преимущество почти не ощущается. Для среды с автоскейлингом, где поды живут минутами, это решает задачу, для которой BIND9 не проектировался.

Что теряется при переходе: rndc, DNSSEC-тулинг, RPZ и десятилетия комьюнити

Здесь начинаются реальные компромиссы, которые редко упоминают в маркетинговых сравнениях.

Управляющий канал. У BIND9 есть rndc — выделенный, TSIG-защищённый протокол администрирования: перезагрузка отдельной зоны без рестарта всего процесса, просмотр статуса, заморозка зоны перед обслуживанием, включение/выключение отладочных логов на лету. У CoreDNS прямого аналога нет — управление сводится к HTTP-эндпоинтам health/ready (для оркестратора) и метрикам Prometheus (для мониторинга), а не к интерактивному административному каналу. Перечитать одну зону без рестарта всего процесса штатно нельзя.

DNSSEC. BIND9 умеет автоматизировать весь цикл подписи зоны — генерацию ключей, ротацию, инкрементальную пересобирку RRSIG через политику dnssec-policy (KASP), которая всё это делает по расписанию сама. CoreDNS такой встроенной автоматизации не имеет: если зона должна быть подписана, вы либо подписываете её внешним инструментом и отдаёте через file уже готовый подписанный набор записей, либо не используете DNSSEC на этом узле вообще. Для домена без DNSSEC-требований это не проблема, для домена с DNSSEC — ощутимая ручная работа, которую BIND9 брал на себя.

RPZ и split-horizon через views. В BIND9 Response Policy Zones — стандартный способ подменять или блокировать ответы по политике (защита от вредоносных доменов, корпоративный фильтр), а view с ACL по клиентским подсетям — стандартный способ отдавать разные ответы внутренним и внешним клиентам с одного сервера. У CoreDNS готового аналога RPZ нет; похожего поведения можно добиться комбинацией rewrite, template и отдельных серверных блоков на разных портах или интерфейсах под разные группы клиентов, но это самостоятельная инженерная задача, а не готовая директива.

Зрелость экосистемы вокруг сервера. BIND9 эксплуатируется с 1980-х (в текущем виде — с конца 90-х), и вокруг него — десятилетия runbook'ов, шаблонов мониторинга под конкретные метрики named, готовых Nagios/Zabbix-проверок. Экосистема CoreDNS моложе на порядок и теснее привязана к Kubernetes: вне контекста кластера документации и разборов инцидентов заметно меньше, а часть найденных в интернете рецептов написана под kubernetes-плагин и напрямую не переносится на автономный сервер.

Сравнение по сумме факторов:

КритерийBIND9CoreDNS
Язык реализацииCGo
Формат конфигурацииnamed.conf + зона-файлы (RFC 1035)Corefile + плагины
Динамическое обновлениеRFC 2136 (nsupdate + TSIG)через backend (kubernetes/etcd), без RFC 2136 из коробки
Управляющий каналrndchealth/ready/Prometheus, без выделенного admin-протокола
DNSSEC-автоматизацияdnssec-policy (KASP) встроеннет, зона подписывается внешним инструментом
RPZ / split-horizonштатные механизмысобирается вручную из rewrite/template/серверных блоков
Service discoveryнет встроенногонативно (kubernetes, etcd)
Метрики из коробкиstatistics-channels (XML/JSON)Prometheus-эндпоинт
Типичная среда эксплуатацииклассический сервер, standaloneKubernetes, container-native инфраструктура

Когда переход оправдан, а когда BIND9 остаётся правильным выбором

Переход логичен, если основная нагрузка — DNS внутри Kubernetes-кластера или другой динамической инфраструктуры, где записи должны отражать состояние оркестратора, а не список, который кто-то ведёт руками. Он логичен и в чисто эксплуатационном смысле — если у вас уже есть Prometheus и вы хотите единый стек метрик без отдельного парсинга statistics-channels. Держать BIND9 ради классических авторитетных зон на 20-30 доменов и одновременно поднимать CoreDNS ради Kubernetes-кластера — нормальная гибридная схема: secondary-плагин CoreDNS умеет принимать зону по AXFR от мастера на BIND9, так что оба сервера эксплуатируются параллельно, каждый в своей роли.

Оставаться на BIND9 разумно, если у вас уже настроен DNSSEC с автоматической ротацией ключей, используются RPZ для фильтрации или views для split-horizon, и переписывать это на комбинацию плагинов ради архитектурной моды нет практического смысла — работающий классический DNS-сервер не нуждается в замене только потому, что где-то рядом появился Kubernetes. Если же вы разворачиваете сервис с нуля на VPS и не завязаны на Kubernetes, а хочется современного набора метрик и Go-рантайма — здесь также стоит взвесить PowerDNS как альтернативу BIND9: у него, в отличие от CoreDNS, есть и REST API, и родная поддержка DNSSEC, и веб-интерфейс, при этом зоны хранятся не в текстовых файлах, а в базе.

Если решение — оставаться на BIND9 или мигрировать на него впервые, пошаговая установка на чистый VPS расписана в отдельном материале про настройку BIND9 на Ubuntu 24.04, а для уже работающего сервера пригодится разбор бэкапа и восстановления BIND9 — динамические зоны и DNSSEC-ключи там теряются иначе, чем статичный конфиг, и это стоит учитывать заранее, а не после сбоя.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли просто скопировать зона-файлы BIND9 в CoreDNS без изменений?

В большинстве случаев да — плагин file понимает тот же формат RFC 1035. Проверьте нестандартные директивы вроде $GENERATE и специфичные для BIND TTL-конструкции — их стоит явно протестировать через dig после переноса, а не считать перенос завершённым по факту старта процесса.

CoreDNS поддерживает зонные трансферы (AXFR) как BIND9?

Да, в роли вторичного сервера через плагин secondary — он умеет принимать зону от мастера, включая BIND9. Роль мастера с полноценным AXFR/IXFR к внешним вторичным серверам у CoreDNS ограниченнее, чем у BIND9, — для сложных схем репликации это стоит проверить на тестовом стенде под свою топологию.

Что произойдёт с DNSSEC, если зона уже подписана в BIND9 и её нужно перенести?

CoreDNS способен отдавать уже подписанную зону через file, если файл содержит актуальные RRSIG и они не просрочены. Но ротацию ключей и пересборку подписи придётся организовать отдельным внешним процессом — встроенного аналога dnssec-policy в CoreDNS нет.

Нужен ли CoreDNS, если Kubernetes не используется вообще?

Не обязательно. Вне Kubernetes CoreDNS даёт в основном современный стек метрик и модульность конфигурации — динамическое обновление и service discovery, ради которых он в первую очередь и выбирается, реализуются полноценно только с backend вроде etcd, который тоже придётся администрировать самостоятельно.

Как быстро проверить, что CoreDNS реально отвечает на запросы после установки?

Обычным dig, как и для любого другого DNS-сервера: dig @127.0.0.1 -p 53 example.com A. Плагин prometheus дополнительно даёт curl 127.0.0.1:9153/metrics — по счётчикам coredns_dns_requests_total и coredns_dns_responses_total сразу видно, доходят ли запросы до нужного серверного блока.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →