# Terraform Modules с AI: Infrastructure-as-Code для стартапов без DevOps-инженера

> Как генерировать Terraform-модули с помощью AI: промпты для AWS и GCP, управление state, структура проекта, best practices. Рабочие примеры для продакшена.
> Author: Roman Belov · Published: 2026-07-12 · Source: https://futurecraft.pro/ru/blog/terraform-modules-ai/

Каждый ресурс, созданный через веб-консоль облачного провайдера, невозможно воспроизвести, откатить или передать новому разработчику. Когда команда вырастает до пяти человек, инфраструктурный долг начинает тормозить релизы.

Terraform решает эту проблему: вся инфраструктура описана в коде, хранится в Git, применяется одной командой. Но у стартапов нет DevOps-инженера, который напишет модули с нуля. AI-модели закрывают этот разрыв. Один структурированный промпт генерирует Terraform-модуль, который проходит `terraform validate` и закрывает большинство типичных сценариев.

В этой статье: от нуля до рабочей инфраструктуры. Промпты для генерации модулей, примеры для AWS и GCP, управление state, безопасность и паттерны, которые предотвращают типичные ошибки новичков.

## Terraform за 10 минут: минимум для старта

Terraform оперирует тремя концепциями: провайдеры, ресурсы и state.

**Провайдер** подключает Terraform к облачной платформе. AWS, GCP, Azure, Cloudflare — для каждого свой провайдер. Провайдер знает API платформы и транслирует HCL-код в API-вызовы.

**Ресурс** описывает один объект инфраструктуры: виртуальную машину, базу данных, DNS-запись, S3-бакет. Ресурсы связаны между собой через ссылки: сервер использует подсеть, подсеть принадлежит VPC.

**State** хранит текущее состояние инфраструктуры. Terraform сравнивает state с описанием в коде и вычисляет diff: что создать, что изменить, что удалить. Без state Terraform не знает, какие ресурсы уже существуют.

Минимальная структура проекта:

```
infrastructure/
├── main.tf          # Ресурсы
├── variables.tf     # Входные параметры
├── outputs.tf       # Выходные значения
├── providers.tf     # Настройка провайдеров
└── terraform.tfvars # Значения переменных (не коммитить секреты)
```

Рабочий цикл состоит из четырёх команд:

```bash
terraform init      # Скачивает провайдеры
terraform plan      # Показывает что изменится
terraform apply     # Применяет изменения
terraform destroy   # Удаляет всё (осторожно)
```

`terraform plan` — самая важная команда. Она показывает diff между кодом и реальной инфраструктурой до того, как что-то изменится. Всегда проверяйте plan перед apply.

## Модули: переиспользуемые блоки инфраструктуры

Модуль в Terraform — это директория с `.tf`-файлами, которую можно вызвать из другого кода с параметрами. Тот же принцип, что и функция в программировании: входные параметры, логика, выходные значения.

Структура модуля:

```
modules/
└── vpc/
    ├── main.tf        # Ресурсы VPC, подсети, роутинг
    ├── variables.tf   # Параметры: CIDR, количество AZ, теги
    └── outputs.tf     # VPC ID, subnet IDs
```

Вызов модуля из корневого конфига:

```hcl
module "network" {
  source = "./modules/vpc"

  cidr_block         = "10.0.0.0/16"
  availability_zones = ["us-east-1a", "us-east-1b"]
  project_name       = "myapp"
  environment        = "production"
}
```

Модули решают три задачи сразу. Модуль описывается один раз и вызывается для каждого окружения — dev, staging, production — с разными параметрами. Он инкапсулирует сложность: вызывающий код передаёт пять параметров вместо описания двадцати связанных ресурсов. И его можно протестировать отдельно от остальной инфраструктуры.

## Промпты для генерации Terraform-модулей

AI-модель генерирует Terraform-код тем точнее, чем конкретнее описан контекст. Промпт должен содержать шесть элементов:

1. **Облачный провайдер и регион** — AWS us-east-1, GCP europe-west1
2. **Что создать** — конкретные ресурсы и связи между ними
3. **Параметризация** — что должно быть переменной, а что захардкожено
4. **Безопасность** — сетевые ограничения, IAM-роли, шифрование
5. **Теги и именование** — конвенция имён, обязательные теги
6. **Ограничения** — версия Terraform, версия провайдера, запрещённые ресурсы

Базовый шаблон промпта:

```
Сгенерируй Terraform-модуль для [облачный провайдер].

Ресурсы:
- [список ресурсов с ключевыми параметрами]

Требования:
- Terraform >= 1.5, провайдер [имя] >= [версия]
- Все ресурсы в [регион]
- Переменные: [что параметризовать]
- Выходы: [что экспортировать]
- Security: [конкретные ограничения]
- Теги: project, environment, managed_by = "terraform"

Структура:
- main.tf, variables.tf, outputs.tf, versions.tf
- Описания для каждой переменной
- Валидация для критичных переменных (CIDR, имена)

Не используй: [запрещённые паттерны]
```

Промпт без секции безопасности выдаёт ресурсы с `0.0.0.0/0` в security groups и без шифрования. Промпт без ограничений на версии выдаёт код, который сломается при обновлении провайдера. Каждая секция предотвращает конкретную категорию ошибок.

## Пример: AWS VPC + ECS Fargate

Промпт для генерации полного стека приложения на AWS:

```
Сгенерируй Terraform-модуль: AWS VPC с ECS Fargate.

Ресурсы:
- VPC с 2 public и 2 private подсетями в разных AZ
- NAT Gateway (один, для экономии)
- ECS Cluster с Fargate capacity provider
- ECS Service + Task Definition для контейнера
- Application Load Balancer в public подсетях
- Security Groups: ALB принимает 80/443, ECS принимает только от ALB
- CloudWatch Log Group для контейнера

Переменные:
- vpc_cidr (default "10.0.0.0/16", с валидацией CIDR формата)
- container_image (string, без default)
- container_port (number, default 8080)
- cpu, memory (number, defaults 256/512)
- desired_count (number, default 2)
- environment (string, validation: dev|staging|production)
- project_name (string)

Выходы:
- vpc_id, public_subnet_ids, private_subnet_ids
- alb_dns_name, ecs_cluster_arn, ecs_service_name

Terraform >= 1.5, AWS provider >= 5.0.
Все ресурсы в переменной aws_region (default us-east-1).
Теги: Project, Environment, ManagedBy = "terraform".
```

Результат содержит 150–200 строк HCL-кода. AI-модель создаёт правильные связи между ресурсами: ECS task definition ссылается на log group, security group ECS-сервиса разрешает трафик только от security group ALB, private подсети используют NAT Gateway для исходящего трафика.

Ключевые моменты, которые нужно проверить в сгенерированном коде:

```hcl
# Security group ECS — трафик только от ALB
resource "aws_security_group_rule" "ecs_ingress" {
  type                     = "ingress"
  from_port                = var.container_port
  to_port                  = var.container_port
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.alb.id
  security_group_id        = aws_security_group.ecs.id
}

# Task definition — лимиты ресурсов заданы явно
resource "aws_ecs_task_definition" "app" {
  family                   = "${var.project_name}-${var.environment}"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = var.cpu
  memory                   = var.memory
  execution_role_arn       = aws_iam_role.ecs_execution.arn

  container_definitions = jsonencode([{
    name      = var.project_name
    image     = var.container_image
    essential = true
    portMappings = [{
      containerPort = var.container_port
      protocol      = "tcp"
    }]
    logConfiguration = {
      logDriver = "awslogs"
      options = {
        "awslogs-group"         = aws_cloudwatch_log_group.app.name
        "awslogs-region"        = var.aws_region
        "awslogs-stream-prefix" = "ecs"
      }
    }
  }])
}
```

Если AI-модель пропустила `execution_role_arn` в task definition или не создала IAM-роль с policy `AmazonECSTaskExecutionRolePolicy`, контейнер не запустится. Это частая ошибка генерации, которую нужно отлавливать на этапе review.

## Пример: GCP Cloud Run + Cloud SQL

Тот же подход для Google Cloud:

```
Сгенерируй Terraform-модуль: GCP Cloud Run + Cloud SQL PostgreSQL.

Ресурсы:
- VPC с private subnet
- Cloud SQL PostgreSQL 15 (db-f1-micro для dev, db-custom для prod)
- Private IP для Cloud SQL через VPC peering
- Cloud Run service с подключением к SQL через VPC connector
- Serverless VPC Connector
- Secret Manager для database password
- IAM bindings: Cloud Run SA с ролями cloudsql.client, secretmanager.secretAccessor

Переменные:
- project_id (string)
- region (default "europe-west1")
- database_name (string)
- cloud_run_image (string)
- cloud_run_cpu, cloud_run_memory (defaults "1", "512Mi")
- min_instances, max_instances (defaults 0, 10)
- environment (validation: dev|staging|production)

Выходы:
- cloud_run_url, cloud_sql_connection_name
- vpc_connector_id, database_ip

Terraform >= 1.5, Google provider >= 5.0.
Включить необходимые API через google_project_service.
```

GCP требует явного включения API (`compute.googleapis.com`, `run.googleapis.com`, `sqladmin.googleapis.com`). AI-модели часто пропускают этот шаг. Добавление строки «Включить необходимые API через google_project_service» в промпт заставляет модель генерировать блоки:

```hcl
resource "google_project_service" "required" {
  for_each = toset([
    "compute.googleapis.com",
    "run.googleapis.com",
    "sqladmin.googleapis.com",
    "vpcaccess.googleapis.com",
    "secretmanager.googleapis.com",
  ])

  project = var.project_id
  service = each.value

  disable_dependent_services = false
  disable_on_destroy         = false
}
```

`disable_on_destroy = false` критичен. Без него `terraform destroy` отключит API, что может сломать другие ресурсы в проекте, не управляемые этим Terraform-кодом.

## Управление state: remote backend

По умолчанию Terraform хранит state в локальном файле `terraform.tfstate`. Для команды это не работает: state должен быть доступен всем и защищён от параллельных изменений.

Remote backend для AWS (S3 с нативной блокировкой):

```hcl
terraform {
  backend "s3" {
    bucket       = "mycompany-terraform-state"
    key          = "production/infrastructure.tfstate"
    region       = "us-east-1"
    encrypt      = true
    use_lockfile = true  # нативная блокировка S3, Terraform 1.11+
  }
}
```

Remote backend для GCP (GCS):

```hcl
terraform {
  backend "gcs" {
    bucket = "mycompany-terraform-state"
    prefix = "production/infrastructure"
  }
}
```

Промпт для генерации backend-инфраструктуры:

```
Сгенерируй Terraform-код для создания remote backend.

AWS вариант:
- S3 bucket с versioning и server-side encryption (AES256)
- Bucket policy: запретить удаление объектов
- Lifecycle rule: хранить noncurrent versions 90 дней

Блокировка state — нативная в S3 через use_lockfile, отдельная DynamoDB-таблица не нужна.
Не использовать backend block в этом коде (chicken-and-egg problem).
State этого кода хранится локально.
```

Важный нюанс: инфраструктура для хранения state создаётся отдельным Terraform-проектом с локальным state. Это решает проблему курицы и яйца. AI-модели иногда добавляют `backend` block в код, который создаёт сам бакет для state. Промпт с явным запретом предотвращает эту ошибку.

## State: безопасность и операции

State-файл содержит секреты. Пароли баз данных, ключи API, приватные IP-адреса — всё попадает в state в открытом виде. Три правила:

**Шифрование.** S3 backend поддерживает `encrypt = true`. GCS шифрует объекты по умолчанию. Для дополнительной защиты используйте KMS-ключ вместо managed encryption.

**Доступ.** Ограничьте доступ к бакету со state. Только CI/CD pipeline и администраторы. Terraform Cloud и HCP Terraform решают это из коробки.

**Блокировка.** S3 блокирует state нативно через `use_lockfile = true` (Terraform 1.11+). DynamoDB-локи, которые раньше были стандартом, помечены deprecated и будут удалены в будущих версиях. GCS блокирует по умолчанию. Без блокировки два параллельных `terraform apply` повредят state-файл.

Операции со state, которые понадобятся:

```bash
# Посмотреть текущие ресурсы в state
terraform state list

# Переместить ресурс (при рефакторинге модулей)
terraform state mv 'module.old.aws_instance.web' 'module.new.aws_instance.web'

# Импортировать существующий ресурс (уже создан вручную)
terraform import 'aws_s3_bucket.data' 'my-existing-bucket'

# Убрать ресурс из управления (без удаления)
terraform state rm 'aws_instance.temporary'
```

`terraform import` особенно полезен для стартапов, которые уже создали инфраструктуру через консоль. Вместо пересоздания ресурсов можно импортировать существующие в state и дальше управлять через код.

## Промпты для итеративного улучшения модулей

Первая версия модуля от AI закрывает базовые потребности. Следующие промпты добавляют production-hardening:

**Добавить мониторинг:**

```
К существующему модулю ECS Fargate добавь:
- CloudWatch alarms: CPU > 80%, Memory > 80%, UnhealthyHostCount > 0
- SNS Topic для нотификаций (email подписка через переменную)
- Dashboard с графиками CPU, Memory, Request Count, Response Time

Alarm actions указывают на SNS topic.
Не изменяй существующие ресурсы.
```

**Добавить autoscaling:**

```
К ECS Service добавь Application Auto Scaling:
- Target tracking по CPU utilization (target 70%)
- Target tracking по Memory utilization (target 75%)
- Scale-in cooldown 300s, scale-out cooldown 60s
- Min capacity из переменной, max capacity из переменной

Используй aws_appautoscaling_target и aws_appautoscaling_policy.
```

**Добавить DNS и HTTPS:**

```
К существующему ALB добавь:
- Route53 record (A alias) для домена из переменной
- ACM certificate с DNS validation
- HTTPS listener (443) на ALB
- Redirect HTTP → HTTPS
- Route53 validation records для ACM

Переменные: domain_name, route53_zone_id.
```

Каждый промпт расширяет модуль одной функцией. Это проще для review и отладки, чем генерировать всё сразу. AI-модель лучше справляется с инкрементальными задачами, когда контекст ограничен конкретным изменением.

## Структура проекта для нескольких окружений

Стартап начинает с одного окружения, но быстро дорастает до трёх: dev, staging, production. Terraform-модули позволяют переиспользовать код между окружениями.

Рекомендуемая структура:

```
infrastructure/
├── modules/
│   ├── networking/    # VPC, подсети, NAT
│   ├── compute/       # ECS/Cloud Run, task definitions
│   ├── database/      # RDS/Cloud SQL
│   └── monitoring/    # CloudWatch/Cloud Monitoring
├── environments/
│   ├── dev/
│   │   ├── main.tf        # Вызовы модулей
│   │   ├── variables.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   ├── staging/
│   │   └── ...
│   └── production/
│       └── ...
└── global/
    ├── iam/           # IAM roles, policies
    └── dns/           # Route53 zones
```

Каждое окружение вызывает те же модули с разными параметрами:

```hcl
# environments/dev/main.tf
module "network" {
  source = "../../modules/networking"

  cidr_block    = "10.0.0.0/16"
  nat_gateway   = false  # Экономия в dev
  project_name  = "myapp"
  environment   = "dev"
}

module "compute" {
  source = "../../modules/compute"

  vpc_id            = module.network.vpc_id
  subnet_ids        = module.network.private_subnet_ids
  container_image   = "myapp:latest"
  desired_count     = 1       # Минимум в dev
  cpu               = 256
  memory            = 512
  environment       = "dev"
}
```

```hcl
# environments/production/main.tf
module "network" {
  source = "../../modules/networking"

  cidr_block    = "10.1.0.0/16"
  nat_gateway   = true   # Обязательно в production
  project_name  = "myapp"
  environment   = "production"
}

module "compute" {
  source = "../../modules/compute"

  vpc_id            = module.network.vpc_id
  subnet_ids        = module.network.private_subnet_ids
  container_image   = "myapp:v1.2.3"
  desired_count     = 3       # Redundancy
  cpu               = 1024
  memory            = 2048
  environment       = "production"
}
```

Dev обходится без NAT Gateway ($32/мес) и запускает один контейнер. Production включает NAT, три контейнера и больше ресурсов. Тот же код, разные параметры.

## Валидация сгенерированного кода

AI-модель в большинстве случаев генерирует синтаксически корректный HCL. Оставшиеся случаи ловятся на этапе валидации. Три уровня проверки:

**Уровень 1: Terraform CLI**

```bash
terraform init
terraform validate
terraform plan
```

`validate` проверяет синтаксис и ссылки между ресурсами. `plan` проверяет, что провайдер принимает указанные параметры. Если `plan` выдаёт ошибку, скопируйте сообщение обратно в AI-модель с промптом «Исправь эту ошибку в Terraform-коде» и приложите полный файл.

**Уровень 2: tflint**

```bash
# Установка
brew install tflint    # macOS
tflint --init          # Скачать плагины

# Запуск
tflint --recursive
```

tflint находит ошибки, которые `terraform validate` пропускает: устаревшие типы инстансов, несуществующие AMI, неоптимальные конфигурации. Промпт для исправления: «tflint выдаёт предупреждения [список]. Исправь модуль, сохраняя функциональность.»

**Уровень 3: checkov (безопасность)**

```bash
pip install checkov
checkov -d .
```

checkov проверяет конфигурацию на соответствие best practices безопасности: шифрование включено, публичный доступ закрыт, логирование настроено. Типичные findings после AI-генерации:

- S3 bucket без `block_public_access`
- Security group с `0.0.0.0/0` на ingress
- RDS без `storage_encrypted = true`
- CloudWatch log group без `retention_in_days`

Каждый finding из checkov превращается в промпт для AI: «Добавь в S3 bucket ресурс aws_s3_bucket_public_access_block с block_public_acls = true, block_public_policy = true, ignore_public_acls = true, restrict_public_buckets = true.»

## Best practices для Terraform с AI

**Версии провайдеров.** Всегда фиксируйте версии в `versions.tf`:

```hcl
terraform {
  required_version = ">= 1.5"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}
```

`~> 5.0` разрешает `5.x`, но не `6.0`. Без фиксации `terraform init` может скачать новую мажорную версию провайдера, которая сломает существующий код.

**Именование.** Используйте единую конвенцию. Промпт «Все имена ресурсов в формате {project}-{environment}-{resource}» заставляет AI-модель генерировать консистентные имена вместо произвольных.

**Не хардкодьте AMI и machine types.** Используйте data sources:

```hcl
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}
```

Захардкоженный AMI ID привязан к конкретному региону и устаревает через месяцы. Data source всегда выбирает актуальный образ.

**Используйте `terraform plan` в CI/CD.** Каждый pull request с изменениями инфраструктуры должен запускать `terraform plan` и показывать diff в комментарии. Подробный гайд по настройке CI/CD-пайплайна для Terraform есть в [статье про генерацию CI/CD пайплайнов](/ru/blog/cicd-pipeline-generator/).

**Никогда не коммитьте tfvars с секретами.** `.gitignore` должен содержать:

```
*.tfvars
!terraform.tfvars.example
.terraform/
*.tfstate
*.tfstate.backup
```

Секреты передавайте через переменные окружения (`TF_VAR_database_password`) или через secret manager провайдера.

**Разделяйте state по контурам.** Один state-файл на окружение. Dev и production никогда не живут в одном state. Ошибка в dev не должна иметь возможность затронуть production-ресурсы.

## Типичные ошибки AI-генерации и как их предотвращать

AI-модели допускают предсказуемые ошибки в Terraform-коде. Зная паттерны, можно добавлять превентивные инструкции в промпт.

**Циклические зависимости.** AI создаёт security group A, которая ссылается на security group B, которая ссылается на A. Terraform выдаёт ошибку цикла. Решение: выносите правила в отдельные ресурсы вместо inline `ingress`/`egress` блоков — в AWS-провайдере 5.0+ это `aws_vpc_security_group_ingress_rule` и `aws_vpc_security_group_egress_rule` (по одному правилу на ресурс; старый `aws_security_group_rule` ещё работает, но новые ресурсы предпочтительнее). Добавьте в промпт: «Security group rules через отдельные ресурсы, не inline.»

**Забытые depends_on.** Некоторые зависимости между ресурсами Terraform не выводит автоматически. Пример: IAM role policy attachment должна быть создана до ECS task, но Terraform не видит эту связь через `jsonencode`. Добавьте: «Используй depends_on для неявных зависимостей: IAM policy attachments → compute resources.»

**Избыточные permissions.** AI-модель часто выдаёт `Action: "*"` и `Resource: "*"` в IAM policies. Добавьте в промпт: «IAM policies с минимальными правами. Конкретные Actions и Resources. Никаких wildcards, кроме случаев, где это единственный вариант.»

**Отсутствие lifecycle rules.** AI создаёт ресурсы без `prevent_destroy` для критичных данных и без `create_before_destroy` для ресурсов с zero-downtime требованием:

```hcl
resource "aws_db_instance" "main" {
  # ...
  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_ecs_service" "app" {
  # ...
  lifecycle {
    create_before_destroy = true
  }
}
```

Добавьте в промпт: «lifecycle prevent_destroy для баз данных и state buckets. create_before_destroy для compute-ресурсов.»

## Миграция с ручной инфраструктуры на Terraform

Стартап с существующей инфраструктурой в облаке может перейти на Terraform без пересоздания ресурсов. Алгоритм:

1. Опишите существующие ресурсы в Terraform-коде (AI-модель поможет по описанию из консоли)
2. Импортируйте каждый ресурс: `terraform import aws_instance.web i-1234567890abcdef0`
3. Запустите `terraform plan`. Diff должен быть пустым
4. Если plan показывает изменения, скорректируйте код до полного совпадения с реальностью
5. Теперь ресурсами управляет Terraform

Промпт для шага 1:

```
У меня есть EC2 инстанс со следующими параметрами:
- Instance type: t3.medium
- AMI: ami-0abcdef1234567890
- VPC: vpc-12345, Subnet: subnet-67890
- Security groups: sg-11111, sg-22222
- EBS: 50GB gp3, encrypted
- Tags: Name=web-server, Environment=production

Сгенерируй Terraform resource block, который точно описывает
этот инстанс. Включи все параметры, которые Terraform отслеживает.
Не пропускай default values, если они отличаются от реальной конфигурации.
```

Для массовой миграции существует `terraformer` — инструмент, который автоматически генерирует Terraform-код из существующей инфраструктуры. Но сгенерированный код требует рефакторинга: он плоский, без модулей, без переменных. AI-модель отлично справляется с рефакторингом terraformer-вывода в чистую модульную структуру.

## Что дальше

Terraform-модули с AI закрывают большую часть потребностей стартапа в управлении инфраструктурой. Следующие шаги зависят от масштаба:

**До 10 разработчиков:** локальный state в S3/GCS, ручной `terraform apply`, code review для `.tf`-файлов. Этого достаточно.

**10–30 разработчиков:** Terraform Cloud или Atlantis для автоматического `plan` на PR и `apply` на merge. Sentinel или OPA для policy-as-code.

**30+ разработчиков:** Platform team, внутренний registry модулей, self-service через Internal Developer Platform.

Для каждого этапа AI-модели генерируют необходимые конфигурации. Подход из этой статьи масштабируется вместе с командой: меняются только промпты и уровень абстракции модулей.

Настройка CI/CD для автоматического apply описана в [гайде по генерации пайплайнов](/ru/blog/cicd-pipeline-generator/). Паттерн circuit breaker для защиты инфраструктурных API-вызовов от каскадных отказов разобран в [статье про resilience в edge functions](/ru/blog/circuit-breaker-deno-edge-functions/).

---

*Нужна помощь с Infrastructure-as-Code? Я помогаю стартапам внедрять AI-решения и строить продукты — [belov.works](https://belov.works).*

## FAQ

**Как безопасно рефакторить существующий модуль, не сломав production-инфраструктуру?**

Ключ — манипуляции со state до изменений кода. Перед реструктуризацией модуля выполняйте `terraform state mv`, чтобы переместить ресурсы на новые логические адреса в state — это сообщает Terraform, что ресурс уже существует по новому пути, а не является операцией «удалить и создать». После каждого перемещения запускайте `terraform plan` и убеждайтесь, что diff не содержит деструктивных изменений. Для сложных рефакторингов с большим числом ресурсов сначала отработайте процесс на non-production окружении, сравните plan до и после, и только затем применяйте те же операции к production.

**Как передавать секреты, нужные Terraform при apply, не сохраняя их в state?**

State-файл Terraform хранит атрибуты ресурсов в открытом виде, включая чувствительные значения. Практическое решение: никогда не передавать реальные значения секретов через Terraform-переменные — вместо этого использовать нативные ссылки провайдера. Для AWS: хранить учётные данные в Secrets Manager и ссылаться на них через data source `aws_secretsmanager_secret_version`, который подставляет значение только в момент создания ресурса. Цель — чтобы в `terraform.tfstate` оставалась только ссылка (ARN, путь), а не само значение секрета.

**Как AI-модели справляются с обновлениями версий Terraform-провайдеров и что требует обязательной ручной проверки?**

AI генерирует синтаксически корректный код для той версии провайдера, на которой обучена, но API провайдеров меняется между мажорными версиями: аргументы ресурсов переименовываются, устаревают или удаляются. При обновлении провайдеров используйте `terraform providers lock` для фиксации новой версии и запускайте `terraform plan` для обнаружения ошибок — вставляйте эти ошибки обратно в модель с полным блоком ресурса и выдержкой из changelog провайдера. Ручная проверка обязательна для IAM-политик (AI склонен к избыточным правам), lifecycle rules (особенно `prevent_destroy`) и ресурсов, управляющих настройками шифрования.
