Рассмотрим 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:
Лучше всего понять на простом примере.
Т.е. бинарник 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:
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
Поддерживаемые операции:
Подробнее — тут.
CSI — Container Storage Interface
Документация.
Ключевые компоненты:
Общий процесс:
Конечно же CSI Node Plugin должен быть на каждом узле (обычно как DaemonSet)
Ошибки, которые случались у каждого:
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:
- Pod Scheduling
- Kubelet получает из API server детали запускаемого пода и обращаеся в CRI для создания пода.
- CRI
- Kubelet обращается к CRI для создания пода. CRI runtime:
- Создает сетевой namespace.
- Создает pause контейнер.
- CNI plugin
- 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:
- Создаёт network namespace
- Вызывает бинарник CNI плагина (например, cilium, calico, bridge) с параметрами:
- 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
Документация.
Ключевые компоненты:
- CSI driver
- Controller Plugin: Управляет volumes через k8s API (create/delete, attach/detach, snapshots).
- Node Plugin: Управляет mount/unmount всех volumes на нодах путем коммуникации с kubelet на ноде.
- Identity Service: Предоставляет метаданные драйвера (name, version, capabilities) в k8s.
- Sidecar containers
- External Provisioner: Отслеживает PVC и выполняет CreateVolume/DeleteVolume через CSI driver.
- External Attacher: Управляет VolumeAttachment чтобы управлять привязкой volume к ноде.
Общий процесс:
- Provisioning
- Пользователь создает PVC, указывая StorageClass.
- External Provisioner (sidecar) видит PVC и вызывает CreateVolume в CSI driver.
- CSI driver создает настоящий volume (AWS EBS, NFS, etc) регистрирует PV в k8s.
- Attachment
- Когда выполняется scheduling пода с новым PVC, external Attacher вызывает ControllerPublishVolume в CSI driver, чтобы привязать volume к ноде, на которую шедулится. под.
- Volume становится доступным ноде.
- 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 База».
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 База».