Как выполнять обновления с нулевым временем простоя в Kubernetes с помощью Rolling Updates
Настройте rolling updates в Kubernetes с помощью readiness probes, maxSurge, maxUnavailable и graceful shutdown.
Как выполнять обновления с нулевым временем простоя в Kubernetes с помощью Rolling Updates
Rolling updates в Kubernetes могут заменять Pod'ы без видимого простоя, но только если ваш Deployment и ваше приложение согласованы в том, когда Pod готов и как он должен завершать работу. Стратегия по умолчанию помогает, но не спасает от плохих readiness probes, несовместимых релизов или потерянных запросов в полете.
Достижение истинного нулевого времени простоя, однако, требует большего, чем просто конфигурация Kubernetes по умолчанию. Это требует тщательной координации между манифестом Deployment, конечными точками здоровья приложения и процессом корректного завершения. Это руководство предоставляет комплексный пошаговый подход к настройке Kubernetes Deployments для обеспечения бесшовных и незаметных для конечного пользователя обновлений приложения.
Это руководство охватывает readiness probes, maxSurge, maxUnavailable и корректное завершение, чтобы ваш сервис сохранял пропускную способность во время развертывания.
Предварительные условия для нулевого времени простоя
Перед настройкой манифеста Kubernetes базовое приложение должно соответствовать определенным принципам для поддержки развертываний с нулевым временем простоя:
- Обратная совместимость приложения: В течение короткого периода, когда старая и новая версии приложения работают одновременно, они должны быть совместимы с общими ресурсами (базы данных, очереди, кэши).
- Идемпотентность: Операции, которые могут обрабатываться обеими версиями, должны быть повторяемыми без негативных побочных эффектов.
- Корректное завершение: Приложение должно быть запрограммировано на распознавание сигнала
SIGTERM, отправляемого Kubernetes, и корректно прекращать прием новых соединений, завершая текущие запросы перед выходом.
Понимание стратегии Rolling Update в Kubernetes
Deployments в Kubernetes по умолчанию используют стратегию RollingUpdate. Этот метод гарантирует, что старая версия приложения не будет полностью удалена до того, как новая версия станет работоспособной, управляя переходом с помощью двух основных параметров:
| Параметр | Описание | Влияние на нулевое время простоя |
|---|---|---|
maxSurge |
Определяет максимальное количество Pod'ов, которое может быть создано сверх желаемого количества реплик. Может быть абсолютным числом или процентом (по умолчанию: 25%). | Контролирует скорость развертывания и гарантирует временное увеличение емкости. |
maxUnavailable |
Определяет максимальное количество Pod'ов, которые могут быть недоступны во время обновления. Может быть абсолютным числом или процентом (по умолчанию: 25%). | Критически важно для нулевого времени простоя. Установка этого значения в 0% означает, что ни один обслуживающий Pod не будет завершен до тех пор, пока новые Pod'ы не станут полностью Ready. |
Рекомендуемая стратегия для нулевого времени простоя
Для максимальной доступности лучшей конфигурацией часто является обеспечение отсутствия потери емкости во время простоя:
maxUnavailable: 0(Гарантирует, что емкость никогда не снижается).maxSurge: 1или25%(Позволяет емкости временно превысить целевую, гарантируя, что новый Pod готов до того, как старый будет остановлен).
Шаг 1: Реализация Readiness Probes
Readiness Probe — это самый важный механизм для обеспечения обновлений с нулевым временем простоя. Kubernetes полагается на этот зонд, чтобы определить, готов ли новый Pod принимать пользовательский трафик и продолжает ли старый Pod активно обслуживать трафик.
Liveness vs. Readiness
- Liveness Probe: Сообщает Kubernetes, здоров ли контейнер и функционирует ли он. Если он не проходит проверку, контейнер перезапускается.
- Readiness Probe: Сообщает Kubernetes, готов ли контейнер обслуживать запросы. Если он не проходит проверку, Pod удаляется из конечных точек связанного Service, перенаправляя трафик от него до тех пор, пока он не станет готов.
Для rolling updates Readiness Probe используется для управления переходом. Kubernetes не приступит к завершению старого Pod'а, пока вновь созданный Pod успешно не пройдет свою проверку готовности.
# фрагмент deployment.yaml
spec:
containers:
- name: my-app
image: myregistry/my-app:v2.0
ports:
- containerPort: 8080
# --- Конфигурация Readiness Probe ---
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 15 # Время ожидания перед первой попыткой зондирования
periodSeconds: 5 # Как часто выполнять проверку
timeoutSeconds: 3
failureThreshold: 3 # Количество последовательных неудач для пометки Pod'а как не готового
# --- Конфигурация Liveness Probe (Стандартная проверка здоровья) ---
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
Совет: Убедитесь, что конечная точка
/health/readyвашего приложения возвращает код успеха (HTTP 200-299) только когда инициализация, подключения к базе данных и другие внешние зависимости полностью работоспособны.
Шаг 2: Настройка стратегии Deployment
Чтобы обеспечить истинное нулевое время простоя, мы явно настраиваем стратегию rolling update, чтобы предотвратить любое снижение количества доступных реплик.
В этой конфигурации Kubernetes сначала создаст новый Pod (maxSurge: 1). Как только новый Pod пройдет свою readiness probe, только тогда Kubernetes завершит старый Pod. Поскольку maxUnavailable равно 0, емкость сервиса никогда не опускается ниже целевого количества реплик.
# фрагмент deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-deployment
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
# Гарантирует, что емкость никогда не опускается ниже желаемого количества реплик (4)
maxUnavailable: 0
# Позволяет создать один дополнительный Pod во время развертывания
maxSurge: 1
template:
# ... спецификация контейнера ...
Шаг 3: Обеспечение корректного завершения (Graceful Termination)
Даже с надежными readiness probes, если приложение мгновенно завершает работу при получении сигнала завершения, оно рискует потерять запросы в полете.
Kubernetes следует определенной последовательности завершения:
- Pod помечается как Terminating.
- Pod удаляется из конечных точек Service (трафик перестает направляться к нему).
- Выполняется pre-stop hook (если определен).
- Контейнер получает сигнал
SIGTERM. - Kubernetes ожидает в течение времени, определенного
terminationGracePeriodSeconds(по умолчанию: 30 секунд). - Если контейнер все еще работает, он получает безальтернативный
SIGKILL.
Чтобы обеспечить корректное завершение, приложение должно обрабатывать SIGTERM, а terminationGracePeriodSeconds должно быть достаточно длинным, чтобы приложение могло завершить существующие запросы.
# фрагмент deployment.yaml, внутри спецификации шаблона Pod
spec:
terminationGracePeriodSeconds: 45 # Настройка на уровне Pod
containers:
- name: my-app
image: myregistry/my-app:v2.0
lifecycle:
preStop:
exec:
# Дает время для обновления конечных точек и внешних балансировщиков нагрузки.
command: ["/bin/sh", "-c", "sleep 10"]
Лучшая практика: Ваше приложение должно прекращать прием новой работы при получении
SIGTERM, затем завершать текущие запросы перед выходом. Немного более длинныйterminationGracePeriodSeconds, например, 45 или 60 секунд, помогает предотвратить жесткое завершение для медленных запросов.
Шаг 4: Выполнение и мониторинг обновления
Как только ваш манифест Deployment включает оптимизированную стратегию и надежные зонды, выполнение обновления становится простым.
Обновите тег образа: Измените манифест развертывания, чтобы отразить новую версию образа (например, с
v2.0наv2.1).Примените конфигурацию:
kubectl apply -f deployment.yamlАльтернативно, вы можете пропатчить образ напрямую:
kubectl set image deployment/my-web-deployment my-app=myregistry/my-app:v2.1Отслеживайте статус развертывания: Наблюдайте, как Kubernetes проходит этапы, проверяя, что количество готовых Pod'ов никогда не опускается ниже желаемого.
kubectl rollout status deployment/my-web-deploymentПроверьте доступность Pod'ов: Наблюдайте за статусом Pod'ов, чтобы подтвердить, что старые Pod'ы (v2.0) корректно завершаются только после того, как новые Pod'ы (v2.1) полностью готовы.
kubectl get pods -l app=my-web-deployment -w
Продвинутые соображения
Использование Pod Disruption Budgets (PDBs)
В то время как стратегия развертывания управляет развертываниями, Pod Disruption Budget (PDB) ограничивает добровольные сбои, такие как осушение узлов и некоторые операции обслуживания кластера. Он не предотвращает каждую незапланированную ошибку, но дает Kubernetes и инструментам автоматизации минимальную цель доступности, которую необходимо соблюдать.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 75% # Гарантирует, что как минимум 75% реплик всегда доступны
selector:
matchLabels:
app: my-web-deployment
Важность начальной задержки
Если вашему приложению требуется время для прогрева, настройте initialDelaySeconds, periodSeconds и failureThreshold так, чтобы готовность отражала реальное поведение при запуске. Неудачная readiness probe удерживает Pod вне конечных точек Service; неудачная liveness probe может перезапустить контейнер и создать цикл перезапуска.
Развертывайте безопасно
Достижение истинных rolling updates с нулевым временем простоя в Kubernetes — это комбинация надежной конфигурации платформы и дисциплинированной разработки приложений. Правильно используя Readiness Probes для сигнализации о рабочем состоянии, настраивая стратегию Deployment (maxUnavailable: 0) для поддержания емкости и реализуя обработчики корректного завершения, вы можете гарантировать, что обновления приложения выполняются надежно, не нарушая обслуживание ваших пользователей. Всегда тщательно тестируйте процесс обновления в среде staging, чтобы проверить период ожидания завершения и логику зондов.