Хуки жизненного цикла контейнера (Container Lifecycle Hooks) в Kubernetes
В этом посте описано, как управляемые kubelet контейнеры могут использовать инфраструктуру хуков жизненного цикла контейнера для исполнения кода, запускаемого событиями в течение их жизненного цикла управления.
Аналогично многим языковым средам программирования (таким как Angular), которые имеют хуки жизненного цикла компонентов, Kubernetes предоставляет контейнерам хуки жизненного цикла. Хуки позволяют контейнерам узнавать о событиях в их жизненном цикле управления и запускать код, реализованный в обработчике, когда выполняется соответствующий хук жизненного цикла.
Контейнеры открыты для двух хуков:
PostStart
Этот хук выполняется сразу после создания контейнера. Тем не менее, нет никакой гарантии, что хук выполнится перед ENTRYPOINT контейнера. Параметры не передаются обработчику.
PreStop
Этот хук вызывается непосредственно перед тем, как контейнер завершается из-за запроса API или события управления, такого как сбой проверки жизнеспособности, вытеснение, конфликт ресурсов и другие. Вызов хука preStop завершается неудачно, если контейнер уже находится в terminated или completed состоянии. preStop это блокировка, синхронная, поэтому она должна быть завершена до того, как будет отправлен вызов на удаление контейнера. Параметры не передаются обработчику.
Реализации обработчиков хуков
Контейнеры могут получить доступ к хуку, реализовав и зарегистрировав обработчик для этого хука. Существует два типа обработчиков хуков, которые могут быть реализованы для контейнеров:
- Exec - выполняет определенную команду, такую как pre-stop.sh, внутри cgroups и пространств имен контейнера. Ресурсы, использованные командой, засчитываются в Контейнер.
- HTTP - выполняет HTTP-запрос к определенной конечной точке контейнера.
Исполнение обработчика хука
Когда вызывается хук управления жизненным циклом контейнера, система управления Kubernetes выполняет обработчик в контейнере, зарегистрированном для этого хука.
Вызовы обработчиков хуков являются синхронными в контексте pod'а, содержащего контейнер. Это означает, что для хука PostStart - ENTRYPOINT контейнера и хук срабатывают асинхронно. Однако, если хук занимает слишком много времени для запуска или зависает, контейнер не может достичь running состояния.
Поведение аналогично для хука PreStop. Если хук зависает во время выполнения, фаза Pod остается в состоянии Terminating и уничтожается после окончания TerminationGracePeriodSeconds pod'а. Если перехват PostStart или PreStop завершается неудачей, он убивает контейнер.
Пользователи должны сделать свои обработчики хуков максимально легкими. Однако существуют случаи, когда имеют смысл длительные команды, например, при сохранении состояния перед остановкой контейнера.
Гарантия выполнения хука
Предполагается, что выполнение хуков будет хотя бы один раз, что означает, что хук может быть вызван несколько раз для любого данного события, например для PostStart или PreStop. Это обязанность реализации хука - обрабатывать данную ситуацию корректно.
Как правило, осуществляются только разовые вызовы хуков. Если, например, получатель хука HTTP не работает и не может принимать трафик, не предпринимается попытка повторной отправки. Однако в некоторых редких случаях возможен двойной вызов хука. Например, если kubelet перезапускается в середине посылки хука, хук может быть повторно отправлен после того, как kubelet вернется.
Отладка обработчиков хуков
Журналы для обработчика хука не отображаются в событиях Pod. Если по какой-либо причине обработчик завершается ошибкой, он передает событие. Для PostStart это событие FailedPostStartHook, а для PreStop это событие FailedPreStopHook. Вы можете увидеть эти события, запустив kubectl describe pod <pod_name>. Вот пример вывода событий при выполнении этой команды:
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
Читайте также:
- Контейнеры в Kubernetes: образы (images)
- Контейнеры в Kubernetes: образы, использование частных реестров (Private Registry)
- Переменные среды контейнера в Kubernetes
Комментарии
Отправить комментарий