Terraform: основы

Terraform — инструмент Infrastructure as Code от HashiCorp: описываешь облачные ресурсы (EC2, S3, RDS, DNS) в HCL-конфигах, terraform apply создаёт/обновляет/удаляет их автоматически.

Зачем нужно

Ручное создание ресурсов через AWS Console не воспроизводимо и не версионируется. Terraform позволяет описать всю инфраструктуру в коде, хранить в Git и применять через CI/CD. terraform plan показывает что изменится ДО применения — как dry-run для инфраструктуры.

Где используется

  • Создание VPC, EC2, RDS, S3, ALB на AWS
  • Управление DNS-записями (Route 53, Cloudflare)
  • Настройка Kubernetes-кластеров (EKS, GKE)
  • Multi-cloud: один инструмент для AWS + GCP + Azure

Основной контент

Установка

# macOS
brew install terraform

# Linux (Ubuntu)
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

terraform version

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

terraform/
├── main.tf           # основные ресурсы
├── variables.tf      # объявление переменных
├── outputs.tf        # выходные значения
├── terraform.tfvars  # значения переменных (в .gitignore если содержат секреты)
└── backend.tf        # конфигурация remote state

Основной конфиг (AWS)

# backend.tf — хранение state в S3
terraform {
  backend "s3" {
    bucket         = "my-terraform-state-bucket"
    key            = "prod/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-locks"   # блокировка для командной работы
    encrypt        = true
  }

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

provider "aws" {
  region = var.region
}

# variables.tf
variable "region" {
  default = "eu-west-1"
}
variable "environment" {}
variable "app_name" {}

# main.tf — EC2 + Security Group
resource "aws_security_group" "api" {
  name        = "${var.app_name}-api-sg"
  description = "API server security group"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "api" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.small"
  key_name               = aws_key_pair.deployer.key_name
  vpc_security_group_ids = [aws_security_group.api.id]

  tags = {
    Name        = "${var.app_name}-api"
    Environment = var.environment
  }
}

# outputs.tf
output "api_public_ip" {
  value = aws_instance.api.public_ip
}

Рабочий цикл

# 1. Инициализация (скачать провайдеры, настроить backend)
terraform init

# 2. Форматирование
terraform fmt

# 3. Валидация конфига
terraform validate

# 4. Plan — показать что будет сделано
terraform plan -var="environment=prod" -var="app_name=myapp"

# 5. Apply — применить изменения
terraform apply -var="environment=prod" -var="app_name=myapp"

# 6. Посмотреть state
terraform show
terraform state list

# 7. Уничтожить инфраструктуру
terraform destroy

Частые ошибки

  • Хранить terraform.tfstate в Git — содержит секреты в открытом виде; использовать S3 backend
  • Не использовать terraform plan перед apply — можно случайно удалить ресурсы с данными
  • Хардкодить AWS Access Key в provider блоке — использовать переменные окружения AWS_ACCESS_KEY_ID
  • Не блокировать версию провайдера (version = "~> 5.0") — обновление может сломать конфиг

Связанные темы

Ресурсы