Kubernetes theory
September 13, 2022

Pod

Pod - это базовая сущность кластера Kubernetes. Контейнеры с полезной нагрузкой в виде приложений находятся в подах кластера.

Приложения, также как и в Docker, упакованы в контейнеры. А контейнеры уже входят в состав пода. Иными словами под - это абстракция над контейнерами.

Кстати, pod с английского переводится как стручёк. А горошенки в этом стручке олицетворяют контейнеры.

Особенности подов:

1. Под - это минимальная объектная единица в кластере k8s. Kubernetes управляет не контейнерами напрямую, а подами.

2. Внутри одного пода могут располагаться несколько контейнеров с полезной нагрузкой. К примеру, nginx и postgresql. Но это абсолютно не продовое решение. Ведь если с подом что-то произойдёт, то погибнут сразу оба приложения. Также такое решение плохо масштабируется. Даже если сделать несколько одинаковых подов, то у каждого пода будет свой экземпляр базы данных и обратного прокси.
Поэтому такие сервисы лучше разносить по разным подам.

3. Под не может находиться вне какого-то пространства имён. Иными словами он всегда будет частью какого-то Namespace.

4. Под физически расположен на нодах кластера.

5. Поды, находящиеся на ноде кластера, совместно используют сетевой стек данной ноды.

6. У подов есть много разных состояний. Об этом поговорим ниже.

7. К подам могут монтироваться постоянные тома, для хранения данных, которые необходимо сохранить.

8. Кластер k8s управляет подами самостоятельно. Так он может перенести под с ноды на ноду без вмешательства со стороны человека.

9. Каждому поду присваивается свой уникальный ip адрес в сети кластера.

10. Поды предоставляют контейнерам доступ к сети и хранилищу.

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

12. Под - это не масштабируемый ресурс. Имеется ввиду, если мы создаём просто под, без управляющего им контроллера.

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

14. Для проверки того живы ли контейнеры внутри пода или нет используются специальные пробы (Liveness Probe и Readness Probe).

15. В случае пересоздания пода, вся информация в нём удаляется. Поэтому нет какого-то большого смысла подключаться к поду и что-то там устанавливать или править настройки.

16. Для управления настройками прилжений внутри контейнера в поде существует специальная абстракция - ConfigMap.

17. Если для работы пода нужна секретная информация, например, ключи доступа или пароли, то используется специальная сущность - Secret.

18. В современном мире поды вручную никто не создаёт. Для создания подов используются контроллеры. Например, Deployment, StatefulSet, DaemonSet.

19. Для горизонтального масштабирования подов используется ещё одна сущность - HPA.

20. У пода в обязательном порядке есть имя и спецификация контейнера с приложением внутри.

21. В манифесте любой сущности в кластере k8s обязательно есть версия его api (apiVersion), тип к которому относится сущность (kind), метаинформация о сущности (metadata) и сама спецификация (spec). Это обязательные параметры. При создании спецификации пода посмотрим на них внимательнее.

Из написанного выше становится ясно, что под - это базовая сущность, с которой работают множество других сущностей в кластере. Я здесь перечислил далеко не всё. Постепенно будем изучать их все.

Но что такое под в физическом смысле? Человек видит спецификацию на его создание, может посмотреть статус пода. Но что же такое сам под. В физическом смысле под - это запрос на создание и запуск контейнера на определённом узле (ноде) кластера k8s.

Под может находиться в одной из следующих фаз:

  • Pending (ожидание): API Server создал ресурс пода и сохранил его в etcd, но под ещё не был запланирован, а образы его контейнеров — не получены из реестра;
  • Running (функционирует): под был назначен узлу и все контейнеры созданы kubelet'ом;
  • Succeeded (успешно завершён): функционирование всех контейнеров пода успешно завершено и они не будут перезапускаться;
  • Failed (завершено с ошибкой): функционирование всех контейнеров пода прекращено и как минимум один из контейнеров завершился со сбоем;
  • Unknown (неизвестно): API Server не смог опросить статус пода, обычно из-за ошибки во взаимодействии с kubelet.

Здесь мы рассмотрели именно состояния пода, а не контейнера внутри пода. Про компоненты кластера такие как API Server, kubelet поговорим позднее.

Итак, создадим простенький под, посмотрим его состояние и его дескрайб.

Pod nginx

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: cam-nginx
  namespace: default
spec:
  containers:
  - name: nginx
    image: nginx:latest
    args:
    - sleep
    - "3600"
EOF

Данный под был установлен в ns=default.

Посмотрим информацию по этому поду.

kubectl get po cam-nginx -n default
NAME        READY   STATUS    RESTARTS   AGE
cam-nginx   1/1     Running   0          6m36s

Под работает в одном экземпляре (удивительно, правда?). Работает уже 6,5 минут и не было ни одного рестарта.

kubectl describe po cam-nginx -n default
Name:         cam-nginx
Namespace:    default
Priority:     0
Node:         cl1r12kvg8q3mf91ohla-usen/10.128.0.29
Start Time:   Tue, 13 Sep 2022 19:45:55 +0300
Labels:       <none>
Annotations:  cni.projectcalico.org/podIP: 10.96.128.15/32
Status:       Running
IP:           10.96.128.15
IPs:
  IP:  10.96.128.15
Containers:
  nginx:
    Container ID:  containerd://7ce394d7e09971befe6f13f07129d2f326c336a6e57ef6160ae2f48ee9f69591
    Image:         nginx:latest
    Image ID:      docker.io/library/nginx@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1
    Port:          <none>
    Host Port:     <none>
    Args:
      sleep
      3600
    State:          Running
      Started:      Tue, 13 Sep 2022 21:46:10 +0300
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 13 Sep 2022 20:46:08 +0300
      Finished:     Tue, 13 Sep 2022 21:46:08 +0300
    Ready:          True
    Restart Count:  2
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-c42rv (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-c42rv:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason   Age                 From     Message
  ----    ------   ----                ----     -------
  Normal  Pulling  24m (x3 over 144m)  kubelet  Pulling image "nginx:latest"
  Normal  Created  24m (x3 over 144m)  kubelet  Created container nginx
  Normal  Started  24m (x3 over 144m)  kubelet  Started container nginx
  Normal  Pulled   24m                 kubelet  Successfully pulled image "nginx:latest" in 1.245822227s

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

Пока выделим важные части, которые и так понятны:
Name:         cam-nginx // имя пода
Namespace:    default //ns
Node:         cl1r12kvg8q3mf91ohla-usen/10.128.0.29 //имя ноды на которой находится под и адрес ноды
Start Time:   Tue, 13 Sep 2022 19:45:55 +0300 // время старта пода
Status:       Running
IP:           10.96.128.15
IPs:
  IP:  10.96.128.15
Containers: // в этой секции информация о контейнере и имидже кот исполь
  nginx:
    Container ID:  containerd://7ce394d7e09971befe6f13f07129d2f326c336a6e57ef6160ae2f48ee9f69591
    Image:         nginx:latest
    Image ID:      docker.io/library/nginx@sha256:0b970013351304af46f322da1263516b188318682b2ab1091862497591189ff1
    Port:          <none>
    Host Port:     <none>
    Args:  // в этой секции отображаются переданные в контейнер аргументы
      sleep
      3600
    State:          Running // статус контейнера
      Started:      Tue, 13 Sep 2022 21:46:10 +0300

Подключимся к поду:

kubectl exec -n default --stdin --tty cam-nginx -- /bin/sh
nginx -v
nginx version: nginx/1.23.1

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Посмотрим логи пода и потребляемые ресурсы:

kubectl top -n default pod cam-nginx --containers 
kubectl logs -n default cam-nginx

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

Полезные ссылки:

Kubernetes: жизнь пода (Флант): https://habr.com/ru/company/flant/blog/415393/
Изучение подов и узлов: https://kubernetes.io/ru/docs/tutorials/kubernetes-basics/explore/explore-intro/
Так что же такое pod в Kubernetes: https://habr.com/ru/company/flant/blog/427819/
Про namaspace тут пишу кратенько: https://teletype.in/@cameda2/6tbWe-V5XxZ
Пример пода с образом ubuntu: https://teletype.in/@cameda2/0WYCLb3fX0a

Знакомство с Kubernetes. Pods: https://ealebed.github.io/posts/2018/знакомство-с-kubernetes-часть-3-pods/