Что такое поэтапное внедрение (rolling deployment) в DevOps?

Ответ

Поэтапное внедрение (Rolling Deployment) — это стратегия развертывания, при которой новая версия приложения заменяет старую постепенно, экземпляр за экземпляром, что позволяет избежать полного простоя (downtime) и минимизировать риск.

Как это работает на практике:

  1. Новый образ приложения (например, myapp:v2) собирается и помещается в реестр (Docker Registry).
  2. Оркестратор (Kubernetes, Nomad) начинает заменять поды (pods) или ноды с версией v1 на v2 по одному или небольшими группами.
  3. После каждого шага выполняются проверки здоровья (health checks). Если новый экземпляр v2 не проходит проверку, развертывание приостанавливается или откатывается.
  4. Процесс продолжается, пока все экземпляры не будут обновлены.

Пример манифеста Kubernetes, определяющего стратегию Rolling Update:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1  # Гарантирует, что во время обновления будет недоступно не более 1 пода
      maxSurge: 1        # Позволяет создать не более 1 дополнительного пода сверх желаемого количества
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myregistry.com/myapp:v2.0.0
        readinessProbe:
          httpGet:
            path: /health
            port: 8080

Преимущества:

  • Нулевой downtime: Приложение остается доступным для пользователей.
  • Быстрый откат: В случае проблем можно остановить развертывание или откатиться, отменив лишь несколько последних шагов.
  • Плавная нагрузка: Инфраструктура не испытывает резкого скачка нагрузки, связанного с одновременным запуском всех новых экземпляров.

Недостатки и сложности:

  • Совместимость данных: На время развертывания одновременно работают две версии приложения. Это требует обеспечения обратной и прямой совместимости API и схем баз данных.
  • Мониторинг: Необходим тщательный мониторинг метрик (латентность, ошибки, потребление ресурсов) для быстрого выявления проблем в новой версии.

Ответ 18+ 🔞

Давай разжую тебе эту тему, как будто объясняю за соседским забором, пока мангал разжигается. Представь, что у тебя есть тачка — старая, но ездит. А ты купил новую, с турбиной и подсветкой сидений. Так вот, поэтапное внедрение (Rolling Deployment) — это не выкинуть старую тачку на хуй и сразу сесть в новую, а плавно пересаживаться, пока двигатель работает.

Как это происходит на самом деле, без этих твоих заумных слов:

  1. Ты собрал новый образ приложения (myapp:v2), типа пригнал новую тачку в гараж.
  2. Оркестратор (это такой злой и умный диспетчер, типа Kubernetes) начинает менять старые рабочие экземпляры (v1) на новые (v2) по одному. Не все сразу, а по чуть-чуть. Стоит один старый контейнер, рядом запускается новый. Старый вырубили — новый уже работает. И так по цепочке.
  3. После каждого такого подмена диспетчер тыкает нового работника палкой: «Жив?». Это health checks. Если новый экземпляр не откликается, вся движуха останавливается, иначе будет тебе хиросима и нигасраки.
  4. И так, пока все старые кони не будут заменены на новых. Без простоев, блядь.

Вот смотри, как это в манифесте выглядит, тут всё серьёзно:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1  # Чтоб в любой момент времени не более одного пода было в отключке
      maxSurge: 1        # И не более одного лишнего пода могло появиться сверх плана
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myregistry.com/myapp:v2.0.0
        readinessProbe:
          httpGet:
            path: /health
            port: 8080

Чем это, блядь, хорошо:

  • Простоя ноль, ядрёна вошь. Пользователи даже не заметят, что ты там что-то обновляешь. Всё работает.
  • Откат быстрый. Если новая версия оказалась пиздопроебибной, ты не откатываешь всё разом, а просто останавливаешься. Проблемных экземпляров — один-два, а не все пять.
  • Нагрузка плавная. Инфраструктура не охуевает от того, что все пять экземпляров старой версии разом легли и пять новых разом встали. Всё идёт по плану.

А теперь, чувак, ложка дёгтя, и немалая:

  • Совместимость — головная боль. Пока идёт обновление, у тебя одновременно работают и v1, и v2. Представь: одна часть пользователей тыкает в старый API, другая — в новый. Если они между собой не договорятся, будет пиздец. Базы данных, АПИ — всё должно уметь ладить само с собой в двух версиях.
  • Мониторить надо в оба глаза. Надо смотреть на метрики, как ястреб: задержки, ошибки, память. Потому что если новый код начнёт жрать ресурсы или падать, ты должен это почуять раньше, чем все пользователи. Доверия ебать ноль к новому коду, только цифры и графики.