0 added
0 removed
Original
2026-01-01
Modified
2026-02-19
1
<p><strong>Рассмотрим CNI, CRI, CSI через призму того, что именно делает Kubernetes</strong>(а еще точнее - kubelet), как именно он настраивает интерфейсы, какие параметры передаёт, что от кого ожидает и что может пойти не так.</p>
1
<p><strong>Рассмотрим CNI, CRI, CSI через призму того, что именно делает Kubernetes</strong>(а еще точнее - kubelet), как именно он настраивает интерфейсы, какие параметры передаёт, что от кого ожидает и что может пойти не так.</p>
2
<p>CRI - Container Runtime Interface</p>
2
<p>CRI - Container Runtime Interface</p>
3
<p>Смотрим<a>официальную документацию.</a></p>
3
<p>Смотрим<a>официальную документацию.</a></p>
4
<p>"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"</p>
4
<p>"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"</p>
5
<p>То есть, буквально можем зайти<a>сюда</a>и посмотреть какие gRPC вызовы используются kubelet для взаимодействия с CRI, чтобы управлять контейнерами. Когда kubelet запускается, при помощи аргумента --container-runtime-endpoint, настраивается адрес, по которому нужно общаться с CRI.</p>
5
<p>То есть, буквально можем зайти<a>сюда</a>и посмотреть какие gRPC вызовы используются kubelet для взаимодействия с CRI, чтобы управлять контейнерами. Когда kubelet запускается, при помощи аргумента --container-runtime-endpoint, настраивается адрес, по которому нужно общаться с CRI.</p>
6
<p>В процессе жизненного цикла работы каждого контейнера на выделенной ноде kubelet посредством CRI общается с container runtime (пример), чтобы запрашивать создание/удаление контейнеров на ноде.</p>
6
<p>В процессе жизненного цикла работы каждого контейнера на выделенной ноде kubelet посредством CRI общается с container runtime (пример), чтобы запрашивать создание/удаление контейнеров на ноде.</p>
7
<p><strong>Как посмотреть вызовы?</strong></p>
7
<p><strong>Как посмотреть вызовы?</strong></p>
8
<p>Установить crictl, прописать --runtime-endpoint</p>
8
<p>Установить crictl, прописать --runtime-endpoint</p>
9
<p>Пример</p>
9
<p>Пример</p>
10
<p>minikube start</p>
10
<p>minikube start</p>
11
<p>minikube ssh</p>
11
<p>minikube ssh</p>
12
<p>docker@minikube:~$ crictl -D pods</p>
12
<p>docker@minikube:~$ crictl -D pods</p>
13
<p>Флаг -D позволит посмотреть gRPC вызовы в деталях.</p>
13
<p>Флаг -D позволит посмотреть gRPC вызовы в деталях.</p>
14
<p>CNI - Container Network Interface</p>
14
<p>CNI - Container Network Interface</p>
15
<p>CNI - стандарт для настройки сети пода. Как работает CNI:</p>
15
<p>CNI - стандарт для настройки сети пода. Как работает CNI:</p>
16
<ol><li>Pod Scheduling</li>
16
<ol><li>Pod Scheduling</li>
17
<li>Kubelet получает из API server детали запускаемого пода и обращаеся в CRI для создания пода.</li>
17
<li>Kubelet получает из API server детали запускаемого пода и обращаеся в CRI для создания пода.</li>
18
<li>CRI</li>
18
<li>CRI</li>
19
<li>Kubelet обращается к CRI для создания пода. CRI runtime:</li>
19
<li>Kubelet обращается к CRI для создания пода. CRI runtime:</li>
20
</ol><ul><li>Создает сетевой namespace.</li>
20
</ol><ul><li>Создает сетевой namespace.</li>
21
<li>Создает pause контейнер.</li>
21
<li>Создает pause контейнер.</li>
22
</ul><ol><li>CNI plugin</li>
22
</ul><ol><li>CNI plugin</li>
23
<li>CRI вызывает CNI plugin (например, calico) для настройки сети пода через CLI.</li>
23
<li>CRI вызывает CNI plugin (например, calico) для настройки сети пода через CLI.</li>
24
</ol><p>Лучше всего понять на<a>простом примере.</a></p>
24
</ol><p>Лучше всего понять на<a>простом примере.</a></p>
25
<p>Т.е. бинарник CNI плагина (а в данном случае shell скрипт) вызывается с необходимыми переменными окружения (например, CNI_COMMAND=ADD), чтобы настроить сеть.</p>
25
<p>Т.е. бинарник CNI плагина (а в данном случае shell скрипт) вызывается с необходимыми переменными окружения (например, CNI_COMMAND=ADD), чтобы настроить сеть.</p>
26
<p>В каталоге /etc/cni/net.d/ хранится конфигурация плагина в формате json.</p>
26
<p>В каталоге /etc/cni/net.d/ хранится конфигурация плагина в формате json.</p>
27
<p>Например</p>
27
<p>Например</p>
28
<p>{</p>
28
<p>{</p>
29
<p>"cniVersion": "0.3.1",</p>
29
<p>"cniVersion": "0.3.1",</p>
30
<p>"name": "my-cni-demo",</p>
30
<p>"name": "my-cni-demo",</p>
31
<p>"type": "my-cni-demo",</p>
31
<p>"type": "my-cni-demo",</p>
32
<p>"podcidr": "10.240.0.0/24"</p>
32
<p>"podcidr": "10.240.0.0/24"</p>
33
<p>}</p>
33
<p>}</p>
34
<p>В каталоге /opt/cni/bin/ должен находится запускаемый файл, который будет вызываться для настройки сети пода, с именем из поля type вышеобозначенного json.</p>
34
<p>В каталоге /opt/cni/bin/ должен находится запускаемый файл, который будет вызываться для настройки сети пода, с именем из поля type вышеобозначенного json.</p>
35
<p><strong>Как это работает:</strong></p>
35
<p><strong>Как это работает:</strong></p>
36
<p>Когда kubelet вызывает RunPodSandbox, container runtime:</p>
36
<p>Когда kubelet вызывает RunPodSandbox, container runtime:</p>
37
<ol><li>Создаёт network namespace</li>
37
<ol><li>Создаёт network namespace</li>
38
<li>Вызывает бинарник CNI плагина (например, cilium, calico, bridge) с параметрами:</li>
38
<li>Вызывает бинарник CNI плагина (например, cilium, calico, bridge) с параметрами:</li>
39
<li>CNI_COMMAND=ADD \\</li>
39
<li>CNI_COMMAND=ADD \\</li>
40
</ol><p>CNI_CONTAINERID=<container_id> \\</p>
40
</ol><p>CNI_CONTAINERID=<container_id> \\</p>
41
<p>CNI_NETNS=/run/netns/<nsname> \\</p>
41
<p>CNI_NETNS=/run/netns/<nsname> \\</p>
42
<p>CNI_IFNAME=eth0 \\</p>
42
<p>CNI_IFNAME=eth0 \\</p>
43
<p>CNI_PATH=/opt/cni/bin \\</p>
43
<p>CNI_PATH=/opt/cni/bin \\</p>
44
<p>/opt/cni/bin/cilium < /etc/cni/net.d/10-cni.conf</p>
44
<p>/opt/cni/bin/cilium < /etc/cni/net.d/10-cni.conf</p>
45
<p>Поддерживаемые операции:</p>
45
<p>Поддерживаемые операции:</p>
46
<ul><li>ADD - создать интерфейс</li>
46
<ul><li>ADD - создать интерфейс</li>
47
<li>DEL - удалить</li>
47
<li>DEL - удалить</li>
48
<li>CHECK - проверить</li>
48
<li>CHECK - проверить</li>
49
<li>VERSION - вернуть версию</li>
49
<li>VERSION - вернуть версию</li>
50
</ul><p>Подробнее -<a>тут.</a></p>
50
</ul><p>Подробнее -<a>тут.</a></p>
51
<p>CSI - Container Storage Interface</p>
51
<p>CSI - Container Storage Interface</p>
52
<p><a>Документация.</a></p>
52
<p><a>Документация.</a></p>
53
<p>Ключевые компоненты:</p>
53
<p>Ключевые компоненты:</p>
54
<ol><li>CSI driver</li>
54
<ol><li>CSI driver</li>
55
</ol><ul><li>Controller Plugin: Управляет volumes через k8s API (create/delete, attach/detach, snapshots).</li>
55
</ol><ul><li>Controller Plugin: Управляет volumes через k8s API (create/delete, attach/detach, snapshots).</li>
56
<li>Node Plugin: Управляет mount/unmount всех volumes на нодах путем коммуникации с kubelet на ноде.</li>
56
<li>Node Plugin: Управляет mount/unmount всех volumes на нодах путем коммуникации с kubelet на ноде.</li>
57
<li>Identity Service: Предоставляет метаданные драйвера (name, version, capabilities) в k8s.</li>
57
<li>Identity Service: Предоставляет метаданные драйвера (name, version, capabilities) в k8s.</li>
58
</ul><ol><li>Sidecar containers</li>
58
</ul><ol><li>Sidecar containers</li>
59
</ol><ul><li>External Provisioner: Отслеживает PVC и выполняет CreateVolume/DeleteVolume через CSI driver.</li>
59
</ol><ul><li>External Provisioner: Отслеживает PVC и выполняет CreateVolume/DeleteVolume через CSI driver.</li>
60
<li>External Attacher: Управляет VolumeAttachment чтобы управлять привязкой volume к ноде.</li>
60
<li>External Attacher: Управляет VolumeAttachment чтобы управлять привязкой volume к ноде.</li>
61
</ul><p>Общий процесс:</p>
61
</ul><p>Общий процесс:</p>
62
<ol><li>Provisioning</li>
62
<ol><li>Provisioning</li>
63
</ol><ul><li>Пользователь создает PVC, указывая StorageClass.</li>
63
</ol><ul><li>Пользователь создает PVC, указывая StorageClass.</li>
64
<li>External Provisioner (sidecar) видит PVC и вызывает CreateVolume в CSI driver.</li>
64
<li>External Provisioner (sidecar) видит PVC и вызывает CreateVolume в CSI driver.</li>
65
<li>CSI driver создает настоящий volume (AWS EBS, NFS, etc) регистрирует PV в k8s.</li>
65
<li>CSI driver создает настоящий volume (AWS EBS, NFS, etc) регистрирует PV в k8s.</li>
66
</ul><ol><li>Attachment</li>
66
</ul><ol><li>Attachment</li>
67
</ol><ul><li>Когда выполняется scheduling пода с новым PVC, external Attacher вызывает ControllerPublishVolume в CSI driver, чтобы привязать volume к ноде, на которую шедулится. под.</li>
67
</ol><ul><li>Когда выполняется scheduling пода с новым PVC, external Attacher вызывает ControllerPublishVolume в CSI driver, чтобы привязать volume к ноде, на которую шедулится. под.</li>
68
<li>Volume становится доступным ноде.</li>
68
<li>Volume становится доступным ноде.</li>
69
</ul><ol><li>Mounting</li>
69
</ul><ol><li>Mounting</li>
70
</ol><ul><li>kubelet на ноде вызывает Node Plugin через unix socket (например, /var/lib/kubelet/plugins/[driver-name]/csi.sock).</li>
70
</ol><ul><li>kubelet на ноде вызывает Node Plugin через unix socket (например, /var/lib/kubelet/plugins/[driver-name]/csi.sock).</li>
71
<li>Node Plugin выполняет монтирование volume в под.</li>
71
<li>Node Plugin выполняет монтирование volume в под.</li>
72
</ul><p>Конечно же CSI Node Plugin должен быть на каждом узле (обычно как DaemonSet)</p>
72
</ul><p>Конечно же CSI Node Plugin должен быть на каждом узле (обычно как DaemonSet)</p>
73
<p>Ошибки, которые случались у каждого:</p>
73
<p>Ошибки, которые случались у каждого:</p>
74
<p>В завершение: жизненный цикл пода с точки зрения этих интерфейсов</p>
74
<p>В завершение: жизненный цикл пода с точки зрения этих интерфейсов</p>
75
<p>kubectl apply Pod + PVC →</p>
75
<p>kubectl apply Pod + PVC →</p>
76
<p>→ kubelet вызывает RunPodSandbox (CRI) →</p>
76
<p>→ kubelet вызывает RunPodSandbox (CRI) →</p>
77
<p>→ CRI вызывает CNI для сетевого интерфейса →</p>
77
<p>→ CRI вызывает CNI для сетевого интерфейса →</p>
78
<p>→ kubelet вызывает CSI NodePublishVolume →</p>
78
<p>→ kubelet вызывает CSI NodePublishVolume →</p>
79
<p>→ kubelet вызывает CreateContainer →</p>
79
<p>→ kubelet вызывает CreateContainer →</p>
80
<p>→ kubelet запускает контейнер →</p>
80
<p>→ kubelet запускает контейнер →</p>
81
<p>→ kubelet следит за probe, healthcheck →</p>
81
<p>→ kubelet следит за probe, healthcheck →</p>
82
<p>→ kubelet удаляет pod →</p>
82
<p>→ kubelet удаляет pod →</p>
83
<p>→ CSI и CNI вызываются для tear-down →</p>
83
<p>→ CSI и CNI вызываются для tear-down →</p>
84
<p>→ Done.</p>
84
<p>→ Done.</p>
85
<p>Освоить основы работы с Kubernetes: c системой автоматизации развертывания, масштабирования и управления приложениями в контейнерах - на курсе<a>"Kubernetes База".</a></p>
85
<p>Освоить основы работы с Kubernetes: c системой автоматизации развертывания, масштабирования и управления приложениями в контейнерах - на курсе<a>"Kubernetes База".</a></p>