Immutable Infrastructure: заміна серверів замість оновлення

Кожен сервер з часом обростає ручними правками та тимчасовими фіксами, перетворюючись на крихку унікальну систему, яку складно оновлювати та відкочувати. Ми впроваджуємо модель immutable infrastructure, замінюючи сервери замість їх оновлення, і реалізуємо проєкт під ключ — від аудиту до налаштування автоматизації. Наша команда забезпечує стабільну роботу та подальшу підтримку, щоб ваші середовища залишалися ідентичними та надійними.
Часті запитання

Сервер живе три роки. За цей час його руками оновлювали пакети, змінювали конфіги, ставили тимчасові фікси «на п'ять хвилин». Немає жодного інженера, який точно знає поточний стан цієї машини. ansible-playbook падає на нестандартних значеннях, які хтось поправив напряму. Такий сервер називають snowflake server — унікальний і крихкий. Типова ситуація: після чергового puppet apply половина продакшену впала, тому що на одному інстансі вручну переписали nginx.conf. Відкотити — нікуди, кожен сервер індивідуальний. Доводиться розбиратися з кожним окремо, втрачаючи години даунтайму. Наша команда DevOps-інженерів з 10-річним досвідом щодня стикається з такими проблемами та допомагає компаніям перейти на надійну модель immutable infrastructure.

Immutable infrastructure — це принципова відмова від оновлення серверів. Замість apt-get upgrade або ansible — створення нового образу, запуск нових інстансів, видалення старих. Сервер не змінюється ніколи після деплою. Такий підхід гарантує ідентичність середовищ і спрощує відкати.

Чому immutable infrastructure вигідніше?

Порівняємо старий підхід і новий у таблиці:

Критерій Snowflake (ручне оновлення) Immutable (заміна сервера)
Час відновлення після збою Години — потрібно з'ясовувати, що змінювали 5-7 хвилин — деплой попереднього AMI
Дрейф конфігурації Неминучий, кожен сервер унікальний Відсутній, всі сервери з одного образу
Безпека Ризик незадокументованих змін Повний аудит через образи та Git
Витрати на підтримку Високі — ручні правки та runbook Низькі — автоматизація та самовідновлення

Phoenix Server паттерн

Концепція проста: кожен сервер — тимчасовий. Як птах Фенікс, він згорає та з'являється новий. Конфігурація та код додатку запікаються в образ. Дані зберігаються поза сервером — у S3, RDS, EFS.

Для VM-інфраструктури це реалізується через Packer + Terraform:

# packer/api-server.pkr.hcl
source "amazon-ebs" "api" {
  ami_name = "api-server-${var.version}-${formatdate("YYYYMMDD", timestamp())}"
  instance_type = "t3.medium"
  region = "eu-west-1"
  source_ami_filter {
    filters = {
      name = "ubuntu/images/hvm-ssd/ubuntu-22.04-amd64-server-*"
      root-device-type = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners = ["099720109477"]
  }
}

build {
  sources = ["source.amazon-ebs.api"]
  provisioner "ansible" {
    playbook_file = "ansible/api-server.yml"
    extra_arguments = ["--extra-vars", "app_version=${var.version}"]
  }
  post-processor "manifest" {
    output = "packer-manifest.json"
  }
}

Packer збирає AMI. Ansible provisioner запікає додаток прямо в образ. Після збірки — packer-manifest.json містить ID нового AMI.

Terraform: заміна інстансів через Launch Template

resource "aws_launch_template" "api" {
  name_prefix = "api-server-"
  image_id = var.ami_id # ID з packer-manifest.json
  instance_type = "t3.medium"

  tag_specifications {
    resource_type = "instance"
    tags = {
      Name = "api-server"
      Version = var.app_version
    }
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_group" "api" {
  name = "api-${var.app_version}"
  desired_capacity = 3
  min_size = 2
  max_size = 6
  vpc_zone_identifier = var.private_subnet_ids

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

  instance_refresh {
    strategy = "Rolling"
    preferences {
      min_healthy_percentage = 50
      instance_warmup = 120
    }
  }

  lifecycle {
    create_before_destroy = true
  }
}

instance_refresh — вбудований механізм AWS для заміни інстансів без даунтайму. При зміні image_id у Launch Template — ASG поступово замінює старі інстанси новими, підтримуючи мінімум 50% healthy.

CI/CD пайплайн: від коміту до нового образу

---
# .github/workflows/deploy.yml
jobs:
  build-ami:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build AMI with Packer
        run: |
          packer init packer/
          packer build \
            -var "version=${{ github.sha }}" \
            packer/api-server.pkr.hcl
      - name: Extract AMI ID
        id: ami
        run: |
          AMI_ID=$(jq -r '.builds[-1].artifact_id' packer-manifest.json | cut -d: -f2)
          echo "ami_id=$AMI_ID" >> $GITHUB_OUTPUT
  deploy:
    needs: build-ami
    steps:
      - name: Update Terraform
        run: |
          terraform apply \
            -var "ami_id=${{ needs.build-ami.outputs.ami_id }}" \
            -var "app_version=${{ github.sha }}" \
            -auto-approve
---

Кожен коміт у main → новий AMI → оновлення ASG. Жодного ssh у продакшн сервери. Жодних ansible-playbook проти живих інстансів.

Як впровадити immutable infrastructure: покроковий план

  • Аудит поточної інфраструктури: виявити всі компоненти, що зберігають state на диску, і спланувати їх міграцію.
  • Виніс даних: перенести бази в RDS, файли в S3, сесії в Redis. Налаштувати екстерналізацію логів.
  • Створення Packer-шаблонів: для кожного типу сервера — окремий шаблон з Ansible provisioner, що запікає додаток та залежності.
  • Налаштування Terraform-модулів: Launch Template з image_id з Packer, Auto Scaling Group з instance refresh.
  • Збірка CI/CD пайплайну: GitHub Actions або GitLab CI: commit → build AMI → update Terraform → вивід у прод.
  • Тестування та rollback: перевірити заміну інстансів, виконати відкат на попередній AMI.
  • Навчання команди: передача документації та runbook.

Критично: що не повинно бути на сервері

Immutable infrastructure працює лише якщо дотримуються кілька правил:

Всі дані поза сервером. База даних — у RDS. Завантажені файли — у S3. Сесії — у Redis. Логи — у CloudWatch Logs або Loki. Якщо дані зберігаються на диску інстанса, вони губляться при заміні.

Конфігурація через environment variables. Жодних конфіг файлів, які створюються при деплої. Тільки змінні середовища з Secrets Manager або Parameter Store:

# user-data script для інстанса
export DB_URL=$(aws ssm get-parameter --name /api/db-url --with-decryption --query Value --output text)
export SECRET_KEY=$(aws secretsmanager get-secret-value --secret-id api/secret-key --query SecretString --output text)
systemctl start api

Заборона SSH у продакшн. Якщо інженер може зайти та щось змінити руками — immutability порушена. SSM Session Manager замість прямого SSH, і лише для екстреної діагностики з повним аудит логом.

Rollback — це деплой попереднього AMI

# Відкочуємо на попередній AMI
terraform apply \
  -var "ami_id=ami-0abcdef1234567890" \
  -var "app_version=previous-sha" \
  -auto-approve

5-7 хвилин на заміну інстансів. Передбачувано. Без сюрпризів у стилі «відкат пройшов, але конфіг інший». Immutable infrastructure швидше в 10 разів за швидкістю відновлення порівняно з традиційним підходом — емпіричні дані з наших проектів.

Що робити з legacy, які зберігають state на диску?

Найскладніше при переході — legacy компоненти, які зберігають state на диску: додатки з file-based sessions, cron jobs що пишуть у /tmp, додатки з хардкоженими шляхами до конфігів. Це потрібно рефакторити до переходу на immutable. Ми допомагаємо провести аудит, виявити такі місця та спланувати міграцію. На це йде більше часу, ніж на саме налаштування Packer + Terraform, але без цього immutable не працює.

Що входить у роботу під ключ

Ми беремо на себе весь цикл: від аудиту до передачі документації. У результаті ви отримуєте:

  • Packer-шаблони для збірки образів усіх компонентів
  • Terraform-модулі з Auto Scaling та instance refresh
  • CI/CD пайплайн (GitHub Actions / GitLab CI) з автоматичним деплоєм та відкатом
  • Runbook з експлуатації та відновлення
  • Навчання вашої команди роботі з новою інфраструктурою
  • Гарантію стабільної роботи протягом 30 днів після впровадження
Приклад типового плану робіт
Етап Термін
Аудит: що зберігається на сервері, що потрібно виносити 1 день
Packer шаблон + Ansible provisioner 1.5 дня
Terraform ASG з instance_refresh 1 день
CI/CD пайплайн (build AMI + deploy) 0.5 дня
Тест rollback + runbook 0.5 дня

Вартість розраховується індивідуально після аудиту інфраструктури. Оцінимо ваш проект — напишіть нам, щоб отримати консультацію та попередній план.

Зв'яжіться з нами для аудиту вашої інфраструктури та замовте впровадження immutable підходу.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139