Модуль 08 — IaC: Terraform / OpenTofu ⭐⭐⭐

Кликать в консоли — это любитель. Профи описывают всю инфру кодом. Воспроизводимость, версионирование, code review для инфры.

Ландшафт инструментов

ИнструментКогда
TerraformСтандарт до 2023, сейчас под BSL-лицензией
OpenTofuOpen-source форк после смены лицензии. Учи его — синтаксис идентичен
PulumiTS/Python/Go вместо HCL. Растёт, но рынок меньше
AWS CDKPython/TS, генерирует CloudFormation. AWS-only
TerragruntWrapper для Terraform/OpenTofu — для масштабирования (DRY)
CrossplaneK8s-native IaC. Будущее для GitOps-команд
CloudFormationAWS native YAML. Legacy
После HashiCorp BSL (август 2023)

HashiCorp сменил лицензию Terraform на BSL. Linux Foundation запустил OpenTofu — open-source форк. Синтаксис идентичен. На вакансиях ещё долго будет «Terraform», но это синонимы. В новых проектах — часто OpenTofu.

HCL — язык Terraform

Структура проекта

infra/
├── modules/                  # переиспользуемые модули
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── versions.tf
│   ├── eks/
│   └── rds/
└── envs/
    ├── dev/
    │   ├── main.tf            # вызовы модулей
    │   ├── backend.tf
    │   └── terraform.tfvars
    ├── staging/
    └── prod/

Типичный main.tf

terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = { source = "hashicorp/aws", version = "~> 5.0" }
  }
  backend "s3" {
    bucket         = "my-tf-state-prod"
    key            = "envs/prod/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "tf-lock"
    encrypt        = true
    kms_key_id     = "alias/tf-state-key"
  }
}

provider "aws" {
  region = var.region
  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "terraform"
      Project     = "myapp"
    }
  }
}

variable "environment" {
  type    = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Must be dev, staging, or prod."
  }
}

locals {
  common_tags = {
    Environment = var.environment
    Owner       = "platform-team"
  }
}

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

  cidr = "10.0.0.0/16"
  azs  = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
  tags = local.common_tags
}

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

  cluster_name    = "myapp-${var.environment}"
  vpc_id          = module.vpc.vpc_id
  private_subnets = module.vpc.private_subnet_ids
  tags            = local.common_tags
}

output "cluster_endpoint" {
  value = module.eks.cluster_endpoint
}

Команды

terraform init              # инициализация, скачивание провайдеров
terraform fmt -recursive    # форматирование
terraform validate          # синтаксис
terraform plan              # ★ что изменится. ВСЕГДА смотри.
terraform plan -out=tf.plan
terraform apply tf.plan     # применить конкретный plan
terraform apply             # plan + apply одной командой
terraform destroy           # снести (осторожно)

terraform import aws_s3_bucket.b bucket-name   # затащить существующий ресурс
terraform state list
terraform state show aws_s3_bucket.b
terraform state mv old_addr new_addr           # переименование
terraform state rm aws_s3_bucket.b             # удалить из state, не из облака
terraform refresh                              # синк state с реальностью
terraform output                               # значения output

State — критическая концепция

⚠️ State содержит секреты

В state сохраняется ВСЁ что вернул API, включая пароли БД. Никогда не клади state в публичный git. S3 bucket — приватный, encryption ON, versioning ON, MFA Delete для prod.

Modules

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

modules/vpc/
├── main.tf          # ресурсы
├── variables.tf     # входы
├── outputs.tf       # выходы
├── versions.tf      # версии terraform и провайдеров
├── README.md        # документация (генерируется terraform-docs)
└── examples/        # примеры использования

Источники модулей

Pin версии: version = "~> 5.0" разрешает 5.x но не 6.0.

Public registry — сокровищница

registry.terraform.io — тысячи готовых модулей. Особенно: terraform-aws-modules (Anton Babenko) — production-ready модули для AWS.

Стратегии organizing

Workspaces — НЕ для production environments

Workspaces — для лабораторий и временных тестов. Не используй их для prod/dev — будет один state файл, разные namespace, легко перепутать.

Directory per environment ⭐ (рекомендуется)

См. структуру выше. Каждый env — своя директория, свой backend, свой state.

Terragrunt ⭐⭐ (для масштаба)

DRY-структура для десятков environments / regions / accounts. Один terragrunt.hcl в корне, остальное наследуется.

infra/
├── terragrunt.hcl              # root config: backend, providers
├── _envcommon/                 # общие настройки модулей
└── live/
    ├── prod/
    │   ├── env.hcl             # env-specific values
    │   ├── eu-west-1/
    │   │   ├── vpc/
    │   │   │   └── terragrunt.hcl    # inputs + include
    │   │   └── eks/
    │   └── us-east-1/
    └── staging/

Тестирование

  1. terraform fmt — форматирование
  2. terraform validate — синтаксис
  3. tflint — линтер на best practices
  4. tfsec / Checkov / KICS — security сканирование
  5. terraform test (с TF 1.6+) — встроенные тесты
  6. Terratest (Go) — интеграционные тесты, поднимает реальную инфру
  7. OPA / Conftest — policy as code на Rego

Best practices

  1. Никогда не редактируй ресурсы вручную в облаке после apply — drift убьёт нервы
  2. Pin версии провайдеров и модулей
  3. Один state — одна логическая инфра. Не пихай всё в один файл
  4. terraform plan в CI на каждый PR — обязательно, с комментарием diff
  5. apply через CI с одобрением, не локально в проде
  6. No secrets in code — Vault/SSM/env vars (TF_VAR_*)
  7. for_each вместо count — стабильнее при удалении
  8. Naming convention единая для всех ресурсов и тегов
  9. Все ресурсы — с тегами (Environment, Owner, ManagedBy)
  10. Code review каждого PR с plan-выводом

CI/CD pipeline для Terraform

Стадии:

  1. fmt check
  2. validate
  3. tflint
  4. tfsec / Checkov
  5. plan (на PR — комментарий с диффом)
  6. apply (после merge в main, с approval для prod)

Инструменты автоматизации

Drift detection

Drift — расхождение между state и реальностью (кто-то правил руками).

Сертификация

HashiCorp Certified: Terraform Associate (003) — несложная, ценится. Срок действия 2 года.

Чек-лист

Источники

IaC освоено. Дальше — CI/CD и GitOps.

Модуль 09 → CI/CD