Прим. перев.: Эта статья продолжает цикл материалов от технического писателя из Google, работающего над документацией для Kubernetes (Andrew Chen), и директора по software engineering из SAP (Dominik Tornow). Их цель — доступно и наглядно объяснить основы организации Kubernetes. В прошлый раз мы переводили статью про high availability, а теперь речь пойдет про такое базовое понятие в Kubernetes, как pod.



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

Pods (Поды) — базовые строительные блоки Kubernetes, однако даже опытные пользователи Kubernetes не всегда могут объяснить, что же это такое.

Данная публикация предлагает лаконичную мысленную модель, которая проливает свет на определяющие характеристики pod'ов Kubernetes. Ради этой краткости пришлось опустить некоторые другие особенности Pod'ов, такие как liveness и readiness probes, разделение ресурсов (включая появившееся недавно namespace sharingприм. перев.), работу с сетью.

Определение


Pod представляет собой запрос на запуск одного или более контейнеров на одном узле.

Pod определяется представлением запроса на запуск (execute) одного или более контейнеров на одном узле, и эти контейнеры разделяют доступ к таким ресурсам, как тома хранилища и сетевой стек.

Однако в обиходе термин «pod» может употребляться и в смысле этого запроса, и в смысле совокупности контейнеров, которые запускаются в ответ на запрос. Поэтому в публикации мы будем использовать слово «pod», когда говорим о запросе, а для второго случая — употреблять выражение «набор контейнеров».

Pod'ы считаются базовыми строительными блоками Kubernetes, потому что все рабочие нагрузки в Kubernetes — например, Deployments, ReplicaSets и Jobs — могут быть выражены в виде pod'ов.

Pod — это один и единственный объект в Kubernetes, который приводит к запуску контейнеров. Нет pod'а — нет контейнера!


Схема 1. Deployment, ReplicaSet, pod и контейнеры

Архитектура Kubernetes



Схема 2. Pod'ы, планировщик (Scheduler) и Kubelet

На этой иллюстрации выделены соответствующие объекты и компоненты. Pod'ы представлены как Kubernetes Pod Objects, а работой с ними занимаются:

  • планировщик (Scheduler),
  • Kubelet.


Объекты Kubernetes



Схема 3. Объекты Kubernetes

На этой иллюстрации показаны объекты Kubernetes, ответственные за работу с pod'ом:

  • собственно объект pod'а (Pod Object);
  • объект связывания (Binding Object);
  • объект узла (Node Object).

Pod Object задаёт набор контейнеров, которые будут запущены, и желаемую политику перезапуска (restart policy) в случае падения контейнера, а также отслеживает состояние запуска.

Binding Object привязывает Pod Object к Node Object, т.е. назначает pod на узел для последующего запуска.

Node Object представляет узел в кластере Kubernetes.

Обработка pod'а



Схема 4. Обработка pod'а

Когда pod создан пользователем или контроллером вроде ReplicaSet Controller или Job Controller, Kubernetes обрабатывает pod в два этапа:

  • Scheduler планирует pod,
  • Kubelet запускает pod.

Планирование pod'а



Схема 5. Управляющий цикл планировщика Kubernetes

Задача планировщика (Scheduler) в Kubernetes — запланировать pod, то есть назначить ему подходящий узел в кластере Kubernetes для последующего запуска.


Связывание объекта pod'а с объектом узла

Pod назначается узлу (или связывается с ним) тогда и только тогда, когда есть объект связывания (binding), у которого:

  • пространство имён равняется пространству имён pod'а,
  • название равняется названию pod'а,
  • тип цели равняется Node,
  • название цели равняется названию узла.

(Любители приключений могут посмотреть на GitHub gist от Kelsey Hightower под названием «Creating and Scheduling a Pod Manually» — пошаговое руководство по созданию объекта связывания вручную.)

Запуск pod'а



Схема 6. Управляющий цикл Kubelet

Задача Kubelet — запустить pod, что по сути означает запуск набора контейнеров pod'а. Запуск pod'а Kubelet'ом происходит в две фазы: инициализацию и основную стадию.

Как правило, набор контейнеров на фазе инициализации осуществляет подготовительные работы, такие как подготовку необходимой структуры директорий и файлов. А набор контейнеров на основной фазе выполняет уже «самые главные» задачи.

В обиходе же, хотя это и не совсем корректно, термин «pod» зачастую подразумевает набор контейнеров на основной фазе или же ещё более узкое значение «самого главного» контейнера основной фазы.


Схема 7.1. Запуск pod'а, фаза инициализации (init) и основная фаза (main)

Во время инициализации Kubelet последовательно запускает контейнеры в соответствии со спецификациями pod'а .Spec.InitContainers и в заданном в списке порядке. Для успешного запуска pod'а и с учётом политики рестарта, его init-контейнеры должны запуститься и успешно завершиться.

Во время основной фазы Kubelet одновременно запускает контейнеры в соответствии со спецификациями pod'а .Spec.Containers. Здесь уже для успешного запуска pod'а и с учётом политики рестарта, его основные (main) контейнеры должны быть запущены и либо успешно завершиться, либо работать неограниченное время.


Схема 7.2. Запуск pod'а, подробности этого процесса

В случае сбоя у контейнера, когда контейнер прекращает работу с отличным от нуля (0) кодом возврата (exit code), Kubelet может перезапустить контейнер в соответствии с политикой рестарта pod'а. Эта политика имеет одно из следующих значений: Always, OnFailure, Never.

У политики рестарта pod'а различная семантика для init-контейнеров и основных контейнеров: если запуск init-контейнеров обязан привести к завершению, то основные контейнеры могут и не завершаться.


Политика рестарта для init-контейнера

Init-контейнер будет перезапущен (т.е. повлечёт за собой запуск нового контейнера с такой же спецификацией) при завершении своей работы только при выполнении следующих условий:

  • exit-код контейнера сообщает об ошибке и
  • политика рестарта pod'а имеет значение Always или OnFailure.


Политика рестарта для основного (main) контейнера

Основной контейнер будет перезапущен (т.е. повлечёт за собой запуск нового контейнера с такой же спецификацией) при завершении своей работы только при выполнении следующих условий:

  • политика рестарта определена как Always или
  • политика рестарта определена как OnFailure и exit-код контейнера сообщает об ошибке.


Схема 8. Пример временной шкалы с красной точкой, символизирующей сбой у контейнера

На иллюстрации показана возможная временная шкала запуска pod'а с двумя спецификациями init-контейнеров и двумя спецификациями основных контейнеров. Также она показывает создание (в соответствии с политикой рестарта) нового контейнера Main Container 1.2 после проблемы с запуском Main Container 1.1.

Фазы pod'а



Схема 9. Взаимодействие Kubelet с объектом pod'а и исполняемой средой контейнера (container runtime)

Kubelet получает спецификации pod'а .Spec.InitContainers и .Spec.Containers, запускает указанный набор контейнеров и соответствующим образом обновляет значения pod'а .Status.InitContainerStatuses и .Status.ContainerStatuses.

Kubelet сворачивает .Status.InitContainerStatuses и .Status.ContainerStatuses pod'а в одно значение — .Status.Phase.

Фаза pod'а — это проекция состояния контейнеров из набора контейнеров, она зависит от:

  • состояний и exit-кодов init-контейнеров,
  • состояний и exit-кодов основных контейнеров.


Схема 10. Фазы pod'а

Ожидание (Pending)



Фаза Pending

Pod находится в фазе ожидания тогда и только тогда, когда:

  • ни один из init-контейнеров pod'а не находится в состоянии Terminated с ошибкой (Failure);
  • все основные контейнеры pod'а находятся в состоянии Waiting.

Работает (Running)



Фаза Running

Pod находится в фазе работы тогда и только тогда, когда:

  • все init-контейнеры pod'а находятся в состоянии Terminated с успехом (Success);
  • хотя бы один основной контейнер pod'а находится в состоянии Running;
  • ни один из основных контейнеров pod'а не находится в состоянии Terminated с ошибкой (Failure).

Успех (Success)



Фаза Success

Pod находится в фазе успеха тогда и только тогда, когда:

  • все init-контейнеры pod'а находятся в состоянии Terminated с успехом (Success);
  • все основные контейнеры pod'а находятся в состоянии Terminated с успехом (Success).

Отказ (Failure)



Фаза Failure

Pod находится в фазе отказа тогда и только тогда, когда:

  • все контейнеры pod'а находятся в состоянии Terminated;
  • хотя бы один из контейнеров pod'а находятся в состоянии Terminated с ошибкой (Failure).

Неизвестно (Unknown)


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

Сбор мусора для pod'ов



Схема 11. Управляющий цикл сборщика мусора для pod'ов (Pod Garbage Collector)

После того, как pod был запланирован и запущен, специальный контроллер в Kubernetes — Pod Garbage Collector Controller — отвечает за удаление объектов pod'ов из хранилища объектов Kubernetes Object Store.

Заключение


Pod — базовый строительный блок Kubernetes: pod определяется как представление запроса на запуск одного или более контейнеров на одном узле. После того, как pod создан, Kubernetes обрабатывает его в два этапа: сначала планировщик (Scheduler) планирует pod, а затем — Kubelet запускает его. На протяжении своего жизненного цикла pod проходит через разные фазы, сообщая о состоянии — или, точнее говоря, о состоянии своего набора контейнеров — пользователю и системе.

P.S. от переводчика


Читайте также в нашем блоге:

Комментарии (4)


  1. anonymous
    00.00.0000 00:00


    1. shurup
      13.11.2018 13:46
      +2

      Немного даже удивлён, что впервые об этом просят (после многих других статей про Поды :-)). Заменили везде в этом тексте на англоязычное название.


      1. alan008
        13.11.2018 14:10

        Спасибо большущее! :)


  1. zolti
    15.11.2018 20:44

    Не очень понятно про init стадию. Получается она нацелена на то, что бы запустить целевой контейнер, проверить что он запустится и завершить его. Т.е. провести успешно полный цикл жизни контейнера (или нескольких) и оповестить, что на каждом этапе (инициализация, запуск, работа, стоп), все прошло удачно? И после этого переходить в следующую — основную фазу?