Пример 1: S3-бакет (базовый старт)
Первый пример из лекции — создание S3-бакета. Минимальная конфигурация для понимания рабочего цикла Terraform.
Структура файлов
s3-bucket-example/
├── providers.tf # провайдер AWS
├── main.tf # ресурс S3
├── variables.tf # переменные
├── terraform.tfvars # значения переменных
└── outputs.tf # имя и ARN бакета
providers.tf — настройка провайдера
# providers.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
# Credentials автоматически из ~/.aws/credentials
}
variables.tf — объявление переменных
# variables.tf
variable "aws_region" {
description = "Регион AWS"
type = string
default = "eu-central-1"
}
variable "bucket_name" {
description = "Глобально уникальное имя S3-бакета"
type = string
default = "pd2025-myname-bucket"
}
variable "environment" {
description = "Название окружения (dev/staging/prod)"
type = string
default = "dev"
}
terraform.tfvars — значения переменных
# terraform.tfvars
aws_region = "eu-central-1"
bucket_name = "pd2025-myname-bucket"
environment = "dev"
main.tf — ресурс S3-бакета
# main.tf
resource "aws_s3_bucket" "app_bucket" {
bucket = var.bucket_name
tags = {
Name = var.bucket_name
Environment = var.environment
ManagedBy = "Terraform"
}
}
outputs.tf — вывод информации после apply
# outputs.tf
output "bucket_name" {
description = "Имя созданного S3-бакета"
value = aws_s3_bucket.app_bucket.id
}
output "bucket_arn" {
description = "ARN S3-бакета"
value = aws_s3_bucket.app_bucket.arn
}
output "bucket_region" {
description = "Регион, в котором создан бакет"
value = var.aws_region
}
Последовательность команд
# Терминал (PowerShell или bash)
# Перейти в директорию проекта
cd s3-bucket-example
# Шаг 1: Инициализация — скачать провайдер AWS
terraform init
# Шаг 2: Предпросмотр — убедиться, что создаётся правильное
terraform plan -var-file="terraform.tfvars"
# Шаг 3: Создать S3-бакет (введите "yes" при подтверждении)
terraform apply -var-file="terraform.tfvars"
# Шаг 4: Проверить создание через AWS CLI
aws s3 ls
# Шаг 5: Просмотр outputs
terraform output
# Шаг 6: Удалить ресурсы после завершения работы
terraform destroy -var-file="terraform.tfvars"
# Сохранить вывод: terraform destroy -var-file="terraform.tfvars" | Tee-Object -FilePath destroy-output.txt
⚠️ Проверить по документации: имена S3-бакетов должны быть глобально уникальными среди всех аккаунтов AWS. Если имя уже занято — apply упадёт с ошибкой. Используйте уникальный префикс (ваша группа + имя). Актуальные ограничения: S3 Bucket Naming Rules.
Пример 2: EC2-инстанс с Docker (полная конфигурация)
Развёртывание EC2-инстанса с автоматической установкой Docker через user_data — разбивка по файлам из лекции (раздел «Использование переменных, outputs.tf, providers.tf»).
Структура файлов
ec2-docker-example/
├── providers.tf # провайдер AWS с required_providers
├── main.tf # Security Group + EC2 instance
├── variables.tf # объявление переменных
├── terraform.tfvars # значения (НЕ секреты)
├── outputs.tf # публичный IP, ID инстанса, SSH-команда
├── install_ec2_docker.sh # user_data: установка Docker на EC2
└── .gitignore # исключить .terraform/, *.tfstate
providers.tf
# providers.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
variables.tf
# variables.tf
variable "aws_region" {
description = "Регион AWS"
type = string
default = "eu-central-1"
}
variable "ami_id" {
description = "ID AMI для EC2 (Amazon Linux 2023, eu-central-1)"
type = string
default = "ami-0de02246788e4a354"
}
variable "instance_type" {
description = "Тип EC2-инстанса"
type = string
default = "t2.micro"
}
variable "key_pair_name" {
description = "Имя Key Pair для SSH-доступа"
type = string
default = "ich"
}
variable "volume_size" {
description = "Размер корневого тома в GB"
type = number
default = 10
}
variable "sg_name" {
description = "Имя Security Group"
type = string
default = "terraform-web-sg"
}
terraform.tfvars
# terraform.tfvars
# Значения для конкретного студента (уникальные имена обязательны!)
aws_region = "eu-central-1"
instance_type = "t2.micro"
key_pair_name = "ich"
volume_size = 10
sg_name = "pd2025-myname-sg"
install_ec2_docker.sh — user_data скрипт
# install_ec2_docker.sh
#!/bin/bash
# Обновляем пакеты
dnf update -y
# Amazon Linux 2023: Docker, плагин Compose v2 и Git одним dnf
dnf install -y docker docker-compose-plugin git
# Запускаем Docker и добавляем в автозапуск
systemctl start docker
systemctl enable docker
# Добавляем пользователя ec2-user в группу docker
usermod -aG docker ec2-user
# Проверяем, что Compose v2 доступен как подкоманда docker
docker compose version
echo "Docker installation complete" >> /var/log/user-data.log
main.tf — Security Group и EC2
# main.tf
# Security Group: разрешить SSH (22) и HTTP (80)
resource "aws_security_group" "web_sg" {
name = var.sg_name
description = "Allow SSH and HTTP"
# SSH — только ваш IP в продакшене, 0.0.0.0/0 для учёбы
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "SSH access"
}
# HTTP
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTP"
}
# HTTPS
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS"
}
# Весь исходящий трафик разрешён
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = var.sg_name
ManagedBy = "Terraform"
}
}
# EC2-инстанс с установкой Docker через user_data
resource "aws_instance" "web_server" {
ami = var.ami_id
instance_type = var.instance_type
key_name = var.key_pair_name
vpc_security_group_ids = [aws_security_group.web_sg.id]
# Скрипт установки Docker (выполняется при первом запуске)
user_data = file("install_ec2_docker.sh")
# Конфигурация корневого тома
root_block_device {
volume_size = var.volume_size
volume_type = "gp3"
}
tags = {
Name = "WebServer-Docker"
ManagedBy = "Terraform"
}
}
outputs.tf
# outputs.tf
output "instance_id" {
description = "ID EC2-инстанса"
value = aws_instance.web_server.id
}
output "instance_public_ip" {
description = "Публичный IP-адрес EC2-инстанса"
value = aws_instance.web_server.public_ip
}
output "security_group_id" {
description = "ID созданной Security Group"
value = aws_security_group.web_sg.id
}
output "ssh_command" {
description = "Команда для SSH-подключения"
value = "ssh -i ~/.ssh/${var.key_pair_name}.pem ec2-user@${aws_instance.web_server.public_ip}"
}
Развёртывание EC2
# Терминал (PowerShell или bash)
cd ec2-docker-example
# Инициализация
terraform init
# Предпросмотр с переменными
terraform plan -var-file="terraform.tfvars"
# Применение (обязательно уникальные имена в tfvars!)
terraform apply -var-file="terraform.tfvars"
# Введите "yes"
# После успешного apply — посмотреть outputs (IP инстанса)
terraform output
# Пример вывода:
# instance_public_ip = "3.73.50.191"
# ssh_command = "ssh -i ~/.ssh/ich.pem ec2-user@3.73.50.191"
# Подключиться по SSH и проверить Docker
ssh -i ~/.ssh/ich.pem ec2-user@3.73.50.191
docker --version
docker ps
# Удалить инфраструктуру после работы
terraform destroy -var-file="terraform.tfvars"
⚠️ Проверить по документации: AMI ID
ami-0de02246788e4a354 специфичен для региона eu-central-1 и учебного окружения. В других регионах AMI ID будет другим. Актуальный AMI Amazon Linux 2023 для вашего региона найдите в консоли EC2 → Launch instance → выберите AMI. Вместо хардкода можно использовать data source (пример в Справочнике).
Пример 3: Модуль для создания нескольких инстансов
Пример из лекции — создание трёх EC2-инстансов через модуль и for_each:
# main.tf — использование модуля с for_each
provider "aws" {
region = "eu-central-1"
}
locals {
instances = {
web1 = {
name = "Web Server 1"
ami = "ami-0de02246788e4a354"
instance_type = "t2.micro"
}
web2 = {
name = "Web Server 2"
ami = "ami-0de02246788e4a354"
instance_type = "t2.micro"
}
web3 = {
name = "Web Server 3"
ami = "ami-0de02246788e4a354"
instance_type = "t2.micro"
}
}
}
module "ec2_instances" {
source = "./modules/ec2_instance"
for_each = local.instances
ami = each.value.ami
instance_type = each.value.instance_type
name = each.value.name
}
Что происходит:
for_each итерирует по мап local.instances. Для каждого ключа (web1, web2, web3) Terraform создаёт отдельный экземпляр модуля. each.value.ami обращается к полям текущего элемента. Чтобы добавить новый сервер — достаточно добавить запись в locals.