HTML Diff
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=&lt;container_id&gt; \\</p>
40 </ol><p>CNI_CONTAINERID=&lt;container_id&gt; \\</p>
41 <p>CNI_NETNS=/run/netns/&lt;nsname&gt; \\</p>
41 <p>CNI_NETNS=/run/netns/&lt;nsname&gt; \\</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 &lt; /etc/cni/net.d/10-cni.conf</p>
44 <p>/opt/cni/bin/cilium &lt; /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>