Rolling Updates: как обновлять без простоев и стресса

6456c38a17c2ca791e6641dabf0c8336.png

Привет, Хабр!

Сегодня поговорим о том, как избежать нервов во время деплоя с помощью стратегии Rolling Updates. Это один из самых лучших и безопасных способов обновления приложений. Если вы хотите минимизировать простои, исключить массовые ошибки и при этом уверенно управлять процессом обновления, Rolling Updates — это ваш выбор.

Rolling Updates — это стратегия деплоя, при которой обновление приложения происходит поэтапно, с минимальными перебоями в работе сервиса. Вместо остановки всех компонентов приложения и замены их новыми версиями, Rolling Updates обновляет небольшие группы (называемые батчами) экземпляров приложения, постепенно замещая старые версии новыми.

Подготовка

При планировании Rolling Updates, важно понимать, что речь идет о постепенном обновлении системы или приложения без полного отключения сервиса.

Для успешного Rolling Update необходима надежная инфраструктура и система мониторинга. В первую очередь, потребуется оркестратор, который может управлять параллельными процессами, как, например, Kubernetes.

Система мониторинга — это не просто опция, а основа. Необходимо отслеживать ключевые метрики.

Пример конфигурации для Kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 2
  template:
    spec:
      containers:
        - name: my-app-container
          image: my-app:latest

Задали стратегию RollingUpdate с параметрами maxUnavailable: 1 (максимум одна недоступная реплика) и maxSurge: 2 (максимум две новые реплики за раз).

Опытные команды SRE тщательно планируют батчи, основываясь на требованиях системы и текущих нагрузках. Здесь очень важен Service Level Objective (SLO), который определяет допустимые уровни доступности и производительности.

Стандартная рекомендация — обновлять не более 25% системы за один раз. Однако все зависит от специфики инфраструктуры. Например, в микросервисных архитектурах это число может быть выше, если каждый сервис изолирован и не оказывает сильного влияния на другие части системы.

Перед началом обновления протестируйте батчи на изолированных серверах или тестовых окружениях. Таким образом, можно будет предсказать поведение реальной системы и скорректировать параметры обновления.

Правильно настроенный мониторинг — залог успешного Rolling Update. Несколько метрик:

  • Время простоя: метрика, измеряющая перерывы в работе сервиса. Она должна стремиться к нулю в идеальных условиях. Небольшие увеличения могут быть допустимы, если обновление требует замены целых нод.

  • Процент обновленных нод: метрика, отображающая текущий прогресс деплоя.

  • Производительность системы: мониторьте CPU, RAM, и дисковую нагрузку. Особенно важно отслеживать аномальные скачки во время обновлений.

Реализация и управление Rolling Updates в Kubernetes

Пример простой конфигурации Rolling Updates в Kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-app:v1
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1

Rolling Updates происходит за счет параметров maxUnavailable и maxSurge. Первый отвечает за количество подов, которые могут быть недоступны во время обновления, а второй — за количество новых подов, которые могут быть созданы до того, как старые будут удалены.

Для того чтобы запустить обновление, достаточно изменить версию контейнера с помощью следующей команды:

kubectl set image deployment/my-app my-app-container=my-app:v2

Kubernetes начнет обновление в реальном времени, поэтапно заменяя поды старой версии новыми.

Следить за процессом можно командой:

kubectl rollout status deployment/my-app

Если что-то пошло не так, можно быстро откатить обновление:

kubectl rollout undo deployment/my-app

Kubernetes поддерживает механизмы для проверки готовности контейнеров через readiness probes и их живучести через liveness probes. Эти проверки позволяют убедиться, что обновленные контейнеры готовы к приему трафика, а приложение стабильно работает. Пример конфигурации проверок:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-health-app
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: my-health-app
    spec:
      containers:
      - name: my-health-container
        image: my-health-app:v1
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20

Используем readinessProbe для проверки готовности контейнера, и livenessProbe для контроля его состояния. Таким образом, только поды, которые успешно прошли проверку, остаются активными, что повышает надежность и снижает риск сбоев.

Также важно не забывать о том, что более сложные системы требуют гибкости. Kubernetes позволяет использовать процентные значения в параметрах maxUnavailable и maxSurge. Например:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-advanced-app
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: "20%"   # Динамическое значение для большого числа подов
      maxSurge: "50%"         # Ускорение деплоя за счет увеличения количества новых подов
  template:
    metadata:
      labels:
        app: my-advanced-app
    spec:
      containers:
      - name: my-advanced-app-container
        image: my-advanced-app:v2

В данном случае используются процентные значения, что позволяет динамически управлять процессом Rolling Updates для крупных приложений с большим количеством реплик.

Во время Rolling Updates могут возникать непредвиденные ситуации, например, контейнеры могут не пройти проверку готовности или возникнут проблемы с производительностью на отдельных подах. В таких случаях нужно откатить обновления:

kubectl rollout undo deployment/my-app

Этот откат возвращает систему к предыдущему стабильному состоянию.

Rolling Updates можно интегрировать с CI/CD инструментами, чтобы автоматизировать и ускорить процесс деплоя.

Пример конфигурации пайплайна с Jenkins:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t my-app:v2 .'
            }
        }
        stage('Deploy') {
            steps {
                sh 'kubectl set image deployment/my-app my-app-container=my-app:v2'
            }
        }
        stage('Monitor') {
            steps {
                script {
                    timeout(time: 10, unit: 'MINUTES') {
                        def status = sh(script: 'kubectl rollout status deployment/my-app', returnStatus: true)
                        if (status != 0) {
                            error "Rolling Update failed!"
                        }
                    }
                }
            }
        }
    }
}

Простой Jenkins пайплайн, который выполняет сборку Docker-образа, деплой на Kubernetes и мониторинг статуса обновления.

Лучшие практики по управлению надежностью, доступностью и эффективностью сервисов можно изучить на онлайн-курсе «SRE практики и инструменты».

© Habrahabr.ru