Skip to content

pod

Что такое pod

POD - объект k8s, через которорый происходит развертывание контейнеров и дальнейшее управление ими. Под является основным строительным блоком в кластере Kubernetes.

В каждый развернутый под может быть упаковано от одного до нескольких контейнеров, которые должны разделять одно окружение (сеть, хранилище). Контейнеры зыпущенные в границах одного пода работают вместе на одной ноде, что облегчает обмен данными между контейнерами: общая сеть и ресурсы хранения.

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

По умолчанию, контейнеры в рамках одного пода изолированны от котейнеров, развернутых в других подах, потому что pod и контейнеры внутри него имеют один и тот же ip-адрес. Для взаимодействия подов необходимо дополнительно настраивать сеть внутри кластера с помощью объекта service.

Файловые системы контейнеров разные, но их можно шарить между контейнерами внутри пода.

Поды, развернутые с помощью Deployment и ReplicaSet очень просто реплицируются. Их жизненным циклом легко управлять.

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

Стоит отметить, что в kubernetes контейнеры бывают двух типов: init и runtime.

  • Runtime контейнеры - это привычные контенеры, из запуск внутри пода происходит одновременно.

  • Init контейнеры - особый тип контейнеров, запуск которых происходит в первую очередь. Только после их успешного запуска происходит старт основных контейнеров пода. Применяются для выполнения инициализационных задач: производят первоначальную настройку среду, устанавливают зависимости, проверяют доступность БД, производят загрузку конфигураций для основного приложения.

pod
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers: # Основной контейнер приложения
  - name: main-container
    image: my-app-image

  initContainers:  # Init контейнер для предварительной настройки
  - name: init-container
    image: init-image

Процесс создания пода

Процесс создания пода в Kubernetes включает несколько этапов:

  1. Запрос на создание пода: Пользователь отправляет запрос на создание пода через утилиту командной строки kubectl или API Kubernetes.
    • Аутентификация и авторизация: Запрос проходит процесс аутентификации и авторизации на сервере API Kubernetes. Это позволяет убедиться, что пользователь имеет права на выполнение операции создания пода.
    • Валидация запроса: Перед созданием пода сервер API Kubernetes проверяет запрос на наличие всех необходимых параметров и соответствие политикам безопасности и конфигурации кластера.
  2. Обновление данных в etcd: После успешной валидации данные о создаваемом поде сохраняются в распределенной базе данных etcd, которая является хранилищем состояния кластера Kubernetes.
  3. Планировщик обнаруживает, что есть неназначенный под, мониторя сервер API (kube-apiserver)
    • Выбор узла для запуска пода: Планировщик Kubernetes определяет, на каком узле в кластере следует разместить создаваемый под, учитывая различные факторы, такие как доступность ресурсов и аффинитеты/антиаффинитеты.
  4. Назначение пода узлу: Информация о назначенном узле обновляется в etcd.
  5. Запуск контейнеров: Kubelet на назначенном узле получает информацию о созданном поде из сервера API Kubernetes. После этого Kubelet запускает контейнеры, определенные в спецификации пода, используя контейнерный движок (например, Docker).
  6. Обновление состояния в API сервере: После успешного запуска контейнеров Kubelet обновляет состояние пода в сервере API Kubernetes, сообщая о том, что под успешно создан и запущен.
  7. Обновление данных в etcd: Сервер API Kubernetes обновляет данные о созданном поде в etcd для отражения его текущего состояния в кластере.

Сеть внутри пода.

Все контейнеры имеют один ip-адрес пода, и взаимодействуют друг с другом через localhost. Соответственно, рабочие порты у контейнеров должны быть разными.

Для проброса портов наружу пода применяются: services и port-forward.

Файловая система пода

Внутри пода можно создавать общие тома и папки.

Тома могут быть временными (очищаются при перезапуске пода) и постоянными (остаются даже при удалении пода)

Подробно про volumes

Управление ресурсами пода

Поскольку ресурсы кластера k8s в целом, и отдельных нод в частности - вещи ограниченные, следует их грамотно распределять между разворачиваемыми подами.

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

Запросы ресурсов (resources requests)

Ресурсы, которые требуются контейнеру для запуска. В соответствии с этими данными kube-scheduler будет подбирать подходящую ноду для пода.

resources requests
spec:
  containers:
  - name: my-container
    image: my-image
    resources:
      requests: # запрашиваемые ресурсы
        memory: "500Mi" # 500 Мегабайт памяти
        cpu: "100m" # 100 Миликоров CPU

Лимиты на ресурсы (resources limits)

Максимальн возможные ресурсы, которые могут быть выделенны для контейнера. Если под будет пытаться использовать больше памяти, он будет принудительно остановлен и запущен заново.

resources limits
spec:
  containers:
  - name: my-container
    image: my-image
    resources:
      limits: # ограничение ресурсов
        memory: "1000Mi" # 1000 Мегабайт памяти
        cpu: "200m" # 200 Миликоров CPU

Отрицательный баланс ресурсов кластера

Что будет, если суммарные допустимые для всех подов лимиты, превышают ресурсы кластера? Кластер будет стабильно работать, надеясь на то, что поды не будут выбирать максимально возможное для них количество ресурсов. Если ресурсы кластера начнут исчерпываться, k8s будет более агресивно гасить прожорливые поды, которые сильнее всего вышли за свои запросы

За состоянием подов модно следить автоматически, для этого существуют различные проверки работоспособности контейнеров.

Проверки работоспособности контейнеров.

Контейнер, по своей природе - штука ненадежная: процесс внутри контейнера может зависнуть и перестать отвечать на запросы.

Устройство k8s позволяет таким образом сконфигурировать поды, что они самостоятельно будут следить за работоспособностью контейнеров. Для этого существуют различные типы проверок для контейнеров.

livenessProbe

Проверка работоспособности (livenessProbe) - инструкция, которая с определенной периодичностью опрашивает контейнер, если последний не онвечает - он принудительно перезагружается.

livenessProbe httpGet
# Пример проверки контейнера с http-сервером
livenessProbe:
  httpGet: # Метод проверки httpGet-запрос
    path: /healthz # Ресурс для проверки, обычно специально создается
    port: 8080
  initialDelaySeconds: 3 # Время, отведенное контейнеру на инициализацию
  periodSeconds: 3 # Периодичность опроса контейнера

# Данная проверка делает http-запрос к специально созданному URI /healthz и порту 8080
# Если приложение в контейнере отвечает http-кодом вида 2хх или 3хх - приложение считается работоспособным
# Если возвращается любой другой ответ - контейнер перезапускается.
livenessProbe tcpSocket
# Пример проверки контейнера без http-сервера
livenessProbe:
  tcpSocket: # Метод проверки запрос на tcp-порт
    port: 8888
  initialDelaySeconds: 3 # Время, отведенное контейнеру на инициализацию
  periodSeconds: 3 # Периодичность опроса контейнера

# Если TCP-соединение с заданным портом будет успешно установлено, контейнер жив.

readinessProbe

Проверка готовности контейнера (readinessProbe) - инструкция, которая проверяет готов ли контейнер обрабатывать запросы. Приложение в контейнере считается готовым, если оно проходит проверку. Приложение начинает получать трафик только после успешной проверки. Можно задавать различные методы проверки: httpGet, tcpSocket, exec.

readinessProbe
# Пример проверки готовности контейнера методом exec
# В контейнере происходит выполнение конанды, если команда возвращает 0-й код (успешное выполнение) - значит контейнер прошел проверку
readinessProbe:
  exec: # Метод проверки 
    command: # Команды для выполнения
    - cat
    - /tmp/healthy
  initialDelaySeconds: 3 # Время, отведенное контейнеру на инициализацию
  periodSeconds: 3 # Периодичность опроса контейнера

startupProbe

startupProbe - это тип проверки, введенный в Kubernetes начиная с версии 1.16. Он предназначен для определения времени, необходимого для запуска приложения в контейнере. Startup Probe позволяет отложить проверки готовности (Readiness Probe) и жизнеспособности (Liveness Probe) до тех пор, пока не будет завершено начальное формирование приложения.

startupProbe
spec:
  containers:
  - name: mycontainer
    image: myimage
    readinessProbe:
      httpGet:
        path: /readiness
        port: 8080
      initialDelaySeconds: 10
    startupProbe:
      httpGet:
        path: /startup
        port: 8080
      failureThreshold: 30
# startupProbe проверяет запуск приложения после 10 секунд ожидания (задержка до первой проверки), и если проверка не проходит,
# она будет повторяться с интервалом в 1 секунду (определяется параметром periodSeconds).
# Если startupProbe проходит в течение 30 последовательных раз (определяется параметром failureThreshold), то он считается успешным,
# и затем начинает действовать readinessProbe.

Команды для работы с подами:

pod
# Самый простой способ создать под, через команду create
kubectl run pod my-pod-name --image=pod-image-name

# Создание пода через применение файла манифеста
kubectl apply -f manirests/my-pods.yaml

# Получение списка запущенных подов в текущем namespace
kubectl get pods

# Получение списка запущенных подов во всех namespace
kubectl get pods --all-namespaces 

# Получение подробной информации о запущенных подах
kubectl get pods -o wide

# Получение подробной информации о поде в формате yaml
kubectl get pod my-pod-name -o yaml

# Получение более подробной информации о поде
kubectl describe pod my-pod-name

# Получение логов от последнего запущенного пода
kubectl logs my-pod-name
# Получение логов от конкретного контейнера в поде
kubectl logs my-pod-name -c my-container name
# Получение логов в реальном времени
kubectl logs -f my-pod-name -c my-container-name
# Получение логов с метками времени
kubectl logs --timestamps my-pod-name
# Получение логов с предыдущего пода, если был перезапуск
kubectl logs --previous POD_NAME

# Посмотреть сколько ресурсов использует под 
kubectl top pod 

# Удалить все незапущенные поды
kubectl delete pods --field-selector=status.phase!='Running'

Статусы подов в Kubernetes

get pods
# Получение списка запущенных подов в текущем namespace
kubectl get pods
  • Running (запущен). Под работает и находится в нормальном состоянии.
  • Pending (ожидание). Под создан, но ему еще не были назначены все ресурсы или не выполнены другие условия для его запуска.
  • Succeeded (успешно завершен). Все контейнеры в поде успешно завершили свою работу и вышли из состояния выполнения.
  • Failed (ошибка). Один или несколько контейнеров в поде завершили работу с ошибкой.
  • Unknown (неизвестно). Состояние пода неизвестно из-за проблем связи между Kubelet и сервером API.
  • CrashLoopBackOff (циклический перезапуск из-за ошибки). Указывает на то, что контейнер в поде постоянно завершается с ошибкой и затем снова пытается перезапуститься, что приводит к циклическому поведению. Это может быть вызвано различными проблемами, такими как ошибка конфигурации, недоступность требуемых ресурсов, ошибки в самом приложении и другие.

    Чтобы исправить ситуацию с CrashLoopBackOff, вам следует выполнить следующие шаги:

    1. Просмотр логов контейнера: Используйте команду kubectl logs <имя_пода> для просмотра логов контейнера, чтобы определить причину сбоев. Это поможет вам понять, что именно вызывает ошибку.
    2. Проверка ресурсов: Убедитесь, что поду достаточно ресурсов (например, CPU, памяти, диск) для нормальной работы. Если не хватает ресурсов, это может привести к сбоям.
    3. Проверка конфигурации: Проверьте конфигурацию вашего пода и контейнера на предмет ошибок. Убедитесь, что все параметры правильно заданы и соответствуют требованиям вашего приложения.
    4. Обновление образа контейнера: Если проблема вызвана ошибкой в образе контейнера, попробуйте обновить его до последней версии или исправить проблему в образе.
    5. Использование Liveness и Readiness проб: Рассмотрите возможность настройки проверок живучести (Liveness Probe) и готовности (Readiness Probe) в вашем поде. Это поможет Kubernetes определить, когда перезапускать под в случае его некорректной работы.
    6. Мониторинг и автоматизация: Настройте мониторинг состояния ваших подов и используйте автоматические средства для быстрого обнаружения и восстановления от сбоев.
  • ContainerCreating (создание контейнера). Kubelet начал процесс создания контейнера в поде, но он еще не был успешно создан.

  • Terminating (завершение работы). Под находится в процессе завершения работы и очистки.
  • ErrImagePull. Указывает на проблемы при попытке загрузки образа контейнера из реестра образов (Docker Hub, Google Container Registry, и т. д.). Это может быть вызвано различными причинами, включая:
    • Недоступность реестра образов: Реестр образов может быть временно недоступен из-за технических проблем или сбоев в сети.
    • Неправильное имя образа: Возможно, указано неправильное имя образа или неправильная версия образа, которая не существует в реестре.
    • Неправильные учетные данные: Если образ находится в приватном реестре, возможно, учетные данные для доступа к нему не были предоставлены или предоставлены неправильно.
    • Проблемы с авторизацией: Если для доступа к реестру образов требуется авторизация, могут возникнуть проблемы с аутентификацией.
    • Проблемы с сетью: Возможны проблемы с сетью, которые мешают связаться с реестром образов для загрузки необходимого образа.