ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Terraform для DNS: управляем зонами и записями у регистратора как кодом

Разбираем практику управления DNS у регистратора через Terraform: выбор провайдера, структура репозитория и state, импорт существующих зон без простоя, GitOps-процессы и типовые шаблоны записей. Плюс чек‑лист, отладка dig и защита от ошибок, чтобы изменения были воспроизводимыми и безопасными.
Terraform для DNS: управляем зонами и записями у регистратора как кодом

DNS давно перестал быть набором вручную поправленных записей в панели регистратора. Когда у компании десятки зон, десятки окружений и сотни записей, править их в UI — путь к дрейфу конфигурации и человеческим ошибкам. Подход Infrastructure as Code позволяет описывать зоны и записи декларативно, хранить историю в Git, запускать ревью и откатывать изменения одной командой. В этой статье разбираю, как организовать управление DNS у регистратора через Terraform: какие есть провайдеры, как строить репозиторий и state, как импортировать существующие зоны без простоя, какие шаблоны и приёмы облегчают жизнь, и как встроить всё это в GitOps-процесс.

Зачем переводить DNS в Terraform

Основной мотив — воспроизводимость и контроль. Любую правку в зоне можно превратить в PR, получить plan-вывод в комментариях, обсудить TTL, убедиться, что не удаляем нужные записи, и применить через CI. История в Git фиксирует, кто и что менял, а откат становится делом revert-коммита. Плюс Terraform обнаруживает дрейф: если запись поправили вручную в панели, на следующем планировании это станет видно.

Второй мотив — повторяемость. Типовые шаблоны MX, SPF, DKIM, DMARC, SRV, CAA можно оформить в модули и переиспользовать в десятках зон. Меняется политика — меняем модуль, а не бегаем по интерфейсам. Подробный разбор почтовых записей и их назначения смотрите в материале «Полная шпаргалка по SPF, DKIM и DMARC» по ссылке DNS-записи для почтовой аутентификации.

Третий мотив — автоматизация. В GitOps-подходе изменения в основной ветке автоматически запускают план и применяются под присмотром политик. Это сокращает TTM для новых доменов и снижает риск ручных ошибок.

Провайдеры и доступы: регистратор vs DNS-хостинг

Чтобы управлять DNS из Terraform, нужен провайдер. Есть два сценария:

  • Управляем DNS у регистратора (когда он же хостит вашу зону на своих NS). Тогда пригодится провайдер, поддерживающий API конкретного регистратора.
  • Держим зону у внешнего DNS-хостинга. Тогда используем провайдер этой платформы, а у регистратора только NS указываем на нужные сервера.

Выбор зависит от ваших требований к функциям (например, поддержка ALIAS/ANAME на апексе, геотаргетинг, API-лимиты, доступность DNSSEC-операций). Важно заранее проверить:

  • Какие типы записей поддерживает провайдер и Terraform-ресурсы для них.
  • Нужен ли отдельный ресурс для самой зоны (часто да) и как создаются/удаляются зоны.
  • Есть ли ограничения при массовых изменениях (rate limit) и как настраивать ретраи/таймауты.
  • Как хранить и передавать токены/ключи в CI (переменные окружения, отдельные секрет-хранилища).

Совет: заведите отдельный технический доступ с минимально необходимыми правами только на нужные зоны. Не используйте личную учетку с MFA в автоматизации.

FastFox VDS
Регистрация доменов от 99 руб.
Каждый проект заслуживает идеального доменного имени, выберите один из сотни, чтобы начать работу!

Структура репозитория: зоны как модули, окружения как рабочие пространства

Удобная практика — вынести каждую зону в модуль и иметь слой-оркестратор, который подключает модули с нужными переменными. Это позволяет переиспользовать шаблоны по проектам и обеспечить единообразие. Окружения (prod, stage, dev) удобно разделять рабочими пространствами Terraform или каталогами с отдельным состоянием.

Пример структуры:

dns/
  modules/
    zone/
      main.tf
      variables.tf
      outputs.tf
  envs/
    prod/
      main.tf
      versions.tf
      terraform.tfvars
    stage/
      main.tf
      versions.tf
      terraform.tfvars

Где модуль zone описывает создание самой зоны и набор типовых записей, а файлы в envs/<env> перечисляют, какие домены обслуживаем и какими переменными наполняем шаблоны (почта, SPF-провайдеры, CAA-политика и пр.).

Базовые элементы HCL: зона и записи

Ниже — условные имена ресурсов. В вашем провайдере они будут другими (например, отдельные ресурсы на A, AAAA, CNAME, MX, TXT, SRV, CAA и т.д.). Суть в том, что зона — это один ресурс, а записи — другие, обычно с полем zone_id/zone.

# Провайдер и креды
provider "exampledns" {
  api_token = var.api_token
}

# Зона (example.com)
resource "exampledns_zone" "root" {
  name = var.domain
}

# А-записи
resource "exampledns_record_a" "www" {
  zone_id = exampledns_zone.root.id
  name    = "www"
  value   = "203.0.113.10"
  ttl     = 300
}

# AAAA
resource "exampledns_record_aaaa" "www6" {
  zone_id = exampledns_zone.root.id
  name    = "www"
  value   = "2001:db8::10"
  ttl     = 300
}

# MX
resource "exampledns_record_mx" "mx" {
  zone_id  = exampledns_zone.root.id
  name     = "@"
  priority = 10
  value    = "mail.example.com."
  ttl      = 600
}

# TXT (SPF)
resource "exampledns_record_txt" "spf" {
  zone_id = exampledns_zone.root.id
  name    = "@"
  value   = "v=spf1 include:_spf.provider.example -all"
  ttl     = 300
}

Важные тонкости:

  • У многих провайдеров имя корня зоны обозначают как @ или пустую строку. Проверяйте документацию.
  • Хвостовая точка у значений типа FQDN (например, для MX, CNAME) может требоваться или добавляться автоматически. Лучше задавать явно.
  • Для апекса (@) часто нельзя использовать CNAME. Если требуется редирект/резолв через CNAME-подобную семантику, ищите поддержку ALIAS/ANAME у провайдера.

Жизненный цикл и защита от удаления

Для базовых записей и самой зоны полезно ставить защиту:

lifecycle {
  prevent_destroy = true
}

Это спасает от случайного удаления зоны с десятками записей. Снимаем защиту явным PR и осознанно.

Импорт существующих зон без простоя

Если зоны уже крутятся у регистратора, разумнее сначала «подтянуть» инфраструктуру в состояние Terraform, не меняя реальность, и только потом начать вносить правки. Алгоритм:

  1. Опишите каркас ресурсов для зоны и ключевых записей так, чтобы соответствовать текущему факту.
  2. Сделайте terraform import для зоны и записей, используя идентификаторы из панели или API.
  3. Запустите terraform plan и добейтесь нулевого diff. Возможно, потребуется поправить имена, TTL или точки в FQDN.
  4. Зафиксируйте состояние в удалённом бекенде и включите GitOps-процесс.

Пока вы не меняете NS у домена и не трогаете содержимое записей, пользователи ничего не замечают. Если планируется перенос на другой DNS-хостинг, готовим зону зеркально, снижаем TTL заранее (например, до 300), проверяем соответствие контента и уже потом переключаем NS у регистратора. Если вы только заводите новый домен, удобно совместить это с регистрация доменов у одного провайдера, чтобы управлять NS и DS из одного места.

Перед переключением NS важно дать время в 1–2 TTL после снижения, чтобы кеши выветрились. И сразу после смены NS проверьте критичные записи: A/AAAA сайта, MX почты, TXT для SPF/DKIM/DMARC.

Диаграмма процесса импорта зоны в Terraform и безопасного переключения NS.

Моделируем типовые записи и политику

Хорошая практика — завернуть повторяющиеся паттерны в модульные блоки и переменные:

  • SPF как строка, собранная из include-списка провайдеров рассылок, с ограничением на 10 DNS-lookup. При необходимости — «сплющивание» include.
  • DKIM: по домену и селекторам, часто несколько TXT-ключей для ротации.
  • DMARC: _dmarc с политикой p=quarantine|reject, отчетами и правильным TTL. Как читать отчеты — в статье Парсинг DMARC-отчетов и доставляемость.
  • CAA: определяем, кто может выпускать сертификаты, плюс указание e-mail для отчетов.
  • SRV: для VoIP, XMPP и прочих сервисов — аккуратность в приоритете, весе, порте и цели.
  • NS для делегирования подзон (split-horizon, delegated sub-zones для отдельных команд).

Часть записей может быть «автоуправляемой» внешними инструментами. Например, валидационные TXT для разных сервисов или временные записи для ACME DNS-01. Чтобы Terraform не «дрался» с ними, используйте lifecycle { ignore_changes = [...] } на соответствующих ресурсах или вынесите такие записи в отдельную, неуправляемую Terraform зону или подзону. Для выпуска сертификатов через DNS-01 проверьте политику CAA и наличие валидных SSL-сертификаты в вашем процессе.

Переменные, locals и генерация записей

Зачастую удобнее описывать данные декларативно в виде карт, а записи генерировать в циклах:

variable "a_records" {
  type = map(string)
}

locals {
  default_ttl = 300
}

resource "exampledns_record_a" "bulk" {
  for_each = var.a_records
  zone_id  = exampledns_zone.root.id
  name     = each.key
  value    = each.value
  ttl      = local.default_ttl
}

Аналогично можно описать массив MX (с приоритетом), набор TXT, SRV и т.д. Такой подход уменьшает объём кода и упрощает ревью: видно только дельту данных.

State и GitOps: план, ревью, применение

Чтобы команда могла одновременно работать над зонами, нужен удалённый бекенд состояния с блокировками и версионированием. Так вы избежите конкурентных применений. Дальше строим простую цепочку:

  • PR запускает terraform init и terraform plan, артефакт плана публикуется в комментарии.
  • После одобрения и слияния запускается terraform apply от имени сервис-аккаунта.
  • Права на apply ограничены: только основной pipeline с подписанными артефактами.

Рекомендуется добавлять защитные флаги и таймауты в CI: -lock-timeout, линтер HCL, форматирование terraform fmt -check и валидацию terraform validate. Для критических зон используйте «двухключевой» процесс: отдельное подтверждение применений или ручной hold в CI.

Пайплайн CI/CD, который запускает terraform plan и apply для DNS c удалённым state.

Безопасность и доступы

Ключи доступа к API провайдера храним в секретах CI/CD или системном секрет-хранилище, передаём провайдеру через переменные окружения или Terraform variables с пометкой sensitive. Не коммитим *.tfvars с секретами, добавляем их в .gitignore. Разделяем роли: чтение для планов и запись только для применений.

Отдельно следите за лимитами API. Массовые изменения могут попасть под rate limit. Помогают батчинг, искусственные задержки между ресурсами (если провайдер поддерживает), а также разбивка применений по зонам.

Отладка и проверки: dig — лучший друг

После каждого изменения выполняйте серию проверок. На локальном резолвере и с авторитативных:

# Проверить A/AAAA
dig +short www.example.com A
dig +short www.example.com AAAA

# Проверить NS и SOA
dig NS example.com
dig SOA example.com

# Проверить TXT (SPF/DMARC/DKIM)
dig +short TXT example.com
dig +short TXT _dmarc.example.com

# С учетом авторазрешения с авторитетных серверов
dig @ns1.provider.example example.com A

Не забудьте про TTL и кеши: планирование и проведение переключений делайте с учетом того, что пользователи могут видеть запись ещё в течение прежнего TTL. Для критичных сценариев заранее снижайте TTL за 24–48 часов.

Типичные грабли и как их обходить

  • Аpex и CNAME: используйте ALIAS/ANAME, если провайдер поддерживает, либо держите A/AAAA.
  • Хвостовые точки в значениях FQDN: лучше указывать явно, чтобы избежать нежданных суффиксов.
  • SPF превышает лимит 10 DNS-lookup: сплющивайте include или пересматривайте политику.
  • DKIM и ротация: храните несколько селекторов и TTL не ниже 1 часа, планируйте смену ключей.
  • Drift из-за ручных правок в панели: не правьте вручную; если пришлось — делайте импорт и синхронизируйте код.
  • Удаления при рефакторинге: ставьте prevent_destroy и проверяйте план целиком, а не точечно.

Мультизоны и мультиаккаунты

Если зон много и они разбросаны по нескольким регистраторам, используйте алиасы провайдера и карты зон с привязкой к провайдеру. Описывайте зоны данными, а не кодом: один модуль — множество инстансов через for_each. Так вы избежите дублирования и получите единый формат.

DNSSEC и DS-записи

Часть регистраторов позволяет управлять DNSSEC через API. Процесс обычно двухшаговый: включаем подпись в хостинге зоны (генерируется ключ и DS), после чего публикуем DS у регистратора. Держите это в одном месте кода и документируйте порядок действий. При ротации ключей не забывайте обновлять DS и выдерживать время на распространение. Если у вас в конвейере также автоматизирован выпуск и продление SSL-сертификаты, увязывайте сроки ротации ключей DNSSEC и CAA-политику.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Чек-лист внедрения

  • Определите провайдера и проверьте поддержку нужных типов записей и возможностей.
  • Соберите каркас модулей для зоны и типовых записей, определите переменные и locals.
  • Настройте удалённый state с блокировками и доступами по ролям.
  • Импортируйте существующие зоны и добейтесь нулевого плана.
  • Постройте GitOps: план в PR, обязательное ревью, контролируемый apply.
  • Опишите процедуры TTL-менеджмента и переключений NS.
  • Защитите критические ресурсы prevent_destroy, документируйте ручные исключения.
  • Автоматизируйте проверки dig и бизнес-критичных записей после каждого apply.

В результате вы получите воспроизводимый, проверяемый и безопасный процесс управления DNS, где любое изменение проходит через код, ревью и автоматические проверки. Это ускоряет выпуск новых доменов, снижает риск ошибок и делает инфраструктуру прозрачной для команды.

Поделиться статьей

Вам будет интересно

Bash one-liners с jq, curl и xargs: практические рецепты для админов OpenAI Статья написана AI (GPT 5)

Bash one-liners с jq, curl и xargs: практические рецепты для админов

Разбираем практические Bash one-liners с jq, curl и xargs: как быстро выдёргивать данные из JSON, пачками дергать HTTP API, провер ...
Nginx + бесплатный cookie-free CDN как origin: пошаговая схема и тонкая настройка OpenAI Статья написана AI (GPT 5)

Nginx + бесплатный cookie-free CDN как origin: пошаговая схема и тонкая настройка

Разбираем, как подключить сайт на Nginx к бесплатному CDN и использовать сервер как origin без сюрпризов. Пошагово настраиваем coo ...
HTTP API-шлюз на Nginx: rate limit, quota и версионирование OpenAI Статья написана AI (GPT 5)

HTTP API-шлюз на Nginx: rate limit, quota и версионирование

Разбираем, как построить лёгкий HTTP API gateway на Nginx без тяжёлых сервис-мешей: маршрутизация по версиям API, ограничение RPS ...