📖 Теория: Infrastructure as Code и Terraform

⚡ Ключевые понятия

IaC — инфраструктура как код: описываем серверы, сети и базы данных в файлах, а не кликаем в консоли. Terraform реализует декларативный подход: пишем «что хотим», инструмент сам решает «как сделать».

  • Декларативный подход — описываем конечное состояние, Terraform считает шаги
  • provider — плагин для работы с конкретным облаком (aws, azure, google)
  • resource — конкретный облачный ресурс (EC2, S3, Security Group)
  • variable — параметр, значение задаётся снаружи (tfvars или CLI)
  • output — значение, которое Terraform выводит после apply (IP-адрес, ARN)
  • terraform.tfstate — файл состояния; Terraform знает, что уже создано

Правило безопасности: terraform.tfvars с секретами — в .gitignore. Файл state — тоже не в публичный git.

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
⚠️ Проверить по документации: актуальная версия Terraform постоянно обновляется. Перед установкой проверьте последний релиз: github.com/hashicorp/terraform/releases. В лекции упоминается версия 1.9.5 — на момент прочтения может быть новее.

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
}
~> 5.0 означает «любая версия 5.x, но не 6.x». Это pessimistic constraint operator — защищает от breaking changes при обновлениях.

Блок 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
  }
}
⚠️ Проверить по документации: конфигурация remote backend требует предварительного создания S3-бакета и DynamoDB-таблицы. В учебных окружениях обычно используется локальный state. Актуальный пример: Terraform S3 Backend.

Провайдеры и модули

Провайдеры

Провайдер — плагин Terraform, обеспечивающий взаимодействие с конкретной платформой. Каждый провайдер содержит набор ресурсов и data sources.

  • hashicorp/aws — Amazon Web Services (EC2, S3, RDS, VPC...)
  • hashicorp/azurerm — Microsoft Azure
  • hashicorp/google — Google Cloud Platform
  • hashicorp/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, никакого дублирования кода.