--- reviewers: - TBD - TBD title: Хуки жизненного цикла контейнеров content_type: concept weight: 30 --- На этой странице описывается, как контейнеры под управлением kubelet могут использовать механизм хуков для запуска кода, инициированного событиями во время своего жизненного цикла. ## Общая информация Многие платформы для разработки предлагают хуки жизненного цикла компонентов (например, Angular). Kubernetes имеет аналогичный механизм. Хуки позволяют контейнерам оставаться в курсе событий своего жизненного цикла и запускать запакованный в обработчик код при наступлении определенных событий, приводящих к вызову хука. ## Хуки контейнеров В распоряжении контейнеров имеются два хука: `PostStart` Выполняется сразу после создания контейнера. Однако нет гарантии, что хук закончит работу до ENTRYPOINT контейнера. Параметры обработчику не передаются. `PreStop` Вызывается непосредственно перед завершением работы контейнера в результате запроса API или иного события (например, неудачное завершение теста liveness/startup, вытеснение, борьба за ресурсы и т.п.). Вызов хука `PreStop` завершается неудачно, если контейнер уже находится в прерванном (terminated) или завершенном (completed) состоянии. Кроме того, работа хука должна закончиться до того, как будет отправлен сигнал TERM для остановки контейнера. Отсчет задержки перед принудительной остановкой Pod'а (grace-период) начинается до вызова хука `PreStop`. Таким образом, независимо от результата выполнения обработчика, контейнер будет остановлен в течение этого grace-периода. Параметры обработчику не передаются. Более подробное описание поведения при прекращении работы можно найти в разделе [Прекращение работы Pod'ов](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination). ### Реализации обработчиков хуков Чтобы контейнер имел доступ к хуку, необходимо реализовать и зарегистрировать обработчик для этого хука. Существует два типа обработчиков хуков, доступных для контейнеров: * 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](https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/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 ``` ## {{% heading "whatsnext" %}} * Дополнительная информация о [контейнерном окружении](/docs/concepts/containers/container-environment/). * Упражнение: [Подключаем обработчики к событиям жизненного цикла контейнера](/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/).