Рассмотрим CNI, CRI, CSI через призму того, что именно делает Kubernetes (а еще точнее — kubelet), как именно он настраивает интерфейсы, какие параметры передаёт, что от кого ожидает и что может пойти не так.
«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) с параметрами:
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 База».