Immutable infrastructure: серверы, которые не нужно чинить

Mutable vs Immutable: две философии

Компания «ШопЭкспресс» — e-commerce платформа, 25 серверов в AWS. Текущий подход: серверы живут месяцами, обновляются через Ansible (мутабельная инфраструктура). Проблема: каждый сервер уникален как снежинка.

Mutable (изменяемая)Immutable (неизменяемая)
Сервер создаётся → обновляется → чинитсяСервер создаётся → работает → уничтожается
SSH для администрированияНет SSH в production
Ansible/Chef/Puppet для обновленийНовый образ → замена сервера
Конфигурационный дрейфНевозможен (read-only)
Откат: сложный, ручнойОткат: предыдущий образ за секунды
Snowflake servers (каждый уникален)Phoenix servers (восстают из пепла)

Принцип immutable: вместо «починить сломанный сервер» — «уничтожить и создать новый из эталонного образа». Как с контейнерами, но на уровне VM.

Pets vs Cattle: мутабельные серверы — домашние питомцы (у каждого имя, их лечат). Иммутабельные — стадо (безымянные, заменяемые).

Packer: сборка golden images

Packer создаёт машинные образы (AMI, VM image) из кода. Один файл → идентичный образ каждый раз.

# packer/app-server.pkr.hcl
packer {
  required_plugins {
    amazon = {
      version = ">= 1.3.0"
      source  = "github.com/hashicorp/amazon"
    }
  }
}

source "amazon-ebs" "app" {
  ami_name      = "shopexpress-app-{{timestamp}}"
  instance_type = "t3.medium"
  region        = "eu-central-1"
  source_ami_filter {
    filters = {
      name                = "debian-12-amd64-*"
      virtualization-type = "hvm"
    }
    owners      = ["136693071363"]
    most_recent = true
  }
  ssh_username = "admin"
}

build {
  sources = ["source.amazon-ebs.app"]

  # Системные пакеты
  provisioner "shell" {
    inline = [
      "sudo apt update && sudo apt upgrade -y",
      "sudo apt install -y nginx python3 python3-venv",
      "sudo systemctl enable nginx"
    ]
  }

  # Приложение
  provisioner "file" {
    source      = "../dist/app.tar.gz"
    destination = "/tmp/app.tar.gz"
  }

  provisioner "shell" {
    inline = [
      "sudo mkdir -p /opt/shopexpress",
      "sudo tar xzf /tmp/app.tar.gz -C /opt/shopexpress",
      "sudo /opt/shopexpress/scripts/setup.sh",
      "rm /tmp/app.tar.gz"
    ]
  }

  # Hardening: удаляем SSH-ключ Packer
  provisioner "shell" {
    inline = [
      "sudo rm -f /home/admin/.ssh/authorized_keys",
      "sudo truncate -s 0 /var/log/auth.log"
    ]
  }
}
# Сборка образа
packer build packer/app-server.pkr.hcl
# ==> amazon-ebs.app: AMI: ami-0abc123def456789
# Build time: 4 minutes 32 seconds

Terraform + ASG: автоматическая замена серверов

Terraform создаёт Auto Scaling Group, которая запускает EC2-инстансы из golden image. Обновление = новый образ → rolling replacement.

# terraform/main.tf
resource "aws_launch_template" "app" {
  name_prefix   = "shopexpress-"
  image_id      = var.app_ami_id  # AMI от Packer
  instance_type = "t3.medium"
  key_name      = ""              # Нет SSH-ключа!

  user_data = base64encode(templatefile("user-data.sh", {
    env        = var.environment
    db_host    = var.db_host
    redis_host = var.redis_host
  }))

  network_interfaces {
    security_groups = [aws_security_group.app.id]
  }

  tag_specifications {
    resource_type = "instance"
    tags = { Name = "shopexpress-app", Environment = var.environment }
  }
}

resource "aws_autoscaling_group" "app" {
  name                = "shopexpress-app"
  min_size            = 3
  max_size            = 10
  desired_capacity    = 3
  vpc_zone_identifier = var.private_subnet_ids

  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }

  instance_refresh {
    strategy = "Rolling"
    preferences {
      min_healthy_percentage = 66  # Минимум 2 из 3 серверов работают
      instance_warmup        = 120
    }
  }

  health_check_type         = "ELB"
  health_check_grace_period = 120

  target_group_arns = [aws_lb_target_group.app.arn]
}
# Деплой нового образа
# 1. Packer собирает новый AMI
# 2. Terraform обновляет launch_template с новым AMI
terraform apply -var="app_ami_id=ami-0abc123def456789"
# 3. ASG instance_refresh автоматически:
#    - Запускает новый инстанс
#    - Ждёт health check
#    - Убивает старый инстанс
#    - Повторяет для всех инстансов

Blue-Green деплой для zero-downtime

Blue-Green — две идентичные среды. Blue работает в production, Green — стоит готовая с новой версией. Переключение — смена target group на load balancer.

# terraform/blue-green.tf
resource "aws_autoscaling_group" "blue" {
  name = "shopexpress-blue"
  launch_template {
    id      = aws_launch_template.blue.id
    version = "$Latest"
  }
  min_size = var.blue_active ? 3 : 0
  max_size = var.blue_active ? 10 : 0
}

resource "aws_autoscaling_group" "green" {
  name = "shopexpress-green"
  launch_template {
    id      = aws_launch_template.green.id
    version = "$Latest"
  }
  min_size = var.blue_active ? 0 : 3
  max_size = var.blue_active ? 0 : 10
}

# Переключение: terraform apply -var="blue_active=false"
# Green поднимается, Blue скейлится до 0

Откат при проблемах — одна команда:

# Откат на предыдущую версию
terraform apply -var="blue_active=true"
# Blue (с предыдущей версией) поднимается за 2-3 минуты
Совет: Для баз данных immutable не работает — данные должны сохраняться. Используйте managed-сервисы (RDS, ElastiCache) или отдельные persistent-серверы для stateful-компонентов.

Результаты «ШопЭкспресс»

Миграция на immutable инфраструктуру заняла 6 недель:

  1. Недели 1-2: конвертация Ansible-ролей → Packer-шаблоны
  2. Недели 3-4: Terraform для ASG, load balancer, blue-green
  3. Недели 5-6: CI/CD pipeline (GitHub Actions: build → Packer → Terraform → smoke test)
МетрикаMutable (было)Immutable (стало)
Время деплоя20-30 мин (Ansible)5 мин (AMI swap)
Откат30-60 мин (ручной)2 мин (предыдущий AMI)
Конфигурационный дрейфПостоянноНевозможен
SSH-сессии в production~50/мес0
Даунтайм при деплое1-2 мин0 (rolling/blue-green)
Инциденты «сломали при обновлении»3/мес0
Когда НЕ использовать immutable: единичные серверы (1-2 штуки — overhead не окупается), stateful-сервисы (БД, очереди), быстрое прототипирование. Immutable — для stateless application tier с 3+ инстансами.

Часто задаваемые вопросы

Логи отправляются в CloudWatch/Loki при старте. Метрики — через OTel/Prometheus. Для экстренной отладки: AWS Systems Manager Session Manager — доступ к консоли без SSH, с audit trail. Или запустите debug-инстанс из того же AMI с SSH.

Никогда не кладите секреты в образ! Используйте: 1) user-data скрипт при запуске инстанса, 2) AWS Secrets Manager / HashiCorp Vault — приложение получает секреты при старте, 3) Переменные окружения через Systems Manager Parameter Store.

Нет, часто дешевле. Вы экономите на: часах работы инженеров (нет ручных SSH-сессий), инцидентах из-за дрейфа, простое при обновлениях. Стоимость сборки AMI (4-5 минут t3.medium) — $0.01 за сборку. ASG не добавляет стоимости.

Да, на bare-metal: PXE boot из golden image, netboot.xyz, или Talos Linux для Kubernetes. На VMware/Proxmox: шаблоны VM + Terraform provider. Принцип тот же: образ собирается через CI, серверы создаются из образа, не модифицируются.

Так же, как обычный деплой: обновить базовый образ (apt upgrade в Packer), собрать новый AMI, раскатать через ASG instance refresh. Весь процесс — 10-15 минут от коммита до production. Для критических CVE это быстрее, чем SSH на 25 серверов.

Нужна помощь с внедрением?

Настроим, оптимизируем и возьмём на поддержку вашу инфраструктуру. 15+ лет опыта, 8 серверов Dell Xeon в дата-центре МТС.

📞 Связаться с нами

Комментарии 0

Оставить комментарий

5 + 3 =