Привет, я Вася из Fastfox. Если Pod внезапно застрял в ContainerCreating, а события показывают CNI ADD failed или failed to create pod sandbox, почти всегда проблема в цепочке «kubelet → CRI (containerd/CRI-O) → CNI-плагин → iptables/eBPF → маршрутизация». Ниже — практичная инструкция, как быстро сузить круг причин и собрать артефакты для себя или для поддержки.
Что именно ломается: kubelet sandbox network и почему Pod даже не запускается
Перед запуском контейнеров kubelet создаёт «песочницу» Pod (sandbox): отдельный сетевой namespace, куда затем помещаются контейнеры Pod. На этом шаге kubelet вызывает runtime (обычно containerd), а runtime выполняет CNI-команды (обычно ADD) на узле.
Если CNI не смог создать veth-пару, выделить IP из пула (IPAM), прописать маршруты, настроить iptables или eBPF, kubelet получает ошибку «kubelet sandbox network», и Pod остаётся без сети — а значит не стартует вовсе.
Важно: в большинстве случаев это не проблема приложения. Даже «пустой» Pod с pause-контейнером не поднимется, если CNI не смог выполнить
ADD.
Как читать сообщения: CNI ADD failed vs failed to create pod sandbox
Обе ошибки часто идут рядом, но смысл чуть разный:
failed to create pod sandbox— общий итог: runtime не смог создать sandbox. Истинная причина обычно во «вложенной» ошибке ниже.CNI ADD failed— конкретика: команда CNIADDзавершилась ошибкой (IPAM, iptables/eBPF, недоступен сокет агента, неверная конфигурация).
Практическое правило: в событиях Pod читайте ошибку целиком, а затем подтверждайте её в логах kubelet и runtime — там чаще всего есть точное имя плагина и текст отказа.

Быстрый чек‑лист: 10 минут до понятного диагноза
1) Смотрим события Pod: там часто уже всё написано
kubectl -n NAMESPACE describe pod PODNAME
Ищите строки вида:
Warning FailedCreatePodSandBoxfailed to set up sandbox containercni plugin not initializedfailed to allocate iptimeout while waiting for network to be ready
2) Проверяем, на каком узле проблема (часто ломается один node)
kubectl -n NAMESPACE get pod PODNAME -o wide
Дальше работаем на конкретной ноде: там будут и CNI-конфиги, и бинарники, и логи kubelet/runtime.
3) Логи kubelet: главный источник kubelet sandbox network
На проблемном узле:
journalctl -u kubelet -b --no-pager | tail -n 200
Если нужно «поймать» конкретный Pod — фильтруйте по имени Pod или UID (его видно в describe).
4) Логи containerd/CRI-O: что именно вернул CNI
journalctl -u containerd -b --no-pager | tail -n 200
Для CRI-O:
journalctl -u crio -b --no-pager | tail -n 200
5) Проверяем CNI-конфиги и бинарники на узле
Типовые пути:
/etc/cni/net.d/— конфиги CNI (conflist/conf)/opt/cni/bin/— бинарники плагинов
ls -la /etc/cni/net.d
ls -la /opt/cni/bin
Частая причина ошибок уровня kubernetes network plugin error: kubelet пытается вызвать плагин, а бинарник отсутствует или конфиг пустой/битый.
6) Проверяем, что CNI вообще «поднялся» в кластере
kubectl -n kube-system get pods -o wide
Дальше — по вашей реализации:
Calico:
calico-node, иногдаcalico-kube-controllersCilium:
cilium,cilium-operatorFlannel:
kube-flannel-ds
7) Собираем cni logs правильно: не только kubelet
Под «cni logs» обычно понимают сразу несколько источников:
kubelet (события и journal)
containerd/CRI-O (journal)
логи DaemonSet плагина в
kube-system
Примеры команд (лейблы зависят от манифестов):
kubectl -n kube-system logs -l k8s-app=calico-node --tail=200
kubectl -n kube-system logs -l k8s-app=cilium --tail=200
kubectl -n kube-system logs -l app=flannel --tail=200
Если не уверены в лейблах — сначала посмотрите:
kubectl -n kube-system get pods --show-labels
Типовые причины и быстрые проверки (Calico/Cilium/Flannel)
Сценарий A: «plugin not initialized» или пустой /etc/cni/net.d
Симптомы: kubelet пишет, что сеть не инициализирована; Pod’ы не стартуют сразу после установки кластера или после «чистки» диска на ноде.
Проверки:
ls -la /etc/cni/net.d
ls -la /opt/cni/bin
Что делать по смыслу:
убедиться, что манифест CNI применён и DaemonSet действительно раскатывается на все узлы;
проверить tolerations/taints: CNI должен запускаться и на control-plane, если на нём планируются Pod’ы;
если конфиги генерируются агентом — проверить его логи и права на запись в
/etc/cni/net.d.
Сценарий B: IPAM не выдаёт адреса (ошибки вида «failed to allocate ip»)
Это частая основа для CNI ADD failed. Причины: закончился пул, пересечение PodCIDR, «залипшие» записи после аварийного ребута, конфликт адресов между узлами.
Практический минимум:
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
Сравните PodCIDR с настройками вашего CNI и контроллера (kube-controller-manager), который назначает PodCIDR.
Для Calico дополнительно полезно проверить состояние IP-пулов и IPAM (конкретные команды зависят от способа установки и доступности утилит). Базовая стратегия одна: убедиться, что пул не исчерпан и не конфликтует с инфраструктурными подсетями.
Сценарий C: iptables/conntrack сломаны или узел в «грязном» состоянии
Если плагин использует iptables (Calico в iptables-режиме, Flannel, часть конфигураций kube-proxy), ошибки могут выглядеть как kubernetes network plugin error с упоминанием chain/rule или проблем с lock.
Быстрые проверки на узле:
iptables -S | head
iptables -t nat -S | head
conntrack -S 2>/dev/null | head
Если conntrack не установлен — это тоже сигнал: на минимальных образах узлов не хватает инструментов, и диагностика превращается в гадание.
Если у вас Kubernetes завязан на eBPF (например, Cilium), пригодится отдельная практика диагностики BPF-программ и связанного окружения: диагностика eBPF через bcc и bpftrace.
Сценарий D: Cilium (eBPF) — агент не готов или недоступен сокет
Для Cilium характерны ошибки, где kubelet/runtime жалуется на таймауты, недоступность агента, невозможность применить BPF-программы, проблемы с монтированием BPF FS или несовместимость ядра.
Проверки:
kubectl -n kube-system get pods -l k8s-app=cilium -o wide
kubectl -n kube-system logs -l k8s-app=cilium --tail=200
Дальше по смыслу ищем: перезапуски, невозможность поднять datapath, конфликты режима kube-proxy replacement и особенности ядра (особенно после обновлений).
Сценарий E: Flannel — проблемы с VXLAN/UDP, маршрутизацией или MTU
Когда VXLAN/UDP режется фаерволом или есть MTU-проблемы, Pod может создаваться, но сеть будет «фантомной». Иногда и sandbox не поднимается, если Flannel не смог корректно настроить интерфейсы/маршруты.
Проверки на узле:
ip link show | head -n 50
ip route show | head -n 50
И обязательно смотрим логи flannel DaemonSet.

Нюансы: почему ошибка появляется только на одном узле
В кластере из десятков нод часто ломается не «весь CNI», а конкретная нода. Типовые причины:
диск забит, и CNI не может писать состояние/кэши;
после обновления ядра изменились модули/параметры, и CNI (особенно eBPF) стал несовместим;
локальный фаервол или правила на уровне провайдера отличаются от остальных;
конфликт iptables режимов (nft/legacy) или «грязные» правила после ручных экспериментов;
рассинхрон времени и проблемы с доступом к control-plane маскируются под сетевые сбои.
Если подозреваете влияние локального фаервола и таблиц, держите под рукой разбор про практику работы с iptables и nftables: как читать и отлаживать правила iptables/nftables.
Как собрать минимальный «пакет доказательств» для разборов
Чтобы не пересылать «у нас не работает», соберите набор, который обычно закрывает 80% вопросов:
Вывод
kubectl -n NAMESPACE describe pod PODNAME(секция Events целиком).Вывод
kubectl -n kube-system get pods -o wide.Хвост kubelet:
journalctl -u kubelet -b --no-pager | tail -n 300
Хвост containerd/CRI-O:
journalctl -u containerd -b --no-pager | tail -n 300
Содержимое CNI-конфигов:
ls -la /etc/cni/net.d
for f in /etc/cni/net.d/*; do echo "### $f"; sed -n '1,200p' "$f"; done
По этим данным обычно уже видно: нет конфигов, не тот плагин, IPAM, таймаут агента, проблемы iptables/eBPF и т.д.
Профилактика: как реже видеть CNI ADD failed в проде
Держите узлы наблюдаемыми: логи kubelet/containerd, перезапуски DaemonSet CNI, базовые метрики по conntrack и ошибкам правил.
Перед апгрейдами ядра и Kubernetes сверяйте совместимость CNI (особенно для eBPF-режимов).
Контролируйте пересечение адресных пространств: PodCIDR/ServiceCIDR/подсети инфраструктуры.
Закладывайте запас по IP-пулам и учитывайте автоскейлинг.
Унифицируйте сетевые правила между узлами (на уровне ОС и на уровне провайдера).
Короткая шпаргалка: что делать, если «failed to create pod sandbox» прямо сейчас
Понять, один узел или весь кластер:
kubectl get pods -A -o wide.На проблемном узле: логи kubelet и runtime (journalctl).
Проверить
/etc/cni/net.dи/opt/cni/bin.Проверить Pod’ы CNI в
kube-systemи их логи.Дальше идти по факту: IPAM, iptables/eBPF, маршруты/MTU, доступность агента.
Если хотите, можно «приземлить» диагностику под вашу связку (kubeadm/k3s/rke2, containerd/CRI-O, Calico/Cilium/Flannel) и добавить точечные команды именно под неё — так разбор становится заметно быстрее.
А если вы поднимаете кластер на отдельных серверах, следите за консистентностью ядра и сетевых настроек между узлами: на VDS это проще контролировать, чем на разнородных машинах.


