DNS-зоны и записи¶
Управление доменными зонами и их записями через Terraform вместо ручного ввода в личном кабинете. Показаны два подхода: зоны картой (разный набор) и зоны циклом (много однотипных).
Ресурсы¶
| Ресурс | Назначение |
|---|---|
nubes_zones_v2 |
DNS-зона |
nubes_zones_v2_record |
запись внутри зоны (A, AAAA, CNAME, MX, SRV, TXT, LUA, NS, SSHFP) |
Запись — отдельный ресурс, поэтому одну запись можно изменить или удалить, не трогая зону целиком.
Провайдер¶
terraform {
required_providers {
nubes = {
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes"
version = "3.6.3"
}
}
}
variable "api_token" { type = string; sensitive = true }
provider "nubes" {
api_token = var.api_token
api_endpoint = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc"
}
Токен держите в secrets.auto.tfvars (не в terraform.tfvars):
Проверить файл поможет ИИ
Кнопка «TF» справа внизу: вставьте terraform.tfvars — ИИ вернёт
исправленный файл и список изменений. Секреты не вставляйте.
Вариант 1 — зоны картой¶
Когда набор зон и записей разный, задайте всё одной картой zones.
variable "zones" {
type = map(object({
zone_name = string
records = map(object({
type = optional(string, "A")
values = list(string)
}))
}))
default = {
a = {
zone_name = "tfzone-a.test"
records = {
www = { type = "A", values = ["10.0.0.77", "203.0.113.14"] }
api = { type = "A", values = ["192.168.3.14"] }
cdn = { type = "CNAME", values = ["www.tfzone-a.test."] }
}
}
b = {
zone_name = "tfzone-b.test"
records = {
www = { type = "A", values = ["10.0.0.9"] }
api = { type = "A", values = ["10.0.0.8"] }
}
}
}
}
# «Уплощаем» вложенную карту «зона → записи» в плоский набор записей.
locals {
records = merge([
for zk, z in var.zones : {
for rk, r in z.records : "${zk}:${rk}" => {
zone = zk
name = rk
type = r.type
values = r.values
}
}
]...)
}
resource "nubes_zones_v2" "zone" {
for_each = var.zones
resource_name = "dns-zone-${each.key}"
zone_name = each.value.zone_name
}
resource "nubes_zones_v2_record" "record" {
for_each = local.records
zones_v2_id = nubes_zones_v2.zone[each.value.zone].id
record_name = each.value.name
record_type = each.value.type
record_input = jsonencode([for v in each.value.values : { record = v }])
record_ttl = 3600
}
Вариант 2 — зоны циклом¶
Когда зон много и они однотипны (например поддомены app-1 … app-50), сгенерируйте
их из одного числа:
variable "zone_count" { type = number; default = 10 }
variable "zone_prefix" { type = string; default = "tfzone" }
variable "zone_domain" { type = string; default = "test" }
locals {
zones = {
for i in range(1, var.zone_count + 1) :
"${var.zone_prefix}-${i}" => {
zone_name = "${var.zone_prefix}-${i}.${var.zone_domain}"
records = {
www = { type = "A", values = ["10.0.${i}.1"] }
api = { type = "A", values = ["10.0.${i}.2"] }
}
}
}
records = merge([
for zk, z in local.zones : {
for rk, r in z.records : "${zk}:${rk}" => {
zone = zk
name = rk
type = r.type
values = r.values
}
}
]...)
}
resource "nubes_zones_v2" "zone" {
for_each = local.zones
resource_name = "dns-zone-${each.key}"
zone_name = each.value.zone_name
}
resource "nubes_zones_v2_record" "record" {
for_each = local.records
zones_v2_id = nubes_zones_v2.zone[each.value.zone].id
record_name = each.value.name
record_type = each.value.type
record_input = jsonencode([for v in each.value.values : { record = v }])
record_ttl = 3600
}
Итоговое имя зоны = <zone_prefix>-<i>.<zone_domain>, например tfzone-3.test.
Готовые файлы¶
Примеры лежат в репозитории tf_examples
(клонируйте и зайдите в нужную папку):
git clone https://gitea.services.ngcloud.ru/Nail/tf_examples.git
cd tf_examples/dns_zones
cp terraform.tfvars.example terraform.tfvars
terraform init
terraform plan
terraform apply
dns_zones/— вариант 1 (карта зон);dns_zones_generated/— вариант 2 (цикл).
Важно¶
- Ключ карты (
a,b,www…) — это адрес объекта в state. Смена ключа = удалить + создать заново, а не переименовать. Значение (zone_name,values) меняйте свободно — обычныйapply. CNAMEпишется с точкой на конце (www.example.com.).- Несколько адресов у одной записи — это один ресурс, а не несколько.
record_ttlдопустим от30до84000секунд;record_type— только из списка типов выше (неверное значение отклонится ещё на этапеplan).- Чтобы зоны работали в интернете, делегируйте домен у регистратора на NS
ns3.ngcloud.ru/ns4.ngcloud.ru. - После
applyповторныйplanдолжен показатьNo changes.