add: documentation
This commit is contained in:
@@ -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..."
|
||||
```
|
||||
@@ -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`.
|
||||
- Для проблемного ресурса работайте в его отдельном стеке.
|
||||
Reference in New Issue
Block a user