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") — обновление может сломать конфиг
Связанные темы
- _MOC DevOps
- Infrastructure as Code -- IaC
- AWS -- обзор сервисов для веб-разработчика
- AWS EC2 -- виртуальные серверы