Как наша DNS выбирает серверы имён для вашей зоны
Каждая зона в Yeap DNS получает пару серверов имён. Назначение должно быть стабильным, распределять нагрузку и учитывать готовность отвечать. Как работает выбор на основе хэша и почему «статус — намерение, heartbeat — факт».
Когда вы добавляете домен в Yeap DNS, консоль показывает два сервера имён (NS), которые нужно указать у регистратора, чтобы делегировать домен нам. Шаг кажется простым, но при этом должны выполняться сразу несколько требований. В статье мы объясняем, как выбираем эти два сервера имён.
Три требования
- Стабильность. Серверы имён указываются в записях делегирования у регистратора и в реестре TLD. Если бы сегодня зона получала A и B, а завтра C и D, вам пришлось бы постоянно менять настройки регистратора, а в промежутках разрешение имён могло бы нарушаться. Для конкретной зоны результат должен быть детерминированным.
- Распределение нагрузки. Если бы все зоны получали одну пару, нагрузка сосредоточилась бы на нескольких узлах, а проблема с одним сервером имён затронула бы всех. Разным зонам должны назначаться разные комбинации.
- Реальная готовность отвечать. За выданными вам серверами имён должны стоять работающие узлы. Делегирование зоны серверу имён без узлов отправляет запросы в пустоту.
Модель пулов
Как и во многих управляемых DNS-сервисах, наша модель состоит из трёх уровней:
- Пулы: наборы серверов имён. Каждый тариф связан с пулом; бесплатные и платные тарифы используют отдельные пулы.
- Серверы имён: каждая запись в пуле — одно имя хоста NS, которое вы в итоге указываете у регистратора.
- Узлы: машины, на которых непосредственно работает авторитетный DNS-сервис. Один сервер имён может обслуживаться несколькими узлами, а его связующие записи (glue) указывают на адреса этих узлов.
Назначить серверы имён зоне — значит выбрать два сервера имён из пула, связанного с тарифом зоны.
Стабильная случайность: сортировка по хэшу с учётом имени зоны
Чтобы совместить стабильность с распределением нагрузки, мы используем классический приём, по сути представляющий собой хэширование по наибольшему случайному весу (rendezvous hashing, HRW):
- для каждого сервера имён в пуле вычисляем
hash(zoneName + ":" + nameserverId); - сортируем по этому хэшу (при совпадении — по ID, чтобы порядок всегда был детерминированным);
- берём первые два.
function pickNameservers(pool, zoneName, count = 2):
if len(pool) <= count:
return pool
sort pool by (crc32(zoneName + ":" + ns.id), ns.id)
return first count items of pool
У этого подхода есть полезные свойства:
- Детерминированность: входные данные — только имя зоны и состав пула. Сколько бы раз ни выполнялось вычисление, одна зона получает один результат, независимо от случайного состояния или нагрузки в момент назначения.
- Равномерное распределение: разные зоны получают разные, внешне случайные последовательности, поэтому в целом равномерно распределяются по комбинациям серверов имён в пуле.
- Небольшая область изменений при расширении: добавление сервера имён в пул меняет результат только для зон, у которых новый сервер попадает в первые два; для остальных зон результат сохраняется. Это главное преимущество HRW перед простым хэшированием с делением по модулю.
Обратите внимание: результат сохраняется при создании зоны. Последующие изменения пула не меняют автоматически серверы имён существующих зон, поэтому добавление мощностей не сдвигает ваше делегирование. Детерминированность особенно полезна тем, что зона, созданная любым способом (через консоль, API или автоматическое создание ресурсов после покупки тарифа), проходит через один алгоритм назначения и получает одинаковый результат.
Если имени зоны для начального значения нет (несколько редких внутренних сценариев), алгоритм выбирает серверы с наименьшим числом размещённых зон — детерминированную форму балансировки нагрузки.
Статус — намерение, heartbeat — факт
Перед сортировкой есть более важный этап: решить, какие серверы имён вообще могут попасть в список кандидатов. Мы называем их готовыми к обслуживанию; такой сервер имён должен удовлетворять всем условиям:
- сам сервер имён включён;
- у него корректное имя хоста NS (не пустое и не тестовый заполнитель);
- к нему привязан хотя бы один узел со статусом «включён», отправивший heartbeat за последние 15 минут.
Последнее условие стоит рассмотреть подробнее. Поле статуса узла в базе данных задаёт оператор; оно выражает намерение: «мы хотим, чтобы этот узел обслуживал запросы». Намерение не равно реальности. Машина может быть помечена как включённая, хотя давно не отвечает из-за переустановки, изменений в сети или устаревших учётных данных. Если бы алгоритм назначения доверял только полю статуса, он мог бы делегировать новые зоны сервису, которого фактически нет.
Поэтому наше правило: поле статуса — намерение, время heartbeat — факт. Каждый узел обновляет время последнего контакта при каждом запросе конфигурации, а узлы, переставшие её запрашивать, через некоторое время автоматически помечаются как недоступные. Алгоритм назначения доверяет только фактам.
Как узлы получают данные вашей зоны
После назначения серверов имён данные зоны должны появиться на нужных узлах. Наша плоскость данных авторитетного DNS — доработанная сборка CoreDNS, которая сама запрашивает данные:
- У каждой зоны есть версия конфигурации, которая также служит серийным номером в записи SOA зоны. Любое изменение записи увеличивает её.
- Узлы периодически запрашивают у плоскости управления актуальные версии, проходя аутентификацию. При изменении версии они загружают новые данные зоны, записывают их в стандартный файл зоны и перезагружают данные.
- Каждый узел получает только зоны, назначенные обслуживаемым им серверам имён, а не весь набор данных.
- Когда зона отключается или удаляется, плоскость управления некоторое время продолжает отправлять узлам сигнал удаления. Узлы удаляют локальный файл зоны и перестают отвечать за неё. Удалённые зоны не остаются на отдельных узлах.
Поскольку серийный номер SOA совпадает с версией конфигурации, с помощью dig можно проверить, есть ли у конкретного сервера имён последняя версия:
dig +short SOA example.com @your-nameserver-hostname
Если все серверы имён возвращают одинаковый серийный номер, у всех актуальные данные.
Урок об инфраструктурных зонах
Имена хостов самих NS тоже должны разрешаться, а их связующие и адресные записи находятся в отдельной инфраструктурной зоне, управляемой той же системой, что и клиентские зоны. Это означает, что её статус всегда должен оставаться включённым: при случайном отключении сигнал удаления заставил бы узлы убрать её, затронув все зоны, использующие эти серверы имён. Мы специально проверили этот сценарий сквозным тестированием перед включением сигналов удаления, и теперь такие зоны помечены как постоянно размещённые.
Этот урок применим к любой системе, которая обслуживает собственную инфраструктуру: если платформа размещает свои критически важные зависимости, им нужна дополнительная защита.
Что нужно сделать вам
После добавления домена вам достаточно указать у регистратора два сервера имён из консоли. На странице зоны показаны назначенные ей серверы имён и текущее число активных узлов у каждого, а проверка NS в консоли сообщает, когда делегирование вступило в силу. Остальное берут на себя алгоритм назначения и конвейер синхронизации.
Создавайте проекты на Yeap Cloud
Бесплатные тарифы DNS и CDN для каждого нового аккаунта.
Читать дальше
Начало работы с Yeap LLM API через OpenAI SDK
Yeap LLM API совместим с OpenAI: используйте привычный SDK, указав https://llm.yeap.cloud/v1 в base_url. Создание ключа, примеры на Python и Node.js, потоковые ответы, эмбеддинги, квоты и ограничения моделей и IP для ключей.
Возобновление сеансов TLS и HTTP/3 на пограничных узлах
Возобновление сеансов позволяет повторным посетителям пропустить полное рукопожатие TLS. Почему ключи билетов должны сохраняться при перезапусках, как мы безопасно меняем их и как HTTP/3 использует общий конвейер обработки запросов.
Практическое руководство по очистке кэша: от ключей до отдельных вариантов
Очистили кэш, но по-прежнему получаете попадания? Чаще всего причина в ключе кэша. Как Yeap CDN формирует ключи, как работают режимы строки запроса и что именно удаляет очистка по URL с параметрами и без них.