Files
tf_examples/AGENTS.md
T

27 KiB
Raw Blame History

AGENTS.md — руководство для ИИ-агентов по репозиторию tf_examples

Этот файл читается ИИ-агентами (GitHub Copilot, Claude, Cursor и др.), которые работают в этом репозитории — репозитории готовых примеров Terraform-провайдера Nubes.

Цель агента: помогать пользователю писать и проверять Terraform-конфигурацию (main.tf, variables.tf, terraform.tfvars) для провайдера Nubes — правильно и без выдуманных параметров, не выполняя при этом деплой. terraform plan и terraform apply запускает только пользователь.

Главное правило: параметры не берутся из памяти модели — они сверяются со схемой ресурса (раздел 2) и с содержимым самих примеров (раздел 6).


0. Кому адресован этот файл

Файл написан для стороннего ИИ-агента, который не знает о предметной области ничего. Если ты такой агент — прочитай файл целиком, прежде чем советовать. Ниже объяснены: базовые понятия Terraform, что такое облако Nubes, как устроены примеры и как правильно помогать пользователю. Все утверждения о параметрах должны опираться на схему (раздел 2) или на содержимое примеров (раздел 6), а не на догадки.

0.1. Базовые понятия Terraform (с нуля)

  • Terraform — инструмент «инфраструктура как код» (Infrastructure as Code). Пользователь описывает желаемое состояние облака в текстовых файлах, а Terraform приводит облако к этому состоянию. Ничего не делается руками в интерфейсе — всё описано в коде.
  • HCL — язык этих файлов (расширение .tf). Пример блока ресурса:
    resource "nubes_postgres" "main_pg" { … }   # тип ресурса — nubes_postgres, локальное имя — main_pg
    
  • Провайдер — плагин, через который Terraform общается с конкретным облаком. Здесь это провайдер Nubes; он скачивается автоматически при terraform init.
  • Ресурс — объект в облаке (кластер БД, виртуальная машина, бакет и т.п.).
  • Переменные объявляются блоком variable "имя" { … }, а их значения задаются в файле terraform.tfvars — это то, что заполняет пользователь под свою организацию.
  • Файл состояния (terraform.tfstate) хранит соответствие «код ↔ реальные объекты». Его не редактируют вручную.
  • Команды: terraform init (скачать провайдер), terraform plan (показать, что изменится, ничего не меняя), terraform apply (применить), terraform destroy (удалить).
  • Каждый пример — отдельный каталог с собственным состоянием; модули не используются.

0.2. Что такое Nubes

Nubes — облачная платформа, предоставляющая услуги «как сервис»: базы данных (PostgreSQL, MongoDB, Redis, MariaDB, ClickHouse), очереди (Kafka, RabbitMQ), Kubernetes («Штурвал»), виртуализацию VMware (vDC, Edge, виртуальные машины), объектное хранилище S3, готовые приложения (Node.js, Flask, Lucee и др.) и сеть (DNS, внешние IP, SNAT).

  • Управляется через Личный кабинет (ЛК) и API. Terraform-провайдер Nubes — обёртка над этим API: каждая услуга платформы представлена ресурсом nubes_*.
  • Ресурсы бывают составными: например, кластер БД (nubes_postgres) → база (nubes_postgres_database) → пользователь (nubes_postgres_user). Часть ресурсов — модификаторы уже существующих услуг (внешние IP, SNAT).
  • У ресурса есть операции (создание/удаление/изменение/остановка/запуск). Провайдер сам вызывает нужную операцию по командам Terraform.
  • Значения, зависящие от организации (токен, кластер, IP-пространства, домены), задаёт пользователь; они берутся из ЛК.

0.3. Зачем эти примеры и как их используют

Пользователь клонирует репозиторий, копирует terraform.tfvars.example → terraform.tfvars, заполняет значения из ЛК, затем выполняет terraform init / plan / apply. Пример — это готовый каркас конфигурации; правки сводятся к значениям и, при необходимости, к именам ресурсов. Задача агента — помогать на этих шагах, а не выполнять их вместо пользователя.


1. Что это за репозиторий

Здесь лежат законченные сценарии развёртывания инфраструктуры в облаке Nubes через Terraform. Репозиторий — эталонные примеры, на которые ссылается сайт документации.

Папка Что это Состояние Документация
fullpipe_chain/ vDC → Edge → внешние IP → SNAT → vApp → ВМ → Штурвал (полная цепочка) рекомендовано использовать — повторяет рабочую конфигурацию стенда /nubes-dev/curated/pipeline/vdc_edge_ip_snat/
Maria_CRUD/ MariaDB + три приложения (Lucee/Flask/Node.js) + HTTP-проверка проверен на TEST-стенде /nubes-test/curated/mariadb/three_apps/
CRUD/ PostgreSQL + три приложения (Lucee/Flask/Node.js) черновик (устаревшая схема, старый пин провайдера) — с оговорками /nubes-test/curated/crud/three_apps/
modify_resources/ внешние IP на организации + SNAT на шлюзе (для уже существующих услуг) черновик —

Что рекомендовать пользователю: fullpipe_chain (полный цикл) или Maria_CRUD (проверенный CRUD-пример). Остальные папки — черновики от прошлых работ: могут содержать неактуальные версии провайдера и работать некорректно. Не выдавай черновик за рабочий образец.


2. Источник правды о параметрах (схемы)

Параметры ресурсов НЕ берутся из памяти. Их берут из схемы:

Источник Что внутри
Страница ресурса на сайте доков https://tf-docs.nodejsk8s.dev.nubes.ru/<stand>/<service>/ — таблица атрибутов = схема
Машиночитаемая схема (JSON) https://tf-docs.nodejsk8s.dev.nubes.ru/<stand>/schema/<service>.json
Локально (если репозиторий внутри провайдера) ../provider/resources_yaml/*.yaml и ../stack/<stand>/<service>/raw.json

Структура raw.json / YAML-спеки (поля параметра): name (человеческое имя), code (машинное имя в API), type (integer/string/map-fixed/…), required, default, sub_params[], man (описание). Тип ресурса в HCL — это resource_type (вида nubes_*); поля ресурса — create.params[].

Стенды: nubes-test (тест), nubes-dev (dev), nubes (prod).


3. Инвентарь ресурсов провайдера (nubes_*)

Если пользователь называет ресурс, которого нет в этом списке — его не существует (например, nubes_instance, nubes_floating_ip — таких нет).

Ресурс resource_type
PostgreSQL nubes_postgres, nubes_postgres_user, nubes_postgres_database
MongoDB nubes_mongodb, nubes_mongodb_user, nubes_mongodb_backup
Redis nubes_redis
MariaDB nubes_mariadb, nubes_mariadb_user, nubes_mariadb_database
ClickHouse nubes_clickhouse
Kafka nubes_kafka, nubes_kafka_topic, nubes_kafka_user
RabbitMQ nubes_rabbitmq
S3 nubes_s3, nubes_s3bucket, nubes_s3_sub_user
Сеть nubes_zones_v2, nubes_dnsrecord, nubes_vcexternalip
VMware / Cloud Director nubes_vc_org, nubes_vc_vdc, nubes_vc_vdc_group, nubes_vc_nsxt, nubes_vc_nsxt_snat, nubes_vc_org_ip_allocation, nubes_vapp, nubes_vc_vm_v3
Kubernetes (Штурвал) nubes_k8s_sthutrval_cluster, nubes_vc_mgmt_sthutrval_cluster, nubes_k8s_velero, nubes_k8s_openbao
Приложения nubes_nodejs, nubes_flask, nubes_lucee, nubes_nextcloud, nubes_gitea, nubes_harbor, nubes_superset, nubes_pgadmin, nubes_akhq, nubes_http
Прочее nubes_llm_ai, nubes_valo_tenant, nubes_template, nubes_dummy

Полный актуальный список — в provider/resources_yaml/ (у провайдера) или на сайте доков.


4. Структура примера и назначение файлов

tf_examples/<example>/
  README.md                 # что делает пример, порядок запуска, что заполнить
  main.tf                   # провайдер + объявление переменных
  variables.tf              # описания и типы переменных (где есть)
  <ресурсы>.tf              # ресурсы (например postgres.tf, vm.tf, resources.tf)
  locals.tf                 # настраиваемые значения (имена, домены, git-ревизии)
  terraform.tfvars.example  # ШАБЛОН параметров; копируется в terraform.tfvars
  terraform.tfvars          # реальные значения — в .gitignore, НЕ коммитится

Ключевая мысль: пользователь копирует terraform.tfvars.example в terraform.tfvars и заполняет. Всё, что «постоянное» (имена ресурсов, размеры), лежит в .tf/locals.tf; все значения, зависящие от организации пользователя (токен, кластер, IP-пространства) — в terraform.tfvars.


5. Конфигурация провайдера (одинакова во всех примерах)

terraform {
  required_providers {
    nubes = {
      source  = "tf-registry.containerk8s.services.ngcloud.ru/<stand>/nubes"
      version = "<версия>"
    }
  }
}

provider "nubes" {
  api_token    = var.api_token      # JWT из ЛК (ЛК → Профиль → Токены → «Технический»)
  api_endpoint = "https://lk-api-gateway-<stand>.ngcloud.ru/api/v1/svc"
}
  • api_token — всегда из terraform.tfvars/secrets.auto.tfvars, никогда не в git.
  • realm — ресурсная платформа (кластер Kubernetes), должна существовать в ЛК.
  • api_endpoint — у тестового стенда ...-test.ngcloud.ru, у прода — без суффикса.

6. Разбор примеров (что создаётся, что задаёт пользователь, грабли)

6.1. fullpipe_chain — полная цепочка (рекомендуемый)

Создаёт: vDC → Edge (AVI) → внешние IP на организации → SNAT → vApp → ВМ → кластер Штурвал. Организацию пользователь создаёт заранее в ЛК (Terraform её не создаёт и не удаляет).

Обязательные значения terraform.tfvars:

Переменная Где брать
api_token ЛК → Профиль → Токены → «Технический»
organization точное название услуги «Организация в Cloud Director»
vdc_network_provider ЛК → создание vDC → «Сетевой провайдер»
vdc_provider_vdc ЛК → создание vDC → «Provider VDC» (тот же ресурсный пул)
vdc_storage_config JSON-массив: [{"name":"SATA","size":"200"}] (дисковая политика + ГБ)
ip_space_name имя ipSpace из карточки организации
vm_user_public_key содержимое ~/.ssh/id_ed25519.pub

Порядок: terraform init → validate → plan (7 ресурсов) → apply. Проверка: terraform output (UUID/имена услуг), ВМ — terraform output vm_state_flat (externalConnect для SSH), Штурвал — shturval_state_params (kubernetesApiAddress, ingressAddress). Кластер Штурвала создаётся десятки минут (operation_timeout = "60m").

destroy по умолчанию = «заморозка»: почти ничего не удаляется (см. раздел 10). Полное удаление — осознанное: снять keep_on_destroy/suspend_on_destroy, порядок — кластер → ВМ → vApp → count = 0 → SNAT → Edge → vDC.

6.2. Maria_CRUD — CRUD на MariaDB (проверенный)

Создаёт: кластер MariaDB 9.4.0, базу maria, пользователя cruduser (ALL PRIVILEGES), три приложения (Lucee / Flask / Node.js) и контейнер HTTP-проверки (nubes_http). Все приложения пишут в одну таблицу crud_items.

Обязательные terraform.tfvars: api_token, realm, mariadb_user_password (пароль БД). Проверка работоспособности: curl .../readyz у HTTP-проверки → {"status":"ready","database":"connected"}.

Грабли (важно объяснять пользователю):

  • логин БД — без _ (cruduser, не crud_user): _ ломает RFC 1123 в имени k8s-объекта;
  • креды берутся из подресурса nubes_mariadb_user, а не из vault_secrets кластера (внутри одного apply vault_secrets ещё пуст → Invalid index);
  • retain бэкапа — в часах, минимум 24;
  • версия MariaDB — только 8.4.0 или 9.4.0 (можно только повышать);
  • db_name пользователя — JSON-массив: jsonencode([{ dbname = "maria" }]);
  • registry_path образа — полный путь (<реестр>/<namespace>/<образ>:<тег>);
  • adopt_existing_on_create — повторный apply усыновляет существующий инстанс (не падает).

6.3. CRUD — PostgreSQL + три приложения

Создаёт: PostgreSQL (nubes_postgres), пользователя и БД, приложения Lucee/Flask/Node.js. Особенность: PostgreSQL не успевает отдать пароль до старта приложений — нужен двойной terraform apply (или два этапа через *_git_revision). Домены приложений задаются в locals.tf (должны быть уникальны). Папка — черновик (старая плоская схема, старый пин провайдера): использовать осторожно, при вопросах сверяться с Maria_CRUD.

6.4. modify_resources — IP и SNAT на существующих услугах

Два ресурса для уже созданных в ЛК услуг: nubes_vc_org_ip_allocation (внешние IP на организации) и nubes_vc_nsxt_snat (SNAT на шлюзе). terraform.tfvars: api_token, organization, nsxt_uid (UUID шлюза Edge из карточки услуги), ip_space_name, ip_count.


7. Секреты — жёсткое правило

  1. api_token, пароли, ключи, приватные ключи никогда не попадают в terraform.tfvars в репозитории и тем более в git.
  2. Реальные значения — в локальном secrets.auto.tfvars (Terraform загружает файлы *.auto.tfvars автоматически). Этот файл — в .gitignore.
  3. Значения-заглушки (<token>, eyJhbGciOi..., AAAA...) — это примеры; их заменяет пользователь на свои.
  4. Если файл передаётся внешнему сервису/ЛЛМ — только без секретов.

8. Workflow агента (проверка/написание файла)

Когда просят «проверить/написать terraform.tfvars (или .tf) для X»:

  1. Определи ресурс и найди его схему (раздел 2): resource_type + params[].
  2. Сверь каждое поле со схемой: имя (code/name), тип, required. Пропуск обязательного поля — ошибка; поле не из схемы — ошибка/предупреждение.
  3. Значения не выдумывай. Не подставляй «правдоподобные» имена кластеров, IP, UUID, домены — их даёт пользователь или ЛК.
  4. Проверь слои: провайдер-конфиг (api_token/realm/api_endpoint), параметры ресурса, зависимости (например, база должна существовать до пользователя — depends_on).
  5. Верни результат: исправленный файл целиком + список изменений + предупреждения.
  6. plan/apply — пользователь. Агент не деплоит и не удаляет.

Дополнительно: проверить файл можно и через сервис — POST /<stand>/_api/file ({"content":"...","instruction":"..."} → {content, changes[], warnings[]}), см. раздел 11.


9. Типичные ошибки (реальные, встречаются в примерах)

  • Секрет в terraform.tfvars (api_token, пароли) вместо secrets.auto.tfvars.
  • realm не существует в ЛК → «Ресурсной платформы … нету в Личном кабинете» (при этом /resourceRealms/available может её показывать — доверяй ЛК, не API-списку).
  • Логин БД с _ (crud_user) → платформа падает на имени k8s-объекта. Только буквы/цифры.
  • Короткий registry_path (без хоста реестра) → образ «не находится».
  • s3_uid, которого нет на стенде → invalid input syntax for type uuid.
  • Домен занят (не уникален) → ошибка деплоя приложения.
  • Пропущен required-параметр (cluster_configuration и т.п.) → plan/apply падает.
  • Опечатка в имени поля (clusterConfig вместо clusterConfiguration) → поле игнорируется.
  • Эмодзи (4-байтовые) в MariaDB-примере → Incorrect string value (частичная utf8mb3-таблица).
  • Асинхронные сбои платформы («Kubernetes cluster unreachable», IAM-сбои) — не всегда вина конфигурации: повтор команды обычно проходит.

10. Жизненный цикл ресурсов (что объяснять пользователю)

Провайдер управляет не только созданием, но и «судьбой» ресурса при удалении:

  • suspend_on_destroy = true — destroy не удаляет, а останавливает (данные сохраняются). Повторный apply усыновляет и размораживает.
  • keep_on_destroy = true — ресурс при destroy не трогается вовсе (например, Edge, SNAT, квота IP, пользователь/база внутри кластера).
  • adopt_existing_on_create = true — если инстанс с таким именем уже есть, провайдер его усыновит, а не упадёт с «уже существует».
  • Организация в Cloud Director создаётся вручную в ЛК — Terraform её не создаёт и не удаляет.

Практический вывод: terraform destroy в этих примерах по умолчанию не удаляет данные — это «заморозка». Полное удаление требует явно снять флаги и соблюсти порядок.


11. Карта документации и сервисов

  • Ресурс на сайте доков: https://tf-docs.nodejsk8s.dev.nubes.ru/<stand>/<service>/ (таблица атрибутов = схема); например /nubes-test/postgres/.
  • Машиночитаемая схема: …/<stand>/schema/<service>.json.
  • Готовые примеры (curated): …/<stand>/curated/… — приоритетны (проверены на деплоях).
  • Стенды: nubes-test, nubes-dev, nubes (prod).
  • Проверка файла через ЛЛМ: POST /<stand>/_api/file ({content, instruction}) → {content, changes, warnings}.
  • Справка по документации: POST /<stand>/_api/assist (ответ по шаблону Роль/Задача/Контекст/Требования/Ограничения).

12. Чего агент делать НЕ должен

  • Деплоить: terraform apply/destroy — только пользователь.
  • Удалять/менять реальные ресурсы и состояние Terraform.
  • Читать секреты из файлов пользователя и подставлять их в вывод.
  • Выдумывать параметры, значения, домены, UUID без источника (схема/ЛК/пользователь).
  • Навязывать свой workflow — помощь и проверка, а не «делай так, как я сказал».

13. Глоссарий

Термин Значение
realm / ресурсная платформа кластер Kubernetes, в котором разворачивается ресурс
resource_name имя услуги в ЛК; уникально внутри своего сервиса; используется для усыновления
sizing_policy профиль ресурсов (TKG 4CPU 8RAM и т.п.)
cluster_configuration размеры кластера: cpu (мили-ядра, 1000 = 1 vCPU), memory (МБ), replicas, disk (ГБ), shards
ipSpace пул внешних IP организации
vDC виртуальный датацентр (Cloud Director)
Edge сетевой шлюз периметра (NSX-T), балансировщик AVI
SNAT трансляция исходящего трафика через шлюз
vApp виртуальный каталог; контейнер для ВМ
suspend остановка ресурса с сохранением данных
adopt «усыновление» уже существующего ресурса по имени
ЛК Личный кабинет Nubes — веб-интерфейс управления услугами
услуга / инстанс конкретный объект в облаке, созданный по ресурсу
операция действие платформы над услугой: create/delete/modify/suspend/resume и др.
resource_name имя услуги в ЛК; по нему провайдер находит и усыновляет объект
startup_configuration параметры размещения (например resource_realm — кластер Kubernetes)
access_configuration сетевой доступ: IP-списки, внешний IP
backup_configuration резервное копирование: schedule (cron), retain (срок хранения)
json_env переменные окружения приложения (JSON)
git_revision версия кода приложения; смена значения → redeploy
domain доменное имя приложения (полный суффикс платформа добавляет сама)
HCL язык конфигурации Terraform (файлы .tf)
terraform.tfvars файл значений переменных; в этом репозитории — в .gitignore
terraform.tfstate файл состояния Terraform; хранит соответствие «код ↔ облако»