Шаг 0: Диагностика проблем монолита. Пора бить тревогу, если: применение изменений (apply) затрагивает несвязанные ресурсы; команда разработки блокируется из-за одного state-файла; время планирования (plan) превышает несколько минут; вы боитесь вносить изменения из-за риска сломать всё. Если это про вас — пора действовать.
Шаг 1: Внедрение удаленного бэкенда (Remote Backend). Самое первое и критически важное действие. Хранение `terraform.tfstate` локально или в репозитории — путь к катастрофе. Выберите удаленный бэкенд с поддержкой state-locking:
- **Terraform Cloud/Enterprise**: Нативный сервис с UI, управлением доступом, политиками (sentinel) и прогонами (runs).
- **AWS S3 + DynamoDB**: Классическая связка. S3 хранит state-файл, DynamoDB обеспечивает блокировку.
- **Google Cloud Storage (GCS)**: Автоматически обеспечивает блокировку.
- **Azure Storage Account**.
Шаг 2: Структурирование по средам (Directory per Environment). Первое логическое разделение. Создайте отдельные директории для разных сред, обычно `environments/dev`, `environments/staging`, `environments/prod`. В каждой будет свой конфигурационный файл Terraform и свой изолированный state-файл. Это предотвратит случайное воздействие на прод из-за изменений в dev. Используйте симлинки или общие модули (см. следующий шаг) для повторного использования кода между средами.
Шаг 3: Создание переиспользуемых модулей (Reusable Modules). Сердце масштабируемого Terraform. Модуль — это контейнер для нескольких ресурсов, которые вместе выполняют одну логическую функцию (например, модуль VPC, модуль Kubernetes кластера, модуль базы данных).
- Вынесите общую логику в отдельную директорию `modules/`. Например, `modules/network/vpc/`.
- Делайте модули идемпотентными и параметризуемыми через variables.
- Используйте outputs для передачи информации между модулями (например, ID созданной VPC).
- Версионируйте модули, используя Git теги или Terraform Registry.
Шаг 4: Принцип разделения state (State Isolation). Каждый независимый компонент инфраструктуры должен иметь свой state-файл. Не храните базу данных и кэш в одном state с сетевыми настройками. Это достигается за счет:
- **Модулей с удаленным state**. Модуль управляет своим state, но это сложно.
- **Логического разделения на «слои» (Layers)**. Более практичный подход. Создайте директории `layers/network`, `layers/data`, `layers/compute`. Каждый слой применяется отдельно, имеет свой бэкенд и state. Сначала применяется network, затем data (который может использовать outputs сети), потом compute. Это ускоряет apply и уменьшает blast radius при ошибках.
- Используйте файлы переменных (`terraform.tfvars`, `dev.tfvars`) для специфичных для среды значений.
- Для чувствительных данных (паролей, ключей) используйте защищенные переменные в Terraform Cloud или внешние системы (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager). Никогда не храните секреты в коде или в plain text в state-файле.
- Внедрите `locals` для вычисляемых значений и упрощения сложных выражений в ресурсах.
- Настройте pipeline в GitLab CI, GitHub Actions или Jenkins.
- Pipeline должен запускать `terraform fmt -check`, `terraform validate`, `terraform plan` при создании PR.
- Apply должен запускаться автоматически только после мержа в определенную ветку (например, `main` или `prod`), либо вручную подтверждаться через Terraform Cloud.
- Используйте инструменты безопасности на стадии plan: `tfsec`, `checkov`, `terrascan` для сканирования конфигураций на уязвимости.
- Используйте подход **Terragrunt** от Gruntwork. Это тонкая обертка над Terraform, которая помогает управлять множеством аккаунтов, регионов и сред, сохраняя код DRY (Don't Repeat Yourself). Он автоматически настраивает бэкенды и передает переменные.
- Либо используйте **Terraform Workspaces** (осторожно, они используют один бэкенд) для легкого разделения внутри одного аккаунта (например, разные регионы).
- Для мультиоблака (AWS + Azure + GCP) создавайте отдельные конфигурации для каждого провайдера, но старайтесь выносить общую логику в модули, где это возможно.
- Фиксируйте версии провайдеров в блоке `required_providers`. Не используйте `version = "> 2.0"`, чтобы избежать неожиданных breaking changes.
- Используйте **Terraform Lock File** (`.terraform.lock.hcl`), который следует коммитить в репозиторий для обеспечения консистентности версий плагинов в команде.
- Внедряйте политики контроля затрат и безопасности. В Terraform Enterprise/Cloud это Sentinel. В open-source можно использовать `terraform plan` с последующим парсингом вывода или OPA (Open Policy Agent).
- Регулярно (ежедневно/еженедельно) запускайте `terraform plan` в non-interactive режиме для обнаружения дрейфа.
- Настройте алерты, если план обнаруживает неожиданные изменения.
- Используйте такие инструменты, как `driftctl`, для постоянного мониторинга расхождений.
Комментарии (12)