Блог Слёрм

CRI, CSI, CNI

Рассмотрим CNI, CRI, CSI через призму того, что именно делает Kubernetes (а еще точнее — kubelet), как именно он настраивает интерфейсы, какие параметры передаёт, что от кого ожидает и что может пойти не так.

CRI — Container Runtime Interface

Смотрим официальную документацию.

«CRI is a plugin interface which enables kubelet to use a wide variety of container runtimes, without the need to recompile. CRI consists of a protocol buffers and gRPC API»

То есть, буквально можем зайти сюда и посмотреть какие gRPC вызовы используются kubelet для взаимодействия с CRI, чтобы управлять контейнерами. Когда kubelet запускается, при помощи аргумента --container-runtime-endpoint, настраивается адрес, по которому нужно общаться с CRI.

В процессе жизненного цикла работы каждого контейнера на выделенной ноде kubelet посредством CRI общается с container runtime (пример), чтобы запрашивать создание/удаление контейнеров на ноде.

Как посмотреть вызовы?

Установить crictl, прописать --runtime-endpoint

Пример

minikube start

minikube ssh

docker@minikube:~$ crictl -D pods

Флаг -D позволит посмотреть gRPC вызовы в деталях.

CNI — Container Network Interface

CNI — стандарт для настройки сети пода. Как работает CNI:

  1. Pod Scheduling
  2. Kubelet получает из API server детали запускаемого пода и обращаеся в CRI для создания пода.
  3. CRI
  4. Kubelet обращается к CRI для создания пода. CRI runtime:

  • Создает сетевой namespace.
  • Создает pause контейнер.

  1. CNI plugin
  2. CRI вызывает CNI plugin (например, calico) для настройки сети пода через CLI.

Лучше всего понять на простом примере.

Т.е. бинарник CNI плагина (а в данном случае shell скрипт) вызывается с необходимыми переменными окружения (например, CNI_COMMAND=ADD), чтобы настроить сеть.

В каталоге /etc/cni/net.d/ хранится конфигурация плагина в формате json.

Например

{

"cniVersion": "0.3.1",

"name": "my-cni-demo",

"type": "my-cni-demo",

"podcidr": "10.240.0.0/24"

}

В каталоге /opt/cni/bin/ должен находится запускаемый файл, который будет вызываться для настройки сети пода, с именем из поля type вышеобозначенного json.

Как это работает:

Когда kubelet вызывает RunPodSandbox, container runtime:

  1. Создаёт network namespace
  2. Вызывает бинарник CNI плагина (например, cilium, calico, bridge) с параметрами:
  3. CNI_COMMAND=ADD \\

CNI_CONTAINERID=<container_id> \\

CNI_NETNS=/run/netns/<nsname> \\

CNI_IFNAME=eth0 \\

CNI_PATH=/opt/cni/bin \\

/opt/cni/bin/cilium < /etc/cni/net.d/10-cni.conf

Поддерживаемые операции:

  • ADD — создать интерфейс
  • DEL — удалить
  • CHECK — проверить
  • VERSION — вернуть версию

Подробнее — тут.

CSI — Container Storage Interface

Документация.

Ключевые компоненты:

  1. CSI driver

  • Controller Plugin: Управляет volumes через k8s API (create/delete, attach/detach, snapshots).
  • Node Plugin: Управляет mount/unmount всех volumes на нодах путем коммуникации с kubelet на ноде.
  • Identity Service: Предоставляет метаданные драйвера (name, version, capabilities) в k8s.

  1. Sidecar containers

  • External Provisioner: Отслеживает PVC и выполняет CreateVolume/DeleteVolume через CSI driver.
  • External Attacher: Управляет VolumeAttachment чтобы управлять привязкой volume к ноде.

Общий процесс:

  1. Provisioning

  • Пользователь создает PVC, указывая StorageClass.
  • External Provisioner (sidecar) видит PVC и вызывает CreateVolume в CSI driver.
  • CSI driver создает настоящий volume (AWS EBS, NFS, etc) регистрирует PV в k8s.

  1. Attachment

  • Когда выполняется scheduling пода с новым PVC, external Attacher вызывает ControllerPublishVolume в CSI driver, чтобы привязать volume к ноде, на которую шедулится. под.
  • Volume становится доступным ноде.

  1. Mounting

  • kubelet на ноде вызывает Node Plugin через unix socket (например, /var/lib/kubelet/plugins/[driver-name]/csi.sock).
  • Node Plugin выполняет монтирование volume в под.

Конечно же CSI Node Plugin должен быть на каждом узле (обычно как DaemonSet)

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

kubectl apply Pod + PVC →

→ kubelet вызывает RunPodSandbox (CRI) →

→ CRI вызывает CNI для сетевого интерфейса →

→ kubelet вызывает CSI NodePublishVolume →

→ kubelet вызывает CreateContainer →

→ kubelet запускает контейнер →

→ kubelet следит за probe, healthcheck →

→ kubelet удаляет pod →

→ CSI и CNI вызываются для tear-down →

→ Done.

Освоить основы работы с Kubernetes: c системой автоматизации развертывания, масштабирования и управления приложениями в контейнерах — на курсе «Kubernetes База».
Kubernetes