Information in this document may be out of date
This document has an older update date than the original, so the information it contains may be out of date. If you're able to read English, see the English version for the most up-to-date information: Container Lifecycle Hooks
Хуки жизненного цикла контейнеров
На этой странице описывается, как контейнеры под управлением kubelet могут использовать механизм хуков для запуска кода, инициированного событиями во время своего жизненного цикла.
Общая информация
Многие платформы для разработки предлагают хуки жизненного цикла компонентов (например, Angular). Kubernetes имеет аналогичный механизм. Хуки позволяют контейнерам оставаться в курсе событий своего жизненного цикла и запускать запакованный в обработчик код при наступлении определенных событий, приводящих к вызову хука.
Хуки контейнеров
В распоряжении контейнеров имеются два хука:
PostStart
Выполняется сразу после создания контейнера. Однако нет гарантии, что хук закончит работу до ENTRYPOINT контейнера. Параметры обработчику не передаются.
PreStop
Вызывается непосредственно перед завершением работы контейнера в результате запроса API или иного события (например, неудачное завершение теста liveness/startup, вытеснение, борьба за ресурсы и т.п.). Вызов хука PreStop
завершается неудачно, если контейнер уже находится в прерванном (terminated) или завершенном (completed) состоянии. Кроме того, работа хука должна закончиться до того, как будет отправлен сигнал TERM для остановки контейнера. Отсчет задержки перед принудительной остановкой Pod'а (grace-период) начинается до вызова хука PreStop
. Таким образом, независимо от результата выполнения обработчика, контейнер будет остановлен в течение этого grace-периода. Параметры обработчику не передаются.
Более подробное описание поведения при прекращении работы можно найти в разделе Прекращение работы Pod'ов.
Реализации обработчиков хуков
Чтобы контейнер имел доступ к хуку, необходимо реализовать и зарегистрировать обработчик для этого хука. Существует два типа обработчиков хуков, доступных для контейнеров:
- Exec — Выполняет определенную команду, например,
pre-stop.sh
, внутри cgroups и пространств имен контейнера. Ресурсы, потребляемые командой, прибавляются к ресурсам, потребляемым контейнером. - HTTP — Выполняет HTTP-запрос к определенной конечной точке контейнера.
Выполнение обработчиков хуков
При вызове хука, привязанного к жизненному циклу контейнера, система управления Kubernetes выполняет обработчик в соответствии с типом хука: kubelet отвечает за httpGet
и tcpSocket
, а exec
выполняется в контейнере.
Вызовы обработчиков хуков синхронны в контексте Pod'а, содержащего контейнер. Это означает, что в случае PostStart
-хука ENTRYPOINT контейнера и хук запускаются асинхронно. При этом если хук выполняется слишком долго или зависает, контейнер не может достичь состояния Running
.
Хуки PreStop
не запускаются асинхронно с сигналом на остановку контейнера; хук должен завершить свою работу до отправки сигнала TERM. Если хук PreStop
зависнет во время выполнения, Pod будет пребывать в состоянии Terminating
до истечения периода terminationGracePeriodSeconds
, после чего Kubernetes "убьет" его. Этот grace-период включает как время, которое требуется для выполнения хука PreStop
, так и время, необходимое для нормальной остановки контейнера. Например, если terminationGracePeriodSeconds
равен 60, работа хука занимает 55 секунд, а контейнеру требуется 10 секунд для нормальной остановки после получения сигнала, то контейнер будет "убит" до того, как сможет нормально завершить свою работу, поскольку terminationGracePeriodSeconds
меньше, чем суммарное время (55+10), необходимое для работы хука и остановки контейнера.
Если любой из хуков postStart
/ preStop
завершается неудачей, Kubernetes "убивает" контейнер.
Поэтому обработчики для хуков должны быть максимально простыми. Однако бывают случаи, когда применение "тяжелых" команд оправдано – например, при сохранении состояния перед остановкой контейнера.
Гарантии поставки хука
Хук должен выполниться хотя бы один раз. Это означает, что он может вызываться неоднократно для любого события вроде PostStart
или PreStop
. Задача по правильной обработке подобных вызовов возложена на сам хук.
Как правило, поставка хука выполняется однократно. Если, например, приемник HTTP-хука не работает и не может принимать трафик, повторная попытка отправки не предпринимается. В редких случаях может происходить двойная поставка. Например, если kubelet перезапустится в процессе доставки хука, тот может быть отправлен повторно.
Отладка обработчиков хуков
Логи обработчиков хуков не отображаются в событиях Pod'а. В случае сбоя обработчика тот транслирует событие. Для PostStart
это событие FailedPostStartHook
, для PreStop
— событие FailedPreStopHook
. Чтобы самостоятельно сгенерировать событие FailedPreStopHook
, в манифесте lifecycle-events.yaml замените команду для postStart на что-то заведомо невыполнимое (badcommand
) и примените его. Если теперь выполнить команду kubectl describe pod lifecycle-demo
, вы увидите следующее:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7s default-scheduler Successfully assigned default/lifecycle-demo to ip-XXX-XXX-XX-XX.us-east-2...
Normal Pulled 6s kubelet Successfully pulled image "nginx" in 229.604315ms
Normal Pulling 4s (x2 over 6s) kubelet Pulling image "nginx"
Normal Created 4s (x2 over 5s) kubelet Created container lifecycle-demo-container
Normal Started 4s (x2 over 5s) kubelet Started container lifecycle-demo-container
Warning FailedPostStartHook 4s (x2 over 5s) kubelet Exec lifecycle hook ([badcommand]) for Container "lifecycle-demo-container" in Pod "lifecycle-demo_default(30229739-9651-4e5a-9a32-a8f1688862db)" failed - error: command 'badcommand' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: \"badcommand\": executable file not found in $PATH: unknown\r\n"
Normal Killing 4s (x2 over 5s) kubelet FailedPostStartHook
Normal Pulled 4s kubelet Successfully pulled image "nginx" in 215.66395ms
Warning BackOff 2s (x2 over 3s) kubelet Back-off restarting failed container
Что дальше
- Дополнительная информация о контейнерном окружении.
- Упражнение: Подключаем обработчики к событиям жизненного цикла контейнера.