Два подхода к разделению окружений в Terraform:
Подход 1: Workspaces. Один набор .tf файлов, переключение между окружениями через terraform workspace select:
# Workspaces — один код, разные state-файлы
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
terraform workspace select prod
terraform plan -var-file=prod.tfvars
# В коде используем terraform.workspace:
resource "aws_instance" "web" {
instance_type = terraform.workspace == "prod" ? "m5.2xlarge" : "t3.medium"
count = terraform.workspace == "prod" ? 3 : 1
tags = {
Environment = terraform.workspace
}
}
Подход 2: Directory per environment. Отдельная директория для каждого окружения с собственным backend и variables:
# Структура проекта — directory per environment
infrastructure/
├── modules/ # Переиспользуемые модули
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── compute/
│ ├── database/
│ └── monitoring/
├── environments/
│ ├── dev/
│ │ ├── main.tf # Вызов модулей с dev-параметрами
│ │ ├── backend.tf # S3 key: dev/infrastructure.tfstate
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ ├── backend.tf # S3 key: staging/infrastructure.tfstate
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ ├── backend.tf # S3 key: prod/infrastructure.tfstate
│ ├── variables.tf
│ └── terraform.tfvars
└── global/ # Ресурсы общие для всех окружений
├── iam/
├── dns/
└── ecr/
Мы выбрали directory per environment по нескольким причинам:
- Окружения изолированы полностью — ошибка в dev не может затронуть prod state.
- Prod может иметь ресурсы, которых нет в dev (WAF, CloudTrail, дополнительные реплики).
- В CI/CD проще:
cd environments/prod && terraform apply.
- Workspace не поддерживает разные provider versions между окружениями.
Пример main.tf для prod-окружения:
# environments/prod/main.tf
module "networking" {
source = "../../modules/networking"
environment = "prod"
vpc_cidr = "10.0.0.0/16"
azs = ["eu-central-1a", "eu-central-1b", "eu-central-1c"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
private_subnets = ["10.0.10.0/24", "10.0.11.0/24", "10.0.12.0/24"]
}
module "database" {
source = "../../modules/database"
environment = "prod"
instance_class = "db.r6g.xlarge"
multi_az = true
backup_retention_period = 30
subnet_ids = module.networking.private_subnet_ids
vpc_id = module.networking.vpc_id
}
module "compute" {
source = "../../modules/compute"
environment = "prod"
instance_type = "m5.2xlarge"
min_size = 3
max_size = 10
desired_size = 3
subnet_ids = module.networking.private_subnet_ids
vpc_id = module.networking.vpc_id
db_endpoint = module.database.endpoint
}
Оставить комментарий