docs: подробные комментарии в примерах DNS-зон и записей
This commit is contained in:
+47
-14
@@ -1,40 +1,72 @@
|
||||
# =============================================================================
|
||||
# Пример: доменные зоны компании и записи в них — через Terraform.
|
||||
# Пример: доменные зоны компании и записи DNS — целиком через Terraform.
|
||||
#
|
||||
# Задача: держать доменные зоны и их записи в коде (IaC), а не руками в ЛК.
|
||||
#
|
||||
# Ресурсы провайдера Nubes:
|
||||
# - nubes_zones_v2 (сервис 109) — DNS-зона;
|
||||
# - nubes_zones_v2_record (подресурс зоны, record) — запись внутри зоны.
|
||||
# - nubes_zones_v2 (сервис 109) — DNS-зона;
|
||||
# - nubes_zones_v2_record (подресурс зоны, record) — запись внутри зоны
|
||||
# (A / CNAME / …). Записи — ОТДЕЛЬНЫЕ ресурсы, поэтому ими можно управлять
|
||||
# адресно: добавить/изменить/удалить одну запись, не трогая зону целиком.
|
||||
#
|
||||
# ⚠️ Имя поля в HCL = `name` из схемы (snake_case); `code` (camelCase) — имя в API.
|
||||
# ⚠️ В HCL пишется `name` поля из схемы (snake_case): `zone_name`, `record_name`,
|
||||
# `record_type`, `record_input`, `record_ttl`. `code` (camelCase) — внутреннее
|
||||
# имя в API, в HCL НЕ используется.
|
||||
#
|
||||
# Зоны задаются картой `var.zones` (ключ → zone_name + records).
|
||||
# Чтобы добавить/убрать зону или запись — правьте `var.zones` и делайте `apply`.
|
||||
# КАК РАСШИРЯТЬ: чтобы добавить/убрать зону или запись — правьте `var.zones`
|
||||
# (в variables.tf или terraform.tfvars) и делайте `terraform apply`.
|
||||
# Ключи карт (`a`, `b`, `www`, …) — это АДРЕСА объектов в state. Меняйте их
|
||||
# осознанно: смена ключа = «удалить старый объект + создать новый», а не
|
||||
# «переименовать». Само значение `zone_name`/`record_input` меняется обычным
|
||||
# `apply`.
|
||||
# =============================================================================
|
||||
|
||||
# ── locals.records: «уплощаем» вложенную структуру «зоны → записи» ────────────
|
||||
#
|
||||
# var.zones — карта «зона → { zone_name, records }», где records — ещё одна
|
||||
# карта «имя записи → { type, values }».
|
||||
#
|
||||
# Ресурсу записи нужен ОДИН плоский набор, где у каждого элемента УНИКАЛЬНЫЙ
|
||||
# ключ: тогда `for_each` создаст ровно по одному ресурсу на запись и даст
|
||||
# стабильные адреса вида `nubes_zones_v2_record.record["a:www"]`.
|
||||
#
|
||||
# `merge([ ... ]...)` — разворот (`...`) списка карт в один вызов merge —
|
||||
# склеивает карты из каждой зоны в общую. Ключ собираем как "<зона>:<запись>",
|
||||
# чтобы записи с одинаковыми именами в разных зонах не столкнулись.
|
||||
locals {
|
||||
# Плоская карта записей «зона:имя» (вложенный цикл → merge/flatten),
|
||||
# чтобы `for_each` у записей давал стабильные адреса.
|
||||
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
|
||||
zone = zk # какая зона (ключ карты var.zones)
|
||||
name = rk # имя записи
|
||||
type = r.type # тип записи (A / CNAME / …)
|
||||
values = r.values # список значений записи
|
||||
}
|
||||
}
|
||||
]...)
|
||||
}
|
||||
|
||||
# Зоны: N штук из var.zones (for_each по ключам карты — стабильные адреса).
|
||||
# ── Зоны ─────────────────────────────────────────────────────────────────────
|
||||
# `for_each = var.zones` — по одному ресурсу на каждый КЛЮЧ карты зон.
|
||||
# `each.key` — короткое имя зоны (a, b, …), `each.value` — её параметры.
|
||||
# `resource_name` — человекочитаемое имя ресурса в Nubes; `zone_name` — сам
|
||||
# домен (FQDN зоны).
|
||||
resource "nubes_zones_v2" "zone" {
|
||||
for_each = var.zones
|
||||
resource_name = "dns-zone-${each.key}"
|
||||
zone_name = each.value.zone_name
|
||||
}
|
||||
|
||||
# Записи: record_input = [{record=<значение>}, ...] из списка values.
|
||||
# ── Записи ───────────────────────────────────────────────────────────────────
|
||||
# `for_each = local.records` — по одному ресурсу на запись (плоская карта выше).
|
||||
# `zones_v2_id` — ссылка на id СВОЕЙ зоны (через for_each зоны): Terraform сам
|
||||
# построит зависимость «зона создаётся раньше своих записей».
|
||||
#
|
||||
# `record_input` — платформа ждёт JSON-массив объектов `[{ record = "<значение>" },
|
||||
# …]`, поэтому собираем его из плоского списка `values` через `jsonencode`.
|
||||
# Одна запись может иметь НЕСКОЛЬКО значений (напр. два A-адреса) — это одна
|
||||
# запись с массивом, а не две отдельные.
|
||||
resource "nubes_zones_v2_record" "record" {
|
||||
for_each = local.records
|
||||
zones_v2_id = nubes_zones_v2.zone[each.value.zone].id
|
||||
@@ -43,3 +75,4 @@ resource "nubes_zones_v2_record" "record" {
|
||||
record_input = jsonencode([for v in each.value.values : { record = v }])
|
||||
record_ttl = 3600
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Конфигурация провайдера Nubes.
|
||||
# api_token — секрет (передаётся из secrets.auto.tfvars);
|
||||
# api_endpoint — адрес API Gateway стенда.
|
||||
# ⚠️ Атрибута `realm` у провайдера НЕТ — ресурсная платформа задаётся параметром
|
||||
# ресурса (напр. `startup_configuration.resource_realm`), а не здесь.
|
||||
provider "nubes" {
|
||||
api_token = var.api_token
|
||||
api_endpoint = var.api_endpoint
|
||||
|
||||
+20
-3
@@ -1,19 +1,36 @@
|
||||
# Переменные примера. api_token — СЕКРЕТ, держать в secrets.auto.tfvars (не коммитить).
|
||||
# =============================================================================
|
||||
# Переменные примера «DNS-зоны и записи».
|
||||
#
|
||||
# ⚠️ api_token — СЕКРЕТ. НЕ кладите его в terraform.tfvars. Держите в отдельном
|
||||
# файле `secrets.auto.tfvars` (Terraform сам подхватывает `*.auto.tfvars`),
|
||||
# а этот файл закройте в .gitignore. Значение — JWT из ЛК (Профиль → Токены).
|
||||
# =============================================================================
|
||||
|
||||
# Токен доступа (JWT) к API Nubes. `sensitive = true` — Terraform не покажет
|
||||
# значение в выводе плана/apply.
|
||||
variable "api_token" {
|
||||
description = "Nubes API token (JWT). Секрет — в secrets.auto.tfvars."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Адрес API Gateway стенда. Для TEST — как в default.
|
||||
variable "api_endpoint" {
|
||||
description = "API Gateway URL стенда"
|
||||
type = string
|
||||
default = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc"
|
||||
}
|
||||
|
||||
# Зоны: карта «короткое имя → { zone_name, records }».
|
||||
# records — карта «имя записи → { type, values }».
|
||||
# ── Зоны и записи ────────────────────────────────────────────────────────────
|
||||
# Карта «короткое имя зоны → { zone_name, records }»:
|
||||
# - КЛЮЧ карты (a, b, …) — адрес зоны в state (стабильный id объекта в TF);
|
||||
# - zone_name — сам домен (FQDN зоны);
|
||||
# - records — карта «имя записи → { type, values }»:
|
||||
# - type — тип записи (A / CNAME / TXT / …), по умолчанию "A";
|
||||
# - values — СПИСОК значений (одна запись может иметь их несколько,
|
||||
# напр. два A-адреса у одного имени).
|
||||
#
|
||||
# Здесь задан дефолт (2 зоны × 3 записи). Можно переопределить в terraform.tfvars.
|
||||
variable "zones" {
|
||||
description = "Зоны компании: имя + записи (type / values[])"
|
||||
type = map(object({
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
# Версии Terraform и провайдера Nubes.
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
required_version = ">= 1.5.0" # минимальная версия Terraform
|
||||
|
||||
required_providers {
|
||||
nubes = {
|
||||
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes"
|
||||
# Реестр провайдера стенда TEST. Для другого стенда — свой namespace:
|
||||
# PROD → .../nubes/nubes, DEV → .../nubes-dev/nubes
|
||||
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes"
|
||||
# Фиксируем версию провайдера — для воспроизводимости.
|
||||
version = "3.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
+37
-14
@@ -1,20 +1,35 @@
|
||||
# =============================================================================
|
||||
# Пример: N DNS-зон генерируются ПРОГРАММНО (в цикле) — через Terraform.
|
||||
# Пример: N DNS-зон генерируются ПРОГРАММНО (в цикле) — целиком через Terraform.
|
||||
#
|
||||
# Отличие от ../dns_zones/: там зоны заданы явной картой `var.zones`,
|
||||
# а здесь зоны генерируются из числа `var.zone_count` через `range(...)`.
|
||||
# Удобно, когда зон много и они однотипны (tfzone-1 … tfzone-N).
|
||||
# Отличие от ../dns_zones/: там зоны заданы ЯВНОЙ картой `var.zones`, а здесь —
|
||||
# генерируются из числа `var.zone_count` через `range(1, N+1)`. Удобно, когда
|
||||
# зон много и они ОДНОТИПНЫ (tfzone-1 … tfzone-N), и задавать каждую руками
|
||||
# не хочется.
|
||||
#
|
||||
# Ресурсы: nubes_zones_v2 (109) + подресурс nubes_zones_v2_record (записи).
|
||||
# ⚠️ Имя поля в HCL = `name` из схемы (snake_case).
|
||||
# Ресурсы провайдера Nubes:
|
||||
# - nubes_zones_v2 (сервис 109) — DNS-зона;
|
||||
# - nubes_zones_v2_record (подресурс зоны, record) — запись внутри зоны.
|
||||
#
|
||||
# ⚠️ В HCL пишется `name` поля из схемы (snake_case): `zone_name`, `record_name`,
|
||||
# `record_type`, `record_input`, `record_ttl`. `code` (camelCase) — имя в API.
|
||||
#
|
||||
# КАК РАСШИРЯТЬ: измените `var.zone_count` (и `zone_prefix`/`zone_domain`) и
|
||||
# сделайте `apply` — зоны добавятся/уберутся. Состав записей в шаблоне зоны
|
||||
# правится в `locals.zones` ниже.
|
||||
# =============================================================================
|
||||
|
||||
# ── locals.zones: ГЕНЕРИРУЕМ N однотипных зон ────────────────────────────────
|
||||
# `range(1, var.zone_count + 1)` даёт последовательность 1..N. Для каждого числа
|
||||
# строим элемент карты: ключ "<prefix>-<i>", значение — { zone_name, records }.
|
||||
# Ключ карты = адрес зоны в state (стабильное имя объекта), поэтому нумерация
|
||||
# зон детерминирована: tfzone-1 … tfzone-N.
|
||||
locals {
|
||||
# N зон генерируются программно: tfzone-1 … tfzone-N.
|
||||
zones = {
|
||||
for i in range(1, var.zone_count + 1) :
|
||||
"${var.zone_prefix}-${i}" => {
|
||||
zone_name = "${var.zone_prefix}-${i}.${var.zone_domain}"
|
||||
# Однотипный набор записей для каждой зоны (пример). Здесь — www и api
|
||||
# с адресами, зависящими от номера зоны (10.0.<i>.1 / .2).
|
||||
records = {
|
||||
www = { type = "A", values = ["10.0.${i}.1"] }
|
||||
api = { type = "A", values = ["10.0.${i}.2"] }
|
||||
@@ -22,28 +37,35 @@ locals {
|
||||
}
|
||||
}
|
||||
|
||||
# Плоская карта записей «зона:имя» (вложенный цикл → merge/flatten).
|
||||
# ── locals.records: «уплощаем» карту зон в плоский набор записей ───────────
|
||||
# Записи — отдельные ресурсы, каждой нужен уникальный ключ в for_each. Собираем
|
||||
# карту «<зона>:<запись>» (разворот `...` в merge склеивает карты всех зон).
|
||||
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
|
||||
zone = zk # какая зона
|
||||
name = rk # имя записи
|
||||
type = r.type # тип (A / CNAME / …)
|
||||
values = r.values # список значений
|
||||
}
|
||||
}
|
||||
]...)
|
||||
}
|
||||
|
||||
# Зоны: N штук, сгенерированных в locals (for_each по ключам — стабильные адреса).
|
||||
# ── Зоны ─────────────────────────────────────────────────────────────────────
|
||||
# `for_each = local.zones` — по одному ресурсу на сгенерированную зону.
|
||||
# `each.key` = "<prefix>-<i>", `each.value.zone_name` = FQDN.
|
||||
resource "nubes_zones_v2" "zone" {
|
||||
for_each = local.zones
|
||||
resource_name = "dns-zone-${each.key}"
|
||||
zone_name = each.value.zone_name
|
||||
}
|
||||
|
||||
# Записи: record_input = [{record=<значение>}, ...] из списка values.
|
||||
# ── Записи ───────────────────────────────────────────────────────────────────
|
||||
# `zones_v2_id` ссылается на id СВОЕЙ зоны → Terraform строит зависимость.
|
||||
# `record_input` — JSON-массив `[{ record = "<значение>" }, …]` (jsonencode),
|
||||
# одна запись может иметь несколько значений.
|
||||
resource "nubes_zones_v2_record" "record" {
|
||||
for_each = local.records
|
||||
zones_v2_id = nubes_zones_v2.zone[each.value.zone].id
|
||||
@@ -52,3 +74,4 @@ resource "nubes_zones_v2_record" "record" {
|
||||
record_input = jsonencode([for v in each.value.values : { record = v }])
|
||||
record_ttl = 3600
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Конфигурация провайдера Nubes.
|
||||
# api_token — секрет (передаётся из secrets.auto.tfvars);
|
||||
# api_endpoint — адрес API Gateway стенда.
|
||||
# ⚠️ Атрибута `realm` у провайдера НЕТ — ресурсная платформа задаётся параметром
|
||||
# ресурса (напр. `startup_configuration.resource_realm`), а не здесь.
|
||||
provider "nubes" {
|
||||
api_token = var.api_token
|
||||
api_endpoint = var.api_endpoint
|
||||
|
||||
@@ -1,29 +1,40 @@
|
||||
# Переменные примера. api_token — СЕКРЕТ, держать в secrets.auto.tfvars.
|
||||
# =============================================================================
|
||||
# Переменные примера «N DNS-зон, сгенерированных программно».
|
||||
#
|
||||
# ⚠️ api_token — СЕКРЕТ: не в terraform.tfvars, а в secrets.auto.tfvars
|
||||
# (Terraform подхватывает `*.auto.tfvars` сам), файл — в .gitignore.
|
||||
# =============================================================================
|
||||
|
||||
# Токен доступа (JWT) к API Nubes. `sensitive` — не показывать значение в выводе.
|
||||
variable "api_token" {
|
||||
description = "Nubes API token (JWT). Секрет — в secrets.auto.tfvars."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Адрес API Gateway стенда (для TEST — как в default).
|
||||
variable "api_endpoint" {
|
||||
description = "API Gateway URL стенда"
|
||||
type = string
|
||||
default = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc"
|
||||
}
|
||||
|
||||
# ── Параметры генерации зон ──────────────────────────────────────────────────
|
||||
# Сколько однотипных зон создать: tfzone-1 … tfzone-<zone_count>.
|
||||
variable "zone_count" {
|
||||
description = "Сколько зон сгенерировать (tfzone-1 … tfzone-N)"
|
||||
type = number
|
||||
default = 10
|
||||
}
|
||||
|
||||
# Префикс имени/домена зоны (первая часть FQDN).
|
||||
variable "zone_prefix" {
|
||||
description = "Префикс имени зоны"
|
||||
type = string
|
||||
default = "tfzone"
|
||||
}
|
||||
|
||||
# Домен (суффикс FQDN). Итоговое имя зоны = "<prefix>-<i>.<zone_domain>".
|
||||
variable "zone_domain" {
|
||||
description = "Домен зон (суффикс FQDN)"
|
||||
type = string
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
# Версии Terraform и провайдера Nubes.
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
required_version = ">= 1.5.0" # минимальная версия Terraform
|
||||
|
||||
required_providers {
|
||||
nubes = {
|
||||
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes"
|
||||
# Реестр провайдера стенда TEST. Для другого стенда — свой namespace:
|
||||
# PROD → .../nubes/nubes, DEV → .../nubes-dev/nubes
|
||||
source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes"
|
||||
# Фиксируем версию провайдера — для воспроизводимости.
|
||||
version = "3.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user