Привет, Хабр!
Сегодня поговорим о том, как избежать нервов во время деплоя с помощью стратегии 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 практики и инструменты».