Поиск по сайту:

Как использовать хуки Kubernetes для отслеживания жизненного цикла контейнера


Хуки обычно используются для регистрации событий контейнера, реализации сценариев очистки и запуска асинхронных задач после присоединения нового пода к вашему кластеру. В этой статье мы покажем, как прикрепить обработчики ловушек к вашим подам и получить больше контроля над жизненными циклами контейнеров.

Два доступных крючка

Текущие выпуски Kubernetes поддерживают два хука жизненного цикла контейнера:

  • PostStart — обработчики этого хука вызываются сразу после создания нового контейнера.
  • PreStop. Этот хук вызывается непосредственно перед тем, как Kubernetes завершает работу контейнера.

Их можно обрабатывать с помощью двух разных механизмов:

  • Exec — запускает указанную команду внутри контейнера.
  • HTTP — делает HTTP-запрос к URL-адресу внутри контейнера.

Ни один из хуков не предоставляет никаких аргументов своим обработчикам. Каждый контейнер поддерживает один обработчик для каждого хука; невозможно вызвать несколько конечных точек или объединить команду exec с HTTP-запросом.

Определение обработчиков ловушек

Вы определяете обработчики ловушек для модулей, используя их поле манифеста containers.lifecycle. В этом поле задайте свойства postStart и preStop, чтобы реализовать один или оба доступных хука.

Вот простой модуль, который регистрирует сообщение при запуске:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-hooks
spec:
  containers:
    - name: pod-hook-container
      image: nginx:latest
      lifecycle:
        postStart:
          exec:
            command: ["/bin/sh", "-c", "echo STARTED > /startup_message"]

Примените Pod к своему кластеру с помощью Kubectl:

$ kubectl apply -f pod.yaml

Теперь добавьте оболочку в работающий контейнер внутри пода:

$ kubectl exec --stdin --tty pod/pod-with-hooks -- sh

Прочтите содержимое файла /startup_message:

$ cat /startup_message
STARTED

Это показывает, что хук был вызван успешно. Хук exec считается успешным, если его команда завершается с нулевым кодом состояния.

HTTP-обработчики

Вы можете настроить обработчик HTTP, заменив поле exec на httpGet. Поддерживаются только запросы HTTP GET (отсутствует поле httpPost).

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-hooks
spec:
  containers:
    - name: pod-hook-container
      image: nginx:latest
      lifecycle:
        postStart:
          httpGet:
            path: /startup
            port: 80

В этом примере Kubernetes отправляет запрос GET в /startup через порт 80 контейнера. Поле httpGet также принимает scheme и host для дальнейшей настройки запроса.

Вот модуль, в котором /shutdown вызывается через HTTPS до завершения работы контейнера:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-hooks
spec:
  containers:
    - name: pod-hook-container
      image: nginx:latest
      lifecycle:
        preStop:
          httpGet:
            path: /startup
            scheme: HTTPS

Обработчики HTTP-ловушек считаются успешными, если код ответа HTTP находится в диапазоне 200-299.

Отладка ваших обработчиков

Обработчики хуков управляются независимо от модулей, к которым они подключены. Их журналы не собираются и не хранятся вместе с обычными журналами Pod, поэтому вы не увидите команды exec, такие как echo Started, при запуске kubectl logs pod/pod-with-hooks.

Вы можете отлаживать хуки, просматривая историю событий пода. О неудачных вызовах сообщается как о событиях FailedPostStartHook и FailedPreStophook. Сообщение об ошибке включает описание того, что вызвало ошибку.

Попробуйте добавить этот модуль в свой кластер:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-hooks
spec:
  containers:
    - name: pod-hook-container
      image: nginx:latest
      lifecycle:
        postStart:
          exec:
            command: ["missing-command"]

Сломанный хук PostStart приведет к сбою запуска пода. Используйте kubectl описать, чтобы получить доступ к его истории событий:

$ kubectl describe pod/pod-with-hooks
...
Events:
  Type     Reason               Age                From               Message
  ----     ------               ----               ----               -------
  Normal   Scheduled            30s                default-scheduler  Successfully assigned pod-with-hooks...
  Normal   Created              10s (x2 over 11s)  kubelet            Created container pod-hook-container
  Normal   Started              10s (x2 over 11s)  kubelet            Started container pod-hook-container
  Warning  FailedPostStartHook  10s (x2 over 11s)  kubelet            Exec lifecycle hook ([missing-command]) for Container "pod-hook-container" in Pod "pod-with-hooks" failed - error: command 'missing-command' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "missing-command": executable file not found in $PATH: unknownrn"
  Normal   Killing              10s (x2 over 11s)  kubelet            FailedPostStartHook
  Warning  BackOff              5s (x2 over 6s)    kubelet            Back-off restarting failed container

Событие FailedPostStartHook указывает на сбой обработчика, поскольку missing-command не является допустимым исполняемым файлом внутри контейнера. Это привело к тому, что контейнер был уничтожен и перезапущен в цикле отсрочки. Это застрянет навечно, так как missing-command никогда не будет исполняемым.

На что обратить внимание

Вызовы хуков имеют несколько характеристик, которые могут вас застать врасплох. Помня об этом, вы сможете избежать странного поведения и неожиданных сбоев.

  • Хуки могут вызываться более одного раза. Kubernetes гарантирует, что ваши обработчики PostStart и PreStop будут вызываться «как минимум» один раз для каждого контейнера. . В некоторых ситуациях хук может вызываться несколько раз. Ваши обработчики должны быть идемпотентными, чтобы они могли противостоять этой возможности.
  • Неудачные перехватчики уничтожают свой контейнер. Как показано в приведенном выше примере отладки, неудачные перехватчики немедленно уничтожают свой контейнер. Вам нужно убедиться, что ваши команды и конечные точки HTTP не содержат ошибок, чтобы избежать непредвиденных проблем с запуском Pod. Обработчики хуков должны быть легкими и свободными от зависимостей. Не пытайтесь получить доступ к ресурсу, который может быть недоступен сразу после запуска вашего контейнера.
  • Перехватчики
  • PostStart соревнуются с ENTRYPOINT контейнера. PostStart срабатывает примерно в то же время, когда создается контейнер . Однако Kubernetes не ждет хука — он будет вызываться асинхронно вместе с ENTRYPOINT контейнера, что может завершиться до того, как будет вызван обработчик вашего хука. Это означает, что скрипт точки входа вашего контейнера начнет выполняться, даже если ваш обработчик сообщит об ошибке и в конечном итоге уничтожит контейнер.
  • Перехватчики
  • PreStop будут блокировать завершение работы контейнера. Kubernetes гарантирует, что ваши контейнеры не будут завершены до тех пор, пока их перехватчики PreStop не будут завершены, но не более время, определяемое льготным периодом завершения Pod. Контейнер будет закрыт независимо от того, работает ли хук по истечении льготного периода.
  • Перехватчики
  • PreStop не вызываются для завершенных модулей. Это может быть особенно эффективным в зависимости от вашего варианта использования. Текущая реализация PreStop срабатывает только тогда, когда Pod завершается из-за удаления, исчерпания ресурсов, сбоя проверки или подобного события. Ловушка не будет вызываться для контейнеров, которые останавливаются естественным образом, потому что их процесс завершает свою задачу и завершается с нулевым кодом ошибки.

Хуки напрямую влияют на жизненный цикл ваших модулей. Поды не могут быть помечены как Running, пока их хук PostStart не завершится; аналогично, Pod будет зависать Завершение до тех пор, пока PreStop не завершится.

Заключение

События жизненного цикла Kubernetes — это способ уведомить контейнеры об их собственном создании и предстоящем удалении. Предоставляя команды или конечные точки API внутри своего контейнера, вы можете отслеживать критические этапы жизненного цикла и сообщать о них другим компонентам вашей инфраструктуры.

События жизненного цикла легко настроить, но они также имеют некоторые распространенные ловушки. Вы можете использовать смежные механизмы, такие как тесты запуска и готовности, если вам нужен более надежный вызов. Это лучший вариант для сценариев, которые необходимы при подготовке среды нового контейнера.




Все права защищены. © Linux-Console.net • 2019-2024