Инфраструктура как код (IaC): когда железо становится программным обеспечением¶
Представьте, что вы архитектор. Вместо того чтобы вручную класть каждый кирпич, смешивать цемент и прокладывать проводку, вы создаёте цифровую модель здания и включаете громадный 3d принтер Нажимаете кнопку - и через месяц на стройплощадке появляется готовый дом, точно соответствующий чертежам. Инфраструктура как код (Infrastructure as Code, IaC) - это именно такой подход к созданию и управлению IT-инфраструктурой.
Что такое IaC? Короткое определение¶
Инфраструктура как код - это практика управления и предоставления вычислительной инфраструктуры (серверы, сети, базы данных) с использованием конфигурационных файлов, которые обрабатываются как обычный программный код.
Проще говоря: вы пишете код, который создает инфраструктуру, вместо того чтобы вручную нажимать кнопки в веб-интерфейсе или выполнять команды по ssh.
Эволюция: от ручного управления к IaC¶
Эпоха ручного управления (до 2010-х)¶
Системный администратор:
1. Заходит в веб-интерфейс AWS/GCP
2. Вручную создает виртуальную машину
3. Подключается по SSH
4. Устанавливает ПО, настраивает
5. Записывает что сделал в Wiki (или не записывает)
Проблемы: - Неповторимость: Создать точно такую же инфраструктуру невозможно - Дрейф конфигурации: Со временем серверы "уплывают" от исходного состояния - Медленно: Создание продакшена занимает дни или недели - Ошибкоопасно: Человеческий фактор на каждом шагу
Эпоха скриптов (2000-е)¶
#!/bin/bash
# Скрипт создания сервера (упрощенно)
aws ec2 run-instances --image-id ami-12345 --count 1 --instance-type t2.micro
ssh ubuntu@server "apt-get update && apt-get install nginx"
scp nginx.conf ubuntu@server:/etc/nginx/
ssh ubuntu@server "systemctl restart nginx"
Лучше, но проблемы остаются: - Скрипты линейны и хрупки - Нет идемпотентности (повторный запуск может сломать всё) - Сложно управлять зависимостями
Эра IaC (2010-е — настоящее время)¶
# Файл Terraform: инфраструктура как код
resource "aws_instance" "web_server" {
ami = "ami-12345"
instance_type = "t2.micro"
tags = {
Name = "Web Server"
Environment = "production"
}
}
resource "aws_security_group" "web_sg" {
name = "web-security-group"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Преимущества: - Повторимость: тот же код = та же инфраструктура - Версионирование: изменения хранятся в Git - Автоматизация: инфраструктура создается сама - Идемпотентность: повторный запуск не ломает систему
Зачем SRE нужен IaC? Без этого просто невозможно!¶
1. Устранение рутины (Toil Elimination)¶
Без IaC: SRE тратит 20% времени на создание/настройку серверов
С IaC: Инфраструктура создается автоматически, SRE тратит время на улучшение кода инфраструктуры
2. Консистентность и соответствие compliance¶
Пример для банка: требуется, чтобы все продакшен-серверы: - Имели шифрование дисков - Отправляли логи в центральное хранилище - Имели определенные security groups
Без IaC: проверяем каждый сервер вручную, находим расхождения, чиним
С IaC: в коде инфраструктуры эти требования зашиты навсегда. Новые серверы создаются уже соответствующими требованиям.
3. Восстановление после катастроф (Disaster Recovery)¶
Сценарий: Дата-центр в Москве сгорел.
Без IaC: Паника. Вспоминаем, что было настроено. Пытаемся воссоздать вручную. Занимает дни.
С IaC: Запускаем тот же код Terraform в другом регионе (Питер). Инфраструктура поднимается за часы.
4. Масштабирование и эксперименты¶
Хотите протестировать новую архитектуру?
Без IaC: Боимся трогать прод. Создаем вручную копию (неполную). Тестируем.
С IaC: Создаем новый environment из кода. Тестируем. Уничтожаем после тестов. Быстро и безопасно.
Принципы IaC для SRE¶
Принцип 1: Идемпотентность¶
Сколько бы раз вы ни запускали код, результат должен быть одинаковым.
Пример неидемпотентного кода (плохо):
echo "server_name localhost;" >> /etc/nginx/nginx.conf
# При каждом запуске добавляет строку снова и снова
Пример идемпотентного кода (хорошо, Ansible):
- name: Ensure nginx config is correct
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
# При каждом запуске проверяет и приводит к нужному состоянию
Принцип 2: Декларативность против императивности¶
Императивный подход (как делать):
# Псевдокод
def setup_server():
create_vm()
wait_for_vm_ready()
install_nginx()
configure_nginx()
start_nginx()
Декларативный подход (что хотим получить):
# Terraform
resource "aws_instance" "web" {
ami = "ubuntu-20.04"
instance_type = "t2.micro"
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y nginx
systemctl start nginx
EOF
}
Декларативный подход предпочтительнее: мы описываем желаемое состояние, а система сама понимает, как его достичь.
Принцип 3: Верификация и тестирование¶
Инфраструктурный код это тоже код. И его нужно тестировать.
Пирамида тестирования IaC:
↗ Интеграционные тесты
↗ (Test Kitchen, Terratest)
↗ Модульные тесты
↗ (ChefSpec, pytest-terraform)
/ Синтаксические проверки
/ (terraform validate, yamllint)
/ Статический анализ
/ (tflint, checkov, terrascan)
Пример теста для Terraform:
// Terratest тест
func TestTerraformWebServer(t *testing.T) {
terraformOptions := &terraform.Options{
TerraformDir: "../infra",
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
// Проверяем, что сервер отвечает
publicIp := terraform.Output(t, terraformOptions, "public_ip")
url := fmt.Sprintf("http://%s", publicIp)
http_helper.HttpGetWithRetry(t, url, nil, 200, "Welcome to nginx", 30, 5*time.Second)
}
Основные инструменты IaC¶
1. Terraform (HashiCorp) — лидер рынка¶
Для чего: Provisioning (создание) облачной инфраструктуры Язык: HCL (HashiCorp Configuration Language) Принцип: Декларативный
# Создаем VPC, подсети, EC2 инстанс и security group
provider "aws" {
region = "eu-west-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
}
resource "aws_instance" "app" {
ami = "ami-12345"
instance_type = "t2.micro"
subnet_id = aws_subnet.public.id
tags = {
Name = "Application Server"
}
}
Почему SRE любят Terraform: - Поддерживает 100+ провайдеров (AWS, GCP, Azure, Kubernetes, GitHub...) - План применения (terraform plan) показывает что изменится - State management (знает текущее состояние инфраструктуры)
2. Ansible (Red Hat) - конфигурационный менеджер¶
Для чего: Configuration Management (настройка уже созданных серверов) Язык: YAML Принцип: Императивный (но с идемпотентностью)
- name: Configure web server
hosts: webservers
become: yes
tasks:
- name: Ensure nginx is installed
apt:
name: nginx
state: present
- name: Ensure nginx is running
service:
name: nginx
state: started
enabled: yes
- name: Deploy website
copy:
src: /local/path/index.html
dest: /var/www/html/
3. Pulumi - инфраструктура на настоящих языках программирования¶
Для чего: Provisioning на стероидах Язык: TypeScript, Python, Go, .NET Принцип: Декларативный, но с полной мощью языков программирования
// Создаем Kubernetes кластер на TypeScript
import * as k8s from "@pulumi/kubernetes";
// Создаем Namespace
const appNamespace = new k8s.core.v1.Namespace("app-ns", {
metadata: { name: "application" }
});
// Создаем Deployment
const appDeployment = new k8s.apps.v1.Deployment("app", {
metadata: { namespace: appNamespace.metadata.name },
spec: {
replicas: 3,
selector: { matchLabels: { app: "webapp" } },
template: {
metadata: { labels: { app: "webapp" } },
spec: {
containers: [{
name: "webapp",
image: "nginx:latest",
ports: [{ containerPort: 80 }]
}]
}
}
}
});
Преимущество для SRE: можно использовать циклы, условия, функции, модули, всё как в обычном программировании.
Рабочий процесс SRE с IaC¶
Стандартный workflow:¶
1. Разработчик делает изменения в коде приложения
2. SRE обновляет код инфраструктуры (добавляет ресурсы, меняет конфигурацию)
3. Pull Request в Git
4. Автоматические проверки:
- Синтаксис
- Политики безопасности
- План изменений
- что-то еще
5. Ревью кода инфраструктуры (как и любого другого кода)
6. Мерж → автоматическое применение через CI/CD
7. Мониторинг результата
Пример CI/CD пайплайна для Terraform:¶
# .gitlab-ci.yml
stages:
- validate
- plan
- apply
terraform-validate:
stage: validate
script:
- terraform init
- terraform validate
terraform-plan:
stage: plan
script:
- terraform init
- terraform plan -out=planfile
artifacts:
paths:
- planfile
terraform-apply:
stage: apply
script:
- terraform apply -auto-approve planfile
only:
- main # Автоматически применяем только в main ветке
Проблемы и вызовы IaC¶
1. State management (особенно в Terraform)¶
State-файл *.tfstate знает, что у нас развернуто. Если он потеряется или повредится, то Terraform перестанет понимать, что происходит.
Решение: Хранить state в удаленном бэкенде (S3 + DynamoDB для блокировок или Consul, или что-то другое).
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "production/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks" # Для блокировок
encrypt = true
}
}
2. Дрейф состояния (State Drift)¶
Кто-то вручную изменил инфраструктуру в обход IaC. Теперь код и реальность расходятся.
Решение: - Запретить ручные изменения (IAM политики) - Регулярно запускать terraform plan для обнаружения дрейфа - Инструменты типа AWS Config для мониторинга compliance
3. Сложность рефакторинга¶
Например, переименование ресурса в Terraform - это уничтожение старого ресурса и создание нового (может быть downtime).
Решение: moved блоки (Terraform 1.1+):
moved {
from = _instance.old_name
to = _instance.new_name
}
4. Секреты и чувствительные данные¶
Код инфраструктуры хранится в Git. Но пароли, ключи API — нет.
Решение: - Использовать менеджеры серетов (например, HashiCorp Vault) - Никогда не хранить секреты в коде
data "aws_secretsmanager_secret" "db_password" {
name = "production/db/password"
}
resource "aws_db_instance" "database" {
# ...
password = data.aws_secretsmanager_secret.db_password.secret_string
}
Продвинутые практики для SRE¶
1. Модульный подход (Terraform Modules)¶
Создавайте переиспользуемые модули:
modules/
├── networking/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── compute/
└── database/
environments/
├── production/
│ └── main.tf # использует модули
└── staging/
└── main.tf
2. Policy as Code (Open Policy Agent, OPA)¶
Автоматическая проверка, что инфраструктура соответствует политикам:
# policy.rego - запрещаем создание инстансов без тегов
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
not resource.change.after.tags
msg := "AWS instances must have tags"
}
3. GitOps для инфраструктуры¶
Инфраструктура обновляется автоматически при изменении кода в Git (как в Kubernetes с ArgoCD, но для облачной инфраструктуры).
IaC и культура SRE¶
Смена мышления:¶
Старое: "Инфраструктура это железо, которое нужно настраивать"
Новое: "Инфраструктура это программный продукт, который нужно разрабатывать"
Новые роли в команде SRE:¶
- Infrastructure Developer: пишет и поддерживает код инфраструктуры
- Platform Engineer: создает внутренние платформы на основе IaC
- Reliability Architect: проектирует устойчивые системы через код
Почему без IaC сегодня нет SRE¶
Без IaC мы: - Тратим время на рутину вместо решения реальных проблем - Не можем гарантировать консистентность сред - Боимся вносить изменения - Медленно восстанавливаемся после сбоев - Не соответствуем современным стандартам инженерии
С IaC мы: - Управляем инфраструктурой как программным продуктом - Можем воспроизвести любое окружение за минуты - Вносим изменения безопасно (с review и тестами) - Имеем документацию в виде исполняемого кода - Спим спокойно, зная, что инфраструктура предсказуема
Ключевой показатель для SRE: время от коммита в Git до работающей инфраструктуры. С ручным подходом это дни. С IaC это минуты.
IaC это это не просто "ещё один инструмент". Это фундаментальный переворот в том, как мы думаем об инфраструктуре. Это переход от ремесла к инженерии. И для SRE это не опция, а необъодимость, потому что в мире, где от инфраструктуры зависит доступность сервисов, управлять ею вручную это не просто неэффективно, это очень опасно.