add: documentation

This commit is contained in:
“Naeel”
2026-06-30 15:45:24 +04:00
parent 540c1f7293
commit ca276d200f
1055 changed files with 47294 additions and 0 deletions
+368
View File
@@ -0,0 +1,368 @@
# Начало работы с Nubes Terraform
Это руководство поможет вам установить инструменты, настроить доступ и развернуть вашу первую инфраструктуру в облаке Nubes, используя Terraform.
## 0. Установка Terraform
Для работы с инфраструктурой как кодом (IaC) потребуется утилита Terraform (версии 1.0 или выше).
1. **Скачивание**:
* Официальный сайт: [hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install)
* *Для пользователей из РФ (без VPN):* [Yandex Cloud Mirror](https://hashicorp-releases.yandexcloud.net/terraform/)
2. **Установка**:
* Распакуйте скачанный архив.
* Поместите исполняемый файл (`terraform` или `terraform.exe`) в папку, доступную в переменной окружения `PATH`.
3. **Проверка**:
* Откройте терминал (PowerShell, CMD, Bash или Terminal в macOS).
* Введите команду `terraform -version`. Вы должны увидеть номер версии.
## 1. Подготовка конфигурации
Создайте рабочую директорию для вашего проекта и создайте основной файл конфигурации `main.tf`.
```hcl title="main.tf"
terraform {
required_providers {
nubes = {
source = "terra.k8c.ru/nubes/nubes"
version = "2.1.23" # Поставьте нужную вам версию провайдера
}
}
}
provider "nubes" {
api_endpoint = "https://deck-api.ngcloud.ru/api/v1/index.cfm"
api_token = var.api_token
}
variable "api_token" {
type = string
sensitive = true
}
```
!!! info "TEST стенд (обязательные адреса)"
Эта документация относится к TEST стенду.
- Личный кабинет: https://deck-test.ngcloud.ru/dashboard/
- API endpoint: https://deck-api-test.ngcloud.ru/api/v1
!!! tip "Безопасность"
Никогда не храните токен прямо в файле `main.tf`, если планируете загружать код в систему контроля версий (git). Используйте `variables.tf` или файл `terraform.tfvars`.
## 2. Получение API токена
Токен (Access Token) необходим провайдеру для авторизации ваших действий в облаке.
Если нет ТОКЕНА доступа или хотите создать новый -
В Личном Кабинете - на странице Профиля пользователя https://deck.ngcloud.ru/authorization/profile
во вкладке Токены - нажать "Выпустить тех-токен"
Значение токена показывается только при его создании, надо его сохранить
Создайте файл `terraform.tfvars` и сохраните токен там:
```hcl title="terraform.tfvars"
api_token = "eyJhbGciOiJ..." # Ваш длинный токен
```
## 3. Описание ресурсов
Добавьте ресурсы, которые вы хотите создать, в файл `main.tf` или `resources.tf`.
Пример создания S3 бакета:
```hcl
resource "nubes_s3bucket" "my_files" {
resource_name = "bucket_0"
bucket_name = "my-unique-bucket-name"
s3_user_uid = "235e0546-..." # UID Корневой услуги S3
}
```
Или Postgres кластера:
```hcl
resource "nubes_postgres" "db" {
resource_name = "pg-tst0"
resource_realm = "k8s-3.ext.nubes.ru" # Платформа развертывания
s3_uid = "235e0546-..." # UUID услуги S3 для бэкапов
resource_c_p_u = 2000 # 2 vCPU (в милликорах)
resource_memory = 4096 # 4 GB (в МБ)
resource_disk = "20" # 20 GB
resource_instances = 1
}
```
Подробные примеры конфигураций смотрите в разделе **Resources** документации.
## 4. Запуск
Теперь вы готовы применить конфигурацию:
1. **Инициализация**: `terraform init` (загружает плагин провайдера).
2. **План**: `terraform plan` (показывает, что будет сделано).
3. **Применение**: `terraform apply` (создает инфраструктуру).
## 5. Почему провайдер использует Suspend/Adopt
Для этой логики используются два флага.
- `suspend_on_destroy`
- `adopt_existing_on_create`
### `suspend_on_destroy`
- `true` (по умолчанию)
- при `terraform destroy` инстанс уходит в `Suspend`;
- при удалении ресурса из манифеста — тоже `Suspend`.
- `false`
- Terraform удаляет ресурс только из state;
- в облаке инстанс не меняется.
### `adopt_existing_on_create`
- `false` (по умолчанию)
- если инстанс уже существует, Terraform вернёт ошибку.
- `true`
- Terraform может взять существующий инстанс под управление.
### Как это связано с `terraform import`
Это похоже на `terraform import`,
но срабатывает в обычном `apply`.
- найден `running` → `adopt`;
- найден `suspended` + обязательные параметры совпадают → `resume + adopt`.
### Важно
Один инстанс должен быть только в одном state.
Если подключить один инстанс
к двум манифестам,
получится конфликт управления:
- первый `apply` меняет ресурс;
- второй `apply` откатывает
или перезаписывает изменения.
---
Следующий шаг: изучите [Справочник по командам Terraform](terraform-basics.md) для уверенной работы.
## Примеры
### Lucee & Postgress
Lucee и NodeJS — это два отдельных UI для CRUD‑операций, оба работают с одной и той же таблицей в Postgres.
```hcl title="resources.tf"
resource "nubes_postgres" "db2" {
# Основной Postgres-кластер для демо.
resource_name = "pg-tst0"
s3_uid = "235e0546-..."
resource_realm = "k8s-3.ext.nubes.ru" # Платформа развертывания
resource_instances = 1
resource_memory = 512
resource_c_p_u = 500
resource_disk = "1"
app_version = "17"
json_parameters = jsonencode({
# Выключаем подробные логи подключений в демо.
log_connections = "off"
log_disconnections = "off"
})
enable_pg_pooler_master = false
enable_pg_pooler_slave = false
allow_no_s_s_l = false
auto_scale = false
auto_scale_percentage = 10
auto_scale_tech_window = 0
auto_scale_quota_gb = "1"
need_external_address_master = false
}
resource "nubes_lucee" "app1" {
# Lucee UI, который читает/пишет в Postgres.
resource_name = "lucy1"
resource_realm = nubes_postgres.db2.resource_realm
domain = "web03" # Пример домена приложения
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/testlucee.git"
json_env = jsonencode({
# JDBC datasource для Lucee.
testds_class = "org.postgresql.Driver"
testds_bundleName = "org.postgresql.jdbc"
testds_bundleVersion = "42.6.0"
testds_connectionString = "jdbc:postgresql://${nubes_postgres.db2.state_out_flat["internalConnect.master"]}:5432/postgres"
testds_username = nubes_postgres.db2.vault_secrets["adminUser"]
testds_password = nubes_postgres.db2.vault_secrets["adminPass"]
testds_connectionLimit = "5"
testds_liveTimeout = "15"
testds_validate = "false"
})
resource_c_p_u = 300
resource_memory = 512
resource_instances = 1
app_version = "5.4"
depends_on = [nubes_postgres.db2]
}
resource "nubes_nodejs" "app3" {
# NodeJS демо, работающий с тем же Postgres.
resource_name = "node_0"
resource_realm = nubes_postgres.db2.resource_realm
domain = "node"
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/testnode.git"
health_path = "/healthz"
app_version = "23"
json_env = jsonencode({
# Переменные подключения к Postgres.
PGHOST = nubes_postgres.db2.state_out_flat["internalConnect.master"]
PGPORT = "5432"
PGUSER = nubes_postgres.db2.vault_secrets["adminUser"]
PGPASSWORD = nubes_postgres.db2.vault_secrets["adminPass"]
PGSSLMODE = "require"
DATABASE_URL = format(
"postgresql://%s:%s@%s:5432/postgres",
nubes_postgres.db2.vault_secrets["adminUser"],
nubes_postgres.db2.vault_secrets["adminPass"],
nubes_postgres.db2.state_out_flat["internalConnect.master"]
)
})
resource_c_p_u = 300
resource_memory = 256
resource_instances = 1
depends_on = [nubes_postgres.db2]
}
```
### Пример (PROD_STAND/RABBIT)
Ниже полный пример `resources.tf` для RabbitMQ + Lucee UI + NodeJS воркера.
Комментарий: UI Lucee отправляет CRUD‑запросы в RabbitMQ, а применение изменений в Postgres выполняет отдельный воркер на NodeJS.
Сервис Postgres должен быть запущен заранее. В данном примере используется Postgres из раздела https://terra.k8c.ru/docs/nubes/nubes/2.1.7/30_registry/guides/getting-started/#lucee-postgress
```hcl title="resources.tf"
# RabbitMQ кластер для демо.
resource "nubes_rabbitmq" "rb1" {
resource_name = "rabbit_0"
resource_realm = "k8s-3.ext.nubes.ru"
resource_instances = 1
resource_memory = 512
resource_c_p_u = 500
resource_disk = 5
need_external_address_master = false
need_external_address_slave = false
}
# Lucee UI, который пишет в Rabbit и читает из Postgres.
resource "nubes_lucee" "rabbit_ui" {
resource_name = "rb-lucee-ui"
resource_realm = "k8s-3.ext.nubes.ru"
domain = "rb-ui"
app_version = "5.4"
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/rabbit-lsd"
resource_c_p_u = 300
resource_memory = 512
resource_instances = 1
# Переменные окружения для datasource, Rabbit и UI.
json_env = jsonencode({
testds_bundleName = "org.postgresql.jdbc"
testds_bundleVersion = "42.6.0"
testds_class = "org.postgresql.Driver"
testds_connectionLimit = "5"
testds_connectionString = "jdbc:postgresql://${var.PGHOST}:5432/postgres"
testds_liveTimeout = "15"
testds_username = var.PGUSER
testds_password = var.PGPASSWORD
testds_validate = "false"
PG_TABLE = "rabbit_messages"
UI_LOG_TABLE = "rabbit_ui_log"
RABBIT_HOST = try(nubes_rabbitmq.rb1.state_out_flat["internalConnect.master"], nubes_rabbitmq.rb1.state_out_flat["inernalConnect.master"])
RABBIT_PORT = "5672"
RABBIT_USER = nubes_rabbitmq.rb1.vault_secrets["adminUser"]
RABBIT_PASSWORD = nubes_rabbitmq.rb1.vault_secrets["adminPass"]
RABBIT_VHOST = "/"
RABBIT_QUEUES = "crud_queue"
RABBIT_DURABLE = "true"
RABBIT_ADMIN_URL = "https://${nubes_rabbitmq.rb1.state_out_flat["externalConnect.admin.fqdn"]}/#/"
NODEWORKER_URL = "https://nodeworker.nodejsk8s.services.ngcloud.ru/"
})
depends_on = [nubes_rabbitmq.rb1]
}
# NodeJS воркер, который переносит CRUD из очереди в Postgres.
resource "nubes_nodejs" "rabbit_nodeworker" {
resource_name = "nodeworker"
resource_realm = "k8s-3.ext.nubes.ru"
domain = "nodeworker"
app_version = "23"
git_path = "https://gitea-naeel.giteak8s.services.ngcloud.ru/naeel/rabbit-nodeworker.git"
health_path = "/healthz"
resource_c_p_u = 100
resource_memory = 256
resource_instances = 1
# Параметры подключения к Rabbit и Postgres.
json_env = jsonencode({
RABBIT_HOST = try(nubes_rabbitmq.rb1.state_out_flat["internalConnect.master"], nubes_rabbitmq.rb1.state_out_flat["inernalConnect.master"])
RABBIT_PORT = "5672"
RABBIT_USER = nubes_rabbitmq.rb1.vault_secrets["adminUser"]
RABBIT_PASSWORD = nubes_rabbitmq.rb1.vault_secrets["adminPass"]
RABBIT_VHOST = "/"
RABBIT_QUEUES = "crud_queue"
RABBIT_DURABLE = "true"
RABBIT_PREFETCH = "1"
REQUEUE_ON_ERROR = "true"
PGHOST = var.PGHOST
PGPORT = "5432"
PGUSER = var.PGUSER
PGPASSWORD = var.PGPASSWORD
PGDATABASE = "postgres"
PGSSLMODE = "require"
PG_TABLE = "rabbit_messages"
})
depends_on = [nubes_rabbitmq.rb1]
}
# Ручной триггер redeploy для воркера.
resource "nubes_nodejs_redeploy" "rabbit_nodeworker_redeploy" {
nodejs_id = nubes_nodejs.rabbit_nodeworker.id
resource_realm = "k8s-3.ext.nubes.ru"
run_id = "redeploy-2026-02-23-011"
}
```
```hcl title="variables.tf"
// Postgres уже запущен, значения берутся из UI Личного кабинета.
variable "PGUSER" {
type = string
default = "postgres"
}
variable "PGPASSWORD" {
type = string
default = "" # пароль укажите вручную, в примере не публикуем
}
variable "PGHOST" {
type = string
default = "postgresqlk8s-master.<id>.svc.k8s-3.ext.nubes.ru" # оставьте префикс и суффикс, меняется только <id>
}
```
```hcl title="terraform.tfvars"
# Инструкция по получению токена: раздел "Получение API токена"
api_token = "eyJhbGciOiJ..."
```
+53
View File
@@ -0,0 +1,53 @@
# Глоссарий терминов
## Apply
Применение изменений, описанных в Terraform конфигурации. Выполняет создание, изменение или удаление ресурсов.
## Destroy
Полное удаление ресурсов, описанных в конфигурации. Выполняется командой `terraform destroy`.
## Import
Подключение уже существующего ресурса к Terraform state. Импорт не создает ресурс, а только добавляет его в состояние.
Короткий пример:
```bash
terraform import nubes_vc_vm_v3.my_vm <resource_id>
```
## Manifest (манифест)
Набор `.tf` файлов в одной папке, которые Terraform рассматривает как единую конфигурацию.
## Module
Переиспользуемая часть конфигурации Terraform. Может использоваться для шаблонов и типовых наборов ресурсов.
## Plan
Просмотр изменений, которые Terraform собирается применить. Выполняется командой `terraform plan`.
## Resource
Описание управляемого объекта в Terraform. Например, виртуальная машина или сеть.
## Stack (стек)
Отдельный набор ресурсов Terraform, управляемый собственным `terraform state`. Обычно это отдельная папка с `.tf` файлами.
## State
Файл состояния Terraform, в котором хранится информация о созданных ресурсах и их текущих параметрах.
Удаление ресурса только из state (без удаления в облаке):
```bash
terraform state rm nubes_vc_vm_v3.my_vm
```
## Workspace
Логическое разделение одного и того же набора конфигураций по разным окружениям. Имеет отдельные state.
@@ -0,0 +1,79 @@
# S3 Bucket Notifications: изменения в бакете и вызов функции
## Короткий ответ
Да, для S3-совместимого хранилища можно вызывать обработчик при изменениях в бакете через стандартный механизм уведомлений:
- событие в бакете (`ObjectCreated`, `ObjectRemoved`),
- правило уведомления на бакете,
- destination (webhook/queue/topic),
- consumer/функция, которая принимает событие.
## Что проверено в нашем контуре
Проверка выполнялась удалённо (через SSH), не локально.
- API `deck-api-test.ngcloud.ru`:
- есть общий endpoint `/notifications`,
- явных endpoint'ов вида `bucketNotifications`, `events`, `webhooks` в этом API не обнаружено.
- Документация `docs.s3.msk-1.ngcloud.ru`:
- в публичных страницах не найден явный раздел про bucket notifications.
- Прямая проверка S3-слоя:
- `mc event ls <alias>/<bucket>` отработал успешно (код возврата `0`),
- это подтверждает доступность стандартной S3 операции чтения notification-конфигурации;
- пустой вывод означает, что правила ещё не заданы.
## Нужно ли задавать это при создании бакета
Рекомендуется задавать сразу в том же Terraform apply, но это отдельная конфигурация относительно самого факта создания бакета.
Практически правильно так:
1. Создать (или использовать) `S3 Storage service`.
2. Создать бакет.
3. Создать destination для событий (webhook/queue/topic).
4. Назначить notification rule на бакет.
5. Поднять consumer/функцию, которая обрабатывает событие.
## Как это выглядит архитектурно
```text
Bucket (ObjectCreated/ObjectRemoved)
-> Bucket Notification Rule
-> Destination (Webhook / Queue / Topic)
-> Function/Worker (business logic)
```
## Что это значит для Terraform
Лучший путь: один модуль/стек, где декларативно описано сразу всё:
- bucket,
- destination,
- notification rule,
- function/consumer.
Это даёт предсказуемый результат: после `apply` события бакета уже маршрутизируются в обработчик.
## Если notifications недоступны в конкретном backend
Fallback — polling:
- периодический опрос бакета,
- сравнение состояния (`key + etag/version_id + mtime`),
- вызов функции только на diff.
## Проверка и настройка через CLI
Пример скрипта в репозитории:
- `scripts/s3_notification_example.sh`
Скрипт:
- читает `.s3cfg`,
- показывает текущие правила,
- добавляет правило,
- показывает итоговую конфигурацию.
> Важно: для `event add` нужен существующий destination (`TARGET_ARN`) в S3/MinIO-конфигурации.
@@ -0,0 +1,99 @@
# Справочник по Terraform для начинающих
Terraform — это инструмент для управления инфраструктурой как кодом (IaC). Он позволяет вам описывать желаемое состояние вашей инфраструктуры в текстовых файлах, а затем автоматически создавать, изменять и удалять облачные ресурсы, чтобы они соответствовали этому описанию.
Здесь собраны основные команды, которые вы будете использовать в 99% случаев.
## Основной рабочий процесс
### 1. `terraform init`
**"Инициализация"**
Первая команда, которую нужно выполнить в новой директории с конфигурацией.
* Скачивает необходимые плагины (провайдеры), описанные в `main.tf`.
* Настраивает "бэкенд" (хранилище состояния).
```bash
terraform init
```
### 2. `terraform validate`
**"Проверка синтаксиса"**
Проверяет ваши файлы конфигурации (`.tf`) на наличие синтаксических ошибок и корректность использования атрибутов. Не обращается к облаку, только статический анализ.
```bash
terraform validate
```
### 3. `terraform plan`
**"План действий"**
Самая важная команда для безопасности. Она сравнивает ваш код с реальным состоянием облака и показывает, что *произойдет*, если вы примените изменения.
* `+` (зеленый): будет добавлено.
* `~` (желтый): будет изменено.
* `-` (красный): будет удалено.
```bash
terraform plan
```
### 4. `terraform apply`
**"Применение"**
Выполняет действия, запланированные на предыдущем шаге. Создает, меняет или удаляет реальные ресурсы в облаке Nubes.
* Всегда запрашивает подтверждение `yes` перед стартом (если не указан флаг `-auto-approve`).
```bash
terraform apply
```
### 5. `terraform destroy`
**"Уничтожение"**
Удаляет **все** ресурсы, описанные в текущей конфигурации Terraform. Используйте осторожно, чтобы очистить тестовое окружение.
* Также требует подтверждения `yes`.
```bash
terraform destroy
```
## Дополнительные полезные команды
* `terraform fmt`: Автоматически форматирует ваш код (расставляет отступы), делая его красивым и аккуратным.
* `terraform output`: Выводит значения "outputs", если вы их определили (например, IP-адреса созданных серверов).
* `terraform state list`: Показывает список ресурсов, про которые "знает" терраформ в данный момент.
## Когда использовать `terraform state rm`
`terraform state rm` удаляет ресурс **только из Terraform state**, но **не удаляет** его в облаке.
Используйте эту команду, когда:
* ресурс уже удалён в облаке вручную/вне Terraform;
* `plan` падает ошибкой вида "экземпляр ... удален";
* нужно заставить Terraform считать ресурс новым и создать его заново на следующем `apply`.
Пример:
```bash
terraform state rm nubes_postgres.db2
terraform plan
terraform apply
```
### Отличие от `terraform import`
* `terraform state rm` — "забыть" ресурс в state.
* `terraform import` — "подхватить" уже существующий ресурс в state.
Если ресурс в облаке действительно удалён, обычно нужен именно `state rm`, а не `import`.
---
!!! tip "Совет"
Всегда выполняйте `terraform plan` перед `apply`, чтобы убедиться, что вы случайно не удаляете важные ресурсы.
@@ -0,0 +1,67 @@
# Структура Terraform проекта
## Почему важно разделять манифесты
Если ресурсы не зависят друг от друга, лучше разделять их по разным папкам или разным state. Тогда сбой одного ресурса не блокирует применение остальных.
Если ресурсы взаимозависимы (например, сеть -> ВМ), их стоит держать вместе, чтобы Terraform применял изменения в правильном порядке.
## Важно: все .tf в папке объединяются
Terraform рассматривает все `.tf` в одной папке как единый конфигурационный файл. Это значит:
- Все ресурсы и переменные в папке находятся в одном graph.
- Ошибка одного ресурса может остановить `apply` для всех остальных.
- При `destroy` Terraform будет удалять все ресурсы из этой папки.
## Рекомендуемая структура
- Один каталог = один независимый стек.
- Для каждого стека отдельные `main.tf`, `variables.tf`, `outputs.tf`.
- Для разных окружений использовать разные каталоги.
Пример:
```
project/
stacks/
vm-a/
main.tf
variables.tf
vm-b/
main.tf
variables.tf
edge/
main.tf
variables.tf
```
## Импорт ресурсов
Импорт используется, когда ресурс уже существует, но Terraform его не создавал.
Общий подход:
1. Создать ресурс в `.tf` с корректными аргументами.
2. Выполнить `terraform import`.
3. Сделать `terraform plan` и убедиться, что нет изменений.
Важно:
- Импорт добавляет ресурс в state, но не создает его.
- После импорта нужно обязательно сверить параметры в `.tf`.
## Удаление ресурсов
Удаление зависит от того, где находится ресурс:
- Если ресурс прописан в `.tf`, Terraform удалит его при `destroy`.
- Если ресурс удален из `.tf`, Terraform удалит его при следующем `apply`.
Рекомендация: перед удалением делать `plan`, чтобы увидеть список ресурсов, которые будут удалены.
## Что делать при ошибках
- Разделяйте независимые ресурсы по разным папкам.
- Проверяйте `plan` перед `apply`.
- Для проблемного ресурса работайте в его отдельном стеке.