Что такое Pod и зачем он нужен

Модули (pods) - это наименьшие развертываемые вычислительные единицы, которые могут создаваться и управляться в Kubernetes.

Pod представляет собой группу из одного или нескольких контейнеров (например, контейнеров Docker) с общим хранилищем/сетью и спецификацией для запуска контейнеров. Содержимое pod всегда находится в одном месте, запускается по одному расписанию и работает в общем контексте. Pod моделирует специфический для приложения "логический хост" - он содержит один или несколько контейнеров приложений, которые относительно тесно связаны - в мире, предшествующем контейнеру, выполнение на одной физической или виртуальной машине означало бы выполнение на одном логическом хосте.

В то время как Kubernetes поддерживает больше сред выполнения контейнеров, чем просто Docker, Docker является наиболее известной средой выполнения и помогает описывать Pod в терминах Docker.

Общий контекст Pod представляет собой набор пространств имен Linux, cgroups и, возможно, других аспектов изоляции - те же самые вещи, которые изолируют контейнер Docker. В контексте pod, отдельные приложения могут иметь дополнительные субизоляции.

Контейнеры в Pod совместно используют IP-адрес и пространство портов и могут находить друг друга через localhost. Они также могут связываться друг с другом, используя стандартные межпроцессные взаимодействия, такие как семафоры SystemV или разделяемая память (shared memory) POSIX. Контейнеры в разных pod имеют разные IP-адреса и не могут связываться по IPC без специальной настройки. Эти контейнеры обычно связываются друг с другом через IP-адреса Pod.

Приложения внутри pod также имеют доступ к общим томам, которые определены как часть pod и доступны для подключения в файловую систему каждого приложения.

В терминах конструкций Docker Pod моделируется как группа контейнеров Docker с общими пространствами имен и общими томами файловой системы.

Как и отдельные контейнеры для приложений, pod считаются относительно эфемерными (а не долговечными) объектами. Pod создаются, им назначается уникальный идентификатор (UID) и они распределяются по узлам, где они остаются до завершения (согласно политике перезапуска) или удаления. Если узел умирает, то Pod, запланированные для этого узла, планируется удалить после истечения времени ожидания. Данный Pod (как определено UID) не “rescheduled” ("перепланирован") на новый узел; вместо этого он может быть заменен идентичным pod, даже c тем же именем (если требуется), но с новым UID.

Когда говорят, что что-то имеет то же время жизни, что и Pod, например том (volume), это означает, что оно существует до тех пор, пока существует этот Pod (с этим UID). Если этот Pod удаляется по какой-либо причине, даже если создается идентичная замена, связанная вещь (например, том) также уничтожается и создается заново.

Преимущества Pod

1. Управление pod'ами

Pod - это модель множества взаимодействующих процессов, которые образуют единое целое. Они упрощают развертывание приложений и управление ими, предоставляя абстракцию более высокого уровня, чем набор составляющих их приложений. Pod служат единицей развертывания, горизонтального масштабирования и репликации. Совместное размещение (совместное планирование), общая судьба (например, завершение), координированная репликация, совместное использование ресурсов и управление зависимостями обрабатываются автоматически для контейнеров в pod.

2. Обмен ресурсами и общение

Pod обеспечивают обмен данными и связь между их составляющими.

Все приложения в Pod используют одно и то же пространство имен сети (один и тот же IP-адрес и пространство портов) и, таким образом, могут "находить" друг друга и обмениваться данными с помощью localhost. Из-за этого приложения в pod должны координировать использование портов. Каждый pod имеет IP-адрес в едином сетевом пространстве, которое полностью взаимодействует с другими физическими компьютерами и pod'ами в сети.

Контейнеры внутри Pod видят, что имя хоста системы совпадает с настроенным именем для Pod.

В дополнение к определению контейнеров приложений, которые запускаются в Pod, Pod определяет набор общих томов хранения (storage volumes). Тома позволяют данным переживать перезапуски контейнеров и делиться ими между приложениями в Pod.

Использование Pod'ов

Pod'ы могут использоваться для размещения вертикально интегрированных стеков приложений (например, LAMP), но их основной мотивацией является поддержка совмещенных, совместно управляемых вспомогательных программ, таких как:

  • системы управления контентом, загрузчики файлов и данных, менеджеры локального кэша и т.д.
  • резервное копирование журналов и контрольных точек, сжатие, вращение (rotation), создание snapshot'ов и т.д.
  • наблюдатели за изменениями данных, журналы событий, адаптеры регистрации и мониторинга, издатели событий и т.д.
  • прокси, мосты и адаптеры
  • контроллеры, менеджеры, конфигураторы и средства обновления

Отдельные Pod'ы не предназначены для запуска нескольких экземпляров одного и того же приложения внутри себя.

Рассмотренные альтернативы

Почему бы просто не запустить несколько программ в одном (Docker) контейнере?

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

Почему бы не поддерживать совместное планирование контейнеров?

Такой подход обеспечит совместное размещение, но не обеспечит большинство преимуществ Pod'ов, таких как совместное использование ресурсов, IPC, гарантированное совместное использование судьбы и упрощенное управление.

Долговечность Pod'ов (или ее отсутствие)

Pod'ы не предназначены для длительного пользования. Они не выдержат сбоев планирования, сбоев узлов или других выселений, например, из-за нехватки ресурсов или в случае обслуживания узлов.

Как правило, пользователям не нужно создавать Pod'ы напрямую. Они почти всегда должны использовать контроллеры даже для синглтонов, например, Deployments. Контроллеры обеспечивают самовосстановление в области кластера, а также управление репликацией и развертыванием. Контроллеры, такие как StatefulSet, также могут обеспечивать поддержку Pod'ов с сохранением состояния.

Использование коллективных API-интерфейсов в качестве основного пользовательского примитива относительно распространено среди систем кластерного планирования, включая Borg, Marathon, Aurora и Tupperware.

Pod представлен как примитив, чтобы облегчить:

  • возможность подключения планировщика и контроллера
  • поддержку операций на уровне pod без необходимости проводить операции через "прокси" API контроллеров
  • отделение времени жизни Pod от времени жизни контроллера, например, для начальной загрузки
  • разъединение контроллеров и сервисов - контроллер конечной точки просто следит за Pod'ами
  • чистую композицию функциональности уровня Kubelet с функциональностью уровня кластера - Kubelet по сути является "pod контроллером"
  • работу приложений с высокой доступностью, которые ожидают замены pod'ов до их завершения и, конечно, до удаления, например, в случае запланированного выселения или предварительной загрузки образа.

Завершение (Termination) Pod'ов

Поскольку Pod'ы представляют собой запущенные процессы на узлах в кластере, важно, чтобы эти процессы корректно завершались, когда они больше не нужны (как альтернатива насильственному уничтожению с помощью сигнала KILL и отсутствию возможности очистки). Пользователи должны иметь возможность запрашивать удаление и знать, когда процессы завершаются, но также быть в состоянии гарантировать, что удаление в конечном итоге завершится. Когда пользователь запрашивает удаление Pod'а, система записывает предполагаемый льготный период, прежде чем разрешить принудительное уничтожение Pod'а, и сигнал TERM отправляется главному процессу в каждом контейнере. По истечении льготного периода этим процессам отправляется сигнал KILL, а затем Pod удаляется с сервера API. Если Kubelet или диспетчер контейнеров перезапускаются во время ожидания завершения процессов, завершение будет повторено с полным льготным периодом.

Пример потока завершения:

  1. Пользователь отправляет команду на удаление Pod с льготным периодом по умолчанию (30 с)
  2. Pod в сервере API обновляется временем (вместе с льготным периодом), после которого Pod считается "мертвым" (“dead”).
  3. Pod отображается как “Terminating” ("Завершающийся"), когда указан в клиентских командах
  4. (одновременно с шагом 3) Когда Kubelet видит, что Pod был отмечен как terminating, потому что время в шаге 2 было установлено, он начинает процесс выключения Pod.
    1. Если один из контейнеров Pod определил хук preStop, он вызывается внутри контейнера. Если хук preStop все еще работает после истечения льготного периода, то шаг 2 вызывается с небольшим (2 секунды) продленным льготным периодом.
    2. Контейнеру отправляется сигнал TERM. Обратите внимание, что не все контейнеры в Pod'е будут получать сигнал TERM в одно и то же время, и каждый из них может потребовать хук preStop, если порядок, в котором они закрываются, имеет значение.
  5. (одновременно с шагом 3) Pod удален из списка конечных точек для обслуживания и больше не считается частью набора работающих Pod' для контроллеров репликации. Pod'ы, которые медленно отключаются, не могут продолжать обслуживать трафик, поскольку балансировщики нагрузки (например, прокси-сервер службы) прекращают их использовать.
  6. Когда льготный период истекает, любые процессы, все еще работающие в Pod'е, уничтожаются с помощью SIGKILL.
  7. Kubelet завершит удаление Pod на сервере API, установив льготный период 0 (немедленное удаление). Pod исчезает из API и больше не виден клиенту.
  8. По умолчанию все удаления выполняются в течение 30 секунд. Команда kubectl delete поддерживает параметр --grace-period=<секунд>, который позволяет пользователю переопределить значение по умолчанию и указать собственное значение. Значение 0 удаляет Pod. Вы должны указать дополнительный флаг --force вместе с --grace-period=0, чтобы выполнить принудительное удаление.

Принудительное удаление Pod'ов

Принудительное удаление Pod'а определяется как удаление Pod из состояния кластера и etcd немедленно. Когда выполняется принудительное удаление, сервер API не ожидает подтверждения от kubelet о том, что Pod был завершен на узле, на котором он работал. Он немедленно удаляет Pod в API, поэтому можно создать новый Pod с тем же именем. На узле Pod'ам, которые настроены на немедленное завершение, все равно будет предоставлен небольшой льготный период, прежде чем их принудительно завершат.

Принудительное удаление может быть потенциально опасным для некоторых Pod'ов и должно выполняться с осторожностью.

Привилегированный режим для контейнеров Pod'а

Любой контейнер в Pod может включить привилегированный режим, используя privileged флаг в контексте безопасности (securityContext) спецификации (spec) контейнера. Это полезно для контейнеров, которые хотят использовать возможности Linux, такие как управление сетевым стеком и доступ к устройствам. Процессы в контейнере получают почти те же привилегии, которые доступны процессам вне контейнера. В привилегированном режиме должно быть проще писать подключаемые Pod'ы для сети и томов в виде отдельных Pod'ов, которые не нужно компилировать в kubelet.

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


Читайте также:


Комментарии

Популярные сообщения из этого блога

Контроллеры в Kubernetes: DaemonSet

Контроллеры в Kubernetes: ReplicaSet

Контроллеры в Kubernetes: StatefulSet