Infrastructure as Code (IaC)
Infrastructure as Code (IaC) — это подход к управлению и настройке IT-инфраструктуры с использованием конфигурационных файлов вместо ручных операций в интерфейсе (консоль AWS, кликабельные формы).
IaC позволяет автоматизировать создание, настройку и управление инфраструктурой — от одного сервера до сотен ресурсов.
Два подхода в IaC
| Подход | Описание | Примеры инструментов |
|---|---|---|
| Императивный | Описываем шаги для достижения нужного состояния: «создай VM, затем установи nginx, затем открой порт 80» | Bash, PowerShell, AWS CLI скрипты, Ansible |
| Декларативный | Описываем желаемое конечное состояние: «у меня должен быть S3-бакет с такими параметрами». Инструмент сам вычисляет шаги. | Terraform, AWS CloudFormation, Pulumi |
Декларативный подход проще в поддержке: не нужно следить за промежуточными состояниями и повторными запусками — Terraform сам понимает, что уже создано, что нужно создать, что нужно изменить.
Ключевые преимущества IaC
- Версионирование в Git: вся инфраструктура хранится как код — полная история изменений
- Code Review: изменения инфраструктуры проходят ревью в Pull Requests
- Воспроизводимость: одна конфигурация создаёт идентичные окружения Dev/Test/Prod
- Командная работа: несколько разработчиков работают над инфраструктурой параллельно
- Управление несколькими окружениями: через переменные создаём dev/staging/production из одной конфигурации
Что такое Terraform
Terraform — инструмент с открытым исходным кодом, разработанный компанией HashiCorp. Используется для автоматизации развёртывания и управления инфраструктурой с декларативным синтаксисом HCL (HashiCorp Configuration Language).
Основные возможности Terraform
- Мультиоблачность: один инструмент для AWS, Azure, Google Cloud, Kubernetes и сотен других провайдеров
- Модули: переиспользуемые блоки конфигурации (модуль VPC, модуль EC2-кластера)
- Plan перед apply: всегда видите изменения до их применения
- State management: Terraform знает текущее состояние и вычисляет дельту
- Безопасные изменения: нельзя случайно удалить ресурс без явного подтверждения
Установка Terraform
Windows
Рекомендуется установка через Winget (встроен в Windows 10/11) или Chocolatey:
# PowerShell — установка через Winget (рекомендуется)
winget install HashiCorp.Terraform
# Проверка установки
terraform --version
Альтернативно — ручная установка:
# Git Bash — скачать архив (проверьте актуальную версию на releases.hashicorp.com)
cd ~/Downloads
curl -O https://releases.hashicorp.com/terraform/1.9.5/terraform_1.9.5_windows_amd64.zip
unzip terraform_1.9.5_windows_amd64.zip
mkdir /c/terraform/
mv terraform.exe /c/terraform/
# Добавить C:\terraform в системный PATH через настройки Windows
macOS
# Терминал macOS — через Homebrew (рекомендуется)
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Проверка
terraform --version
HCL-синтаксис Terraform
HCL (HashiCorp Configuration Language) — декларативный язык конфигурации Terraform. Читаемый для человека, поддерживает комментарии, переменные и выражения.
Блок terraform{} — обязательная настройка
В современном Terraform (0.13+) провайдеры объявляются внутри блока terraform { required_providers {} }:
# providers.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-central-1"
# Credentials берутся автоматически из ~/.aws/credentials
}
Блок resource
Ресурс — это конкретный объект инфраструктуры (сервер, бакет, сетевой интерфейс):
# main.tf
# Синтаксис: resource "тип_ресурса" "локальное_имя" { атрибуты }
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-unique-bucket-name-2024"
tags = {
Name = "My Terraform Bucket"
Environment = "dev"
}
}
resource "aws_instance" "web_server" {
ami = "ami-0de02246788e4a354" # Amazon Linux 2023, eu-central-1
instance_type = "t2.micro"
tags = {
Name = "WebServer-Terraform"
}
}
Блок variable
Переменные параметризуют конфигурацию — позволяют изменять значения без редактирования основных файлов:
# variables.tf
variable "bucket_name" {
description = "Уникальное имя S3-бакета"
type = string
default = "my-group-bucket"
}
variable "instance_type" {
description = "Тип EC2-инстанса"
type = string
default = "t2.micro"
}
variable "aws_region" {
description = "Регион AWS"
type = string
default = "eu-central-1"
}
variable "volume_size" {
description = "Размер корневого тома в GB"
type = number
default = 10
}
Файл значений переменных
# terraform.tfvars — переопределяем значения по умолчанию
bucket_name = "pd2025-myname-bucket"
instance_type = "t2.micro"
aws_region = "eu-central-1"
terraform.tfvars находятся секреты (ключи, пароли) — файл должен быть в .gitignore. В лекции используется .terraform.tfvars (с точкой в начале) — это нестандартное имя, которое Terraform не подхватывает автоматически. Стандартные имена, которые Terraform загружает автоматически: terraform.tfvars и *.auto.tfvars.
Блок output
Outputs определяют значения, которые Terraform выводит после успешного apply (IP-адрес нового сервера, ARN ресурса, URL):
# outputs.tf
output "bucket_name" {
description = "Имя созданного S3-бакета"
value = aws_s3_bucket.my_bucket.id
}
output "instance_public_ip" {
description = "Публичный IP-адрес EC2-инстанса"
value = aws_instance.web_server.public_ip
}
output "instance_id" {
description = "ID созданного EC2-инстанса"
value = aws_instance.web_server.id
}
Блок data
Data source позволяет читать информацию об уже существующих ресурсах (не создавая новые):
# main.tf — получить актуальный AMI Amazon Linux 2023 динамически
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id # берём из data source
instance_type = var.instance_type
}
Файл состояния terraform.tfstate
После первого terraform apply в рабочей директории появляются два файла:
| Файл | Назначение |
|---|---|
terraform.tfstate |
Текущее состояние инфраструктуры. Terraform сравнивает этот файл с конфигурацией, чтобы понять, что нужно создать/изменить/удалить. |
terraform.tfstate.backup |
Резервная копия предыдущего состояния. Страховка при повреждении основного файла. |
terraform.tfstate вручную. Если файл утерян, Terraform потеряет связь с реально созданными ресурсами — придётся восстанавливать через terraform import.
Remote state (best practice для команд)
Для командной работы локальный state-файл неудобен: два разработчика не могут применять изменения одновременно. Решение — remote backend: хранить state в S3-бакете с блокировкой через DynamoDB.
# backend.tf — remote state в S3 (для командной работы)
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "eu-central-1"
dynamodb_table = "terraform-locks" # Блокировка параллельных apply
encrypt = true
}
}
Провайдеры и модули
Провайдеры
Провайдер — плагин Terraform, обеспечивающий взаимодействие с конкретной платформой. Каждый провайдер содержит набор ресурсов и data sources.
hashicorp/aws— Amazon Web Services (EC2, S3, RDS, VPC...)hashicorp/azurerm— Microsoft Azurehashicorp/google— Google Cloud Platformhashicorp/kubernetes— Kubernetes-кластеры
После terraform init провайдеры скачиваются в директорию .terraform/providers/. Файл .terraform.lock.hcl фиксирует точные версии — гарантирует воспроизводимость.
Модули
Модуль — группа ресурсов, вынесенных в отдельную директорию для повторного использования. Позволяет создавать одинаковые компоненты с разными параметрами:
# main.tf — использование модуля для создания нескольких EC2-инстансов
locals {
instances = {
web1 = { name = "Web Server 1", instance_type = "t2.micro" }
web2 = { name = "Web Server 2", instance_type = "t2.micro" }
web3 = { name = "Web Server 3", instance_type = "t2.small" }
}
}
module "ec2_instances" {
source = "./modules/ec2_instance"
for_each = local.instances
ami = "ami-0de02246788e4a354"
instance_type = each.value.instance_type
name = each.value.name
}
Конструкция for_each создаёт по одному экземпляру модуля для каждого элемента в мап. Чтобы добавить четвёртый сервер — просто добавьте запись в locals, никакого дублирования кода.