На протяжении жизненного цикла приложения работа модулей может прекращаться по разным причинам. В некоторых случаях Kubernetes завершает работу модулей из-за действий пользователя (например, когда развертывание обновляется или удаляется). В других случаях Kubernetes завершает работу модулей, когда ему необходимо освободить ресурсы на данном узле. В любом случае Kubernetes позволяет контейнерам, работающим в модуле, корректно завершать работу в течение настраиваемого периода времени.
Взгляните на диаграмму ниже, чтобы лучше понять, что происходит, когда вы удаляете модуль.
Ниже приведены 2 сценария, при которых Pod отключается.
Плавное завершение работы
В этом случае контейнеры в модуле корректно завершают работу в течение льготного периода. Состояние «мягкого завершения работы» контейнера означает, что выполняются дополнительные перехватчики предварительной остановки, и модуль отвечает на сигнал SIGTERM. После успешного завершения работы контейнера Kubelet удаляет модуль с API-сервера.
Принудительное выключение
В этом случае контейнер не может быть отключен в течение льготного периода. Сбой при выключении может произойти по ряду причин, в том числе
Если приложение не может быть завершено в течение льготного периода, Kubelet отправляет сигнал SIGKILL, чтобы принудительно завершить работу процессов, запущенных в модуле. В зависимости от приложения это может привести к потере данных и ошибкам пользователя.
В этой статье мы сосредоточимся на корректном завершении работы.
В Kubernetes каждое развертывание означает удаление старого модуля и создание новой версии модуля.
Если во время этого процесса не происходит плавного завершения работы, могут возникнуть две проблемы:
В процессе удаления модулей Kubernetes существуют две параллельные временные шкалы, как показано на рисунке ниже. Одним из них является график изменения сетевых правил. Другой — удаление модуля.
Когда операционный персонал или конвейеры развертывания выполняютkubectl delete pod
команды, начинаются два процесса.
Сетевые правила вступают в силу
удалить модуль
проходитьудалить модуль В процессе мы видим, что если процесс в контейнере не настроен, то контейнер немедленно завершит работу, что вызовет проблемы. 1。
Поскольку обновление сетевых правил и удаление модуля происходят одновременно, нет гарантии, что сетевые правила будут обновлены до удаления модуля. Вот что может быть причиной проблемы 2.
Следующая конфигурация может решить эти проблемы:
На изображении ниже показана временная шкала после установки.
К вопросу 1: Настройте плавное завершение процессов внутри контейнеров.
На примере SpringBoot, чтобы включить плавное завершение работы, вы можете добавить следующие параметры в файл конфигурации Spring Boot:
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
Используя приведенную выше конфигурацию, Spring Boot гарантирует, что новые запросы не будут приняты после получения SIGTERM и что все текущие запросы будут обработаны в течение тайм-аута. Даже если его не удастся завершить вовремя, соответствующая информация будет записана, а затем принудительно удалена.
Значение таймаута должно быть привязано к максимально допустимой продолжительности обработки запроса. По нашему опыту, все запросы обычно обрабатываются в течение 30 секунд, за исключением особых обстоятельств. Для тех, которые не завершаются в течение определенного времени ожидания, мы фиксируем время ожидания в журнале мониторинга и отправляем предупреждение, затем устраняем основную причину тайм-аута и предпринимаем соответствующие действия.
Вот как можно решить проблему 1. Другие языки и фреймворки должны иметь аналогичные конфигурации.
Для вопроса 2: добавьте preStopHook.
чтобы справиться с проблемами 2. Мы больше не должны направлять новый трафик на pod Затем начните удалять под. Следовательно, должно быть preStopHook добавить в Kubernetes yaml файл,пусть Kubelet существоватьполучатьудалить модуль событие «сон один раз”,исуществоватьначинатьудалить модуль Подождите достаточно времени, прежде чем обновлять сетевые правила.
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"] # set prestop hook
Приведенная выше конфигурация заставит Kubelet ждать установленное время.
Изменить завершение GracePeriodSeconds
Ссылаясь на предыдущий анализ удаления Pod, Kubernetes оставляет максимальный интервал времени в 30 секунд для удаления контейнера. Если сумма времени ожидания плавного завершения работы Spring и preStopHooks Kubernetes превышает 30 секунд, это может привести к тому, что Kubernetes принудительно удалит контейнер до того, как Spring Boot завершит обработку запроса. Таким образом, если процесс занимает более 30 секунд, timerminationGracePeriodSeconds следует настроить так, чтобы он превышал время ожидания плавного завершения работы Spring плюс preStopHook.
terminationGracePeriodSeconds: 45
Наконец, полный yaml-файл Kubernetes выглядит так:
apiVersion: apps/v1
kind: Deployment
metadata:
name: gracefulshutdown-app
spec:
replicas: 3
selector:
matchLabels:
app: gracefulshutdown-app
template:
metadata:
labels:
app: gracefulshutdown-app
spec:
containers:
- name: graceful-shutdown-test
image: gracefulshutdown-app:latest
ports:
- containerPort: 8080
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"] #set prestop hook
terminationGracePeriodSeconds: 45 # terminationGracePeriodSeconds
С помощью этих трех шагов мы можем полностью решить обе проблемы.
В этой статье описано решение,Используется, чтобы гарантировать, что гипотетическая служба будет правильно обрабатывать все запросы, необходимые для развертывания с нулевым временем простоя. поэтому,Создание этой функциональности улучшит взаимодействие с пользователем и уменьшит влияние дефектов в сервисе.
оригинал: https://yashwanth-nimmala.medium.com/kubernetes-graceful-shutdown-73bb23af2abd
- END -