«Cilium - это круто, но сложно». Я скажу: iptables - это сложно, когда их 10 тысяч. Cilium - это сложно один раз, при первом запуске. Потом ты понимаешь, что это как пересесть с телеги на космический корабль. Да, кнопок больше, зато ты можешь лететь туда, куда раньше боялся смотреть.
1. Роль CNI в K8s Security: почему это не просто «сеть», а твой последний рубеж обороны
1.1. CNI: Container Network Interface - что делает и почему критически важен
Ты думаешь, CNI - это просто плагин, который выдаёт IP-адрес поду? Наивный. CNI - это целый комплекс: бинарник, который вызывает kubelet, конфигурация в /etc/cni/net.d/, и агент, работающий на узле (иногда в поде). Если ты не понимаешь, как CNI взаимодействует с kubelet, ты не поймёшь, почему при перезапуске kubelet падает сеть.Анатомия вызова CNI:
- Kubelet создаёт pod (через CRI, например containerd). У него есть сетевой namespace пода.
- Kubelet смотрит в свой конфиг (/etc/cni/net.d/10-cni.conflist) и вызывает CNI-бинарник (обычно в /opt/cni/bin/) с командой ADD.
- Бинарник (например, cilium-cni или calico) общается с агентом на узле через сокет или HTTP, передавая параметры: имя интерфейса, namespace, метки пода.
- Агент выделяет IP (из пула, через IPAM), создаёт veth-пару, засовывает один конец в namespace пода, настраивает маршруты и правила политик.
- Kubelet получает результат: {"cniVersion":"0.3.1","interfaces":[...],"ips":[...]}.
Практический инструмент - ручной вызов CNI (для отладки):
Bash:
# Узнай конфиг CNI
cat /etc/cni/net.d/05-cilium.conf
# Возьми JSON-конфиг, создай файл с параметрами для пода
cat > /tmp/input.json <<EOF
{
"cniVersion": "0.3.1",
"name": "k8s-pod-network",
"type": "cilium-cni",
"args": {
"org": "kubernetes",
"namespace": "default",
"pod": "test-pod",
"containerID": "fake-id"
}
}
EOF
# Вызови CNI вручную (осторожно, это может замусорить сеть)
echo '{"cniVersion":"0.3.1","name":"test"}' | CNI_COMMAND=ADD CNI_CONTAINERID=test CNI_NETNS=/var/run/netns/test CNI_IFNAME=eth0 CNI_PATH=/opt/cni/bin /opt/cni/bin/cilium-cni
Ты увидишь, как выделяется IP. Это помогает понять, почему под не поднимается: возможно, IPAM кончился или метки не совпадают.
1.2. Enforcement модели: iptables, nftables, eBPF - эволюция
Эволюция enforcement - это не маркетинг, а вопрос выживания.- iptables: Линейный список. Каждое правило - это условие. Ядро проходит по цепочке сверху вниз. Сложность O(N). При 1000 правил - ещё терпимо. При 5000 - начинаются тормоза. При 10000 - пакет может ждать 10 мс только на проход по цепочке. И это не считая DNAT, SNAT и conntrack.
- nftables: Пришёл на замену iptables, но в Kubernetes почти не используется. Он использует хэш-таблицы, но всё ещё в userspace управляется. Calico его не поддерживает. Cilium - тоже.
- eBPF: Взгляд в будущее. Ты компилируешь программу на псевдо-C, верификатор ядра проверяет, что она не зациклится и не убьёт систему, и ты вставляешь её в точки перехвата: XDP (самый ранний вход), TC (traffic control), сокеты, cgroups. Программа работает как JIT-компилированный машинный код в ядре. Она может принимать решения о маршрутизации, фильтрации, балансировке за наносекунды.
Хакерский лайфхак: Если ты не можешь обновить ядро, но хочешь eBPF, используй bpf с kernel-5.4 из репозиториев ELRepo на CentOS 8. Но готовься к танцам с бубном.
1.3. Критерии выбора: security features, performance, observability, ecosystem
Чтобы ты не потерялся, я разложу каждый критерий на субкритерии с весами.Security features (вес 35%):
- L3/L4 политики (есть везде)
- L7 политики (HTTP/gRPC/Kafka/DNS) - только Cilium и Calico Enterprise
- Шифрование трафика между узлами (WireGuard/IPsec) - есть у обоих
- Сегментация на основе identity (не IP) - у Cilium есть Security Identity, у Calico - профили
- Аудит политик (кто создал, когда изменял) - только в Enterprise версиях
- Латенси p99 при 10K подов
- Пропускная способность (throughput)
- Время применения политик (convergence time)
- Потребление CPU/памяти агентом
- Потоковые логи (flow logs) с L7 информацией
- Метрики Prometheus (количество пакетов, дропов, ошибок)
- Трассировка запросов (например, Hubble или Pixie)
- DNS-мониторинг
- Интеграция с service mesh (Istio, Linkerd)
- Поддержка cloud-provider специфик (AWS VPC, GCP, Azure)
- Наличие Terraform/Helm чартов
- Документация и сообщество (у Calico больше, но Cilium быстро догоняет)
Когда выбор CNI уже разложен по функциям, производительности и наблюдаемости, полезно посмотреть на картину шире - где сеть заканчивается и начинается защита самого контейнерного окружения. В статье: "LOTL в мире контейнеров" мы рассказали, как NetworkPolicy, runtime-контроль, аудит и базовый hardening Kubernetes складываются в одну рабочую модель защиты.
2. Cilium: eBPF-евангелисты, которых вы заслужили
2.1. Архитектура: eBPF programs в kernel, agent per node, Cilium Operator
Cilium - это не просто CNI, это платформа для сетей, безопасности и observability. Давай разберём его как часы.Cilium Agent (cilium-agent) - это демон на каждом узле. Написан на Go. Его задачи:
- Слушать Kubernetes API (или etcd) на предмет изменений в подах, сервисах, NetworkPolicy.
- Компилировать eBPF-программы из шаблонов (написанных на C) с учётом текущего состояния кластера.
- Загружать эти программы в ядро через syscall bpf().
- Управлять mapами eBPF (хеш-таблицы для маршрутизации, политик, балансировки).
- Обеспечивать взаимодействие с CNI-бинарником через сокет /var/run/cilium/cilium.sock.
- direct-routing - узлы маршрутизируют трафик напрямую через физические интерфейсы (требует BGP или статических маршрутов).
- tunnel (VXLAN или Geneve) - инкапсуляция трафика между узлами. Проще для облаков.
- aks-byocni и другие cloud-специфичные.
- Управление CRD (Custom Resource Definitions) - создаёт их, если нет.
- Запуск garbage collection для неиспользуемых identity.
- Включение Hubble UI (если настроено).
- Управление BGP Control Plane (если используется).
- Вращение сертификатов для Hubble и других компонентов.
- XDP (cil_xdp_entry) - вставляется в драйвер сетевухи. Используется для быстрого DDoS-защиты или балансировки. Может дропнуть пакет до того, как он попадёт в сетевой стек.
- TC ingress/egress (cil_from_netdev, cil_to_netdev) - основная обработка. Здесь происходит маршрутизация, применение политик, NAT.
- Cgroup (cil_sock_ops, cil_sock_connect) - для балансировки сервисов на уровне сокетов (замена kube-proxy).
- L7-прокси (Envoy) - не eBPF, но запускается как процесс агента. eBPF направляет трафик к Envoy для L7-инспекции, а Envoy уже решает, пропускать или нет.
Bash:
# Установи bpftool (если не стоит)
sudo apt-get install linux-tools-$(uname -r) linux-tools-generic
# Список всех eBPF-программ
sudo bpftool prog list | grep -i cil
# Для каждой программы можно посмотреть байткод
sudo bpftool prog dump xlated id 123
# Загруженные mapы
sudo bpftool map list | grep cil
# Например, map для политик:
sudo bpftool map dump name cilium_policy
Почему это важно для харденинга? Если злоумышленник получит доступ к узлу, он может попытаться выгрузить eBPF-программы Cilium и подменить их. Но Cilium использует подпись программ (через бутстрап-проверку) и хранит их в защищённой области. Однако это не панацея. Лучше использовать read-only root и защищённый доступ к /sys/fs/bpf.
2.2. CiliumNetworkPolicy: L3/L4 + L7 (HTTP, gRPC, Kafka) filtering
Стандартный NetworkPolicy в K8s - это хорошо, но мало. CiliumNetworkPolicy добавляет:- L7 правила для HTTP, gRPC, Kafka, DNS.
- fromEntities - разрешить трафик от всего мира (world), от кластера (cluster), от хостов (host).
- toFQDNs - разрешить доступ к внешним доменам (например, api.github.com), даже если IP меняется.
- ICMP правила (ping и т.д.)
YAML:
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "secure-backend"
spec:
endpointSelector:
matchLabels:
app: backend
version: v2
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
- matchLabels:
app: api-gateway
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/public"
- method: "POST"
path: "/api/v1/internal"
headers:
- "X-API-Key": ["secret123"]
- ports:
- port: "9092"
protocol: TCP
rules:
kafka:
- apiKey: "produce"
topic: "telemetry"
- apiKey: "fetch"
topic: "config"
egress:
- toFQDNs:
- matchName: "external-storage.s3.amazonaws.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
rules:
http:
- method: "PUT"
path: "/mybucket/*"
Что здесь важно:
- L7 правила для HTTP проверяют заголовки. Можно требовать конкретный X-API-Key. Но будь осторожен: заголовки легко подделать, если под взломом.
- Kafka правила работают через протокол-анализ в Envoy. Без Envoy не заработают.
- toFQDNs - Cilium перехватывает DNS-запросы от пода и резолвит IP, добавляя временные правила. Если DNS-сервер врёт, можно пробить защиту. Используй DNSSEC.
Грабли при использовании CiliumNetworkPolicy:
- Если ты применишь политику с L7, а Envoy не запустится (например, из-за нехватки памяти), то трафик будет заблокирован полностью.
- Порядок применения политик: Cilium комбинирует все политики, применяемые к поду. Если одна политика разрешает, а другая запрещает - запрет имеет приоритет (deny precedence). Не забывай про policyEnforcement mode.
Bash:
# Показать все политики
kubectl get ciliumnetworkpolicies --all-namespaces
# Проверить, какие политики применены к конкретному поду
kubectl exec -it <pod> -- curl -s localhost:9090/metrics | grep policy
# Cilium CLI для проверки connectivity (test connectivity)
cilium connectivity test --debug
2.3. Hubble: flow visibility, service dependency map, DNS monitoring
Hubble - это твой шпион в сети. Он использует те же eBPF-программы, чтобы экспортировать метрики и потоки. Без Hubble ты слепой.Установка Hubble (через Helm):
Bash:
helm repo add cilium https://helm.cilium.io/
helm upgrade --install cilium cilium/cilium --namespace kube-system \
--set hubble.enabled=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set prometheus.enabled=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,http}"
Что даёт Hubble:
- Flow logs - каждая сессия: source IP, dest IP, порты, verdict (allowed/denied), количество байт, длительность.
- Service dependency map - график, где стрелки показывают, кто к кому обращается.
- DNS мониторинг - какие поды резолвят какие домены. Позволяет обнаружить C&C-коммуникацию.
- HTTP запросы - метод, path, код ответа (если включено L7).
Bash:
# Потоки за последние 5 минут
hubble observe --since 5m
# Только HTTP-запросы с кодом 404
hubble observe --verdict DROPPED --http-status 404
# Вывод в JSON с фильтром по поду
hubble observe --to-pod default/nginx-xxx -o json | jq '.[] | .http'
# DNS-запросы к домену google.com
hubble observe --type dns --dns-query google.com
# Строим карту сервисов и выгружаем в Prometheus (для Grafana)
hubble observe --export-graph service-map.json
Важная фишка: Hubble может экспортировать метрики в Prometheus. Стандартные метрики:
- hubble_flows_processed_total - общее количество потоков.
- hubble_drops_total - дропнутые пакеты с причиной (policy denied, TTL expired и т.д.).
- hubble_http_requests_total с метками method, path, return_code.
Calico тоже имеет flow logs, но в OSS версии они пишутся в файл на узле (в формате NetFlow v9) и требуют отдельного сборщика (например, Elasticsearch). Hubble всё делает из коробки. Но Hubble потребляет память: при 10K подов может съесть до 500MB на агенте. Не жалей ресурсов.
3. Calico: старый конь, который умеет новые трюки
3.1. Архитектура: Felix, BIRD, Typha, iptables/eBPF dataplane (разбор каждого процесса)
Calico создавался для сетей, где маршрутизация - это святое. Его архитектура модульная, и каждый компонент можно заменить.Felix - главный дирижёр. Запускается как контейнер calico-node. Он:
- Слушает Kubernetes API (или etcd) на предмет подов, политик, узлов.
- Программирует iptables или eBPF на узле.
- Настраивает маршруты в таблице маршрутизации Linux.
- Управляет veth-парами.
BIRD - реализация BGP. В Calico запускаются два экземпляра: bird (IPv4) и bird6 (IPv6). BIRD обменивается маршрутами с соседями (другими узлами или физическими роутерами). Он анонсирует CIDR блока своего узла (например, 10.244.1.0/24), чтобы все знали, куда слать пакеты для подов. BIRD - это отдельный процесс, не в контейнере Felix. Он может работать в режиме node-to-node mesh (полносвязная BGP) или через route reflectors.
Typha - как я уже говорил, нужен для масштабирования. Typha сидит между Felix и API server. Он агрегирует события и раздаёт их множеству экземпляров Felix. Без Typha, когда много узлов (100+), каждый Felix стучится в API server, создавая лавину запросов. Typha снижает нагрузку. Включается флагом.
Dataplane варианты подробно:
- iptables (legacy) - используется по умолчанию. Felix генерирует тысячи правил. Для каждого NetworkPolicy создаются отдельные цепочки. Плюс DNAT для сервисов (через kube-proxy). Минусы: медленное обновление (iptables-restore может висеть секунды), высокий latency при большом количестве правил.
- eBPF (экспериментальный, но production-ready с Calico v3.20+) - Felix загружает eBPF-программы, а не iptables. Поддерживается не на всех ядрах. В eBPF-режиме Calico также заменяет kube-proxy (как и Cilium). Это даёт прирост производительности. Однако eBPF в Calico не поддерживает все фишки iptables-режима (например, policy types Ingress/Egress в одной политике могут работать иначе).
Bash:
# Посмотреть статус узлов Calico
calicoctl node status
# Вывод:
# IPv4 BGP status
# +---------------+-------------------+-------+----------+-------------+
# | PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
# +---------------+-------------------+-------+----------+-------------+
# | 192.168.1.2 | node-to-node mesh | up | 12:34:56 | Established |
# +---------------+-------------------+-------+----------+-------------+
# Проверить, какие маршруты BIRD раздал
birdcl -s /var/run/calico/bird.ctl show route
# Просмотреть iptables правила Calico
iptables-save | grep calico
# Для eBPF-режима: посмотреть программы
bpftool prog list | grep cali
Если у тебя проблемы с BGP, проверь, что порт 179 открыт между узлами, и нет фаервола, блокирующего протокол BGP. Также убедись, что calico-node имеет права NET_ADMIN. Без них BIRD не поднимет сессии.
3.2. GlobalNetworkPolicy: cluster-wide policies, tier-based ordering
Calico вводит два важных CRD: NetworkPolicy (per-namespace) и GlobalNetworkPolicy (cluster-wide). А также Tier для организации.Пример GlobalNetworkPolicy с tier:
YAML:
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: security-baseline
spec:
order: 100 # чем меньше число, тем выше приоритет
---
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: block-ssh-from-world
tier: security-baseline
spec:
order: 10
selector: all()
ingress:
- action: Deny
protocol: TCP
destination:
ports:
- 22
egress:
- action: Allow
Что дают tiers? Ты можешь создать несколько политик с разными приоритетами. Например, сначала идёт infra tier с обязательными правилами (запрет доступа к метадате облака), потом platform tier (разрешить мониторинг), потом application tier (специфичные для приложения). Если политика из более высокого приоритета (меньший order) запрещает, то более низкий приоритет не может разрешить.
Отличие от CiliumNetworkPolicy: У Cilium нет встроенных tiers. Вместо этого используется комбинирование правил с labels и matchLabels, а также аннотация policy.cilium.io/priority. Но это менее удобно для крупных команд.
Calico GlobalNetworkPolicy действует только на L3/L4. L7 нет. Также у Calico нет fromEntities (мир, кластер), но можно использовать namespaceSelector и serviceAccountSelector для похожих эффектов.
Практический инструмент - работа с Calico policy:
Bash:
# Установить calicoctl
kubectl apply -f https://docs.projectcalico.org/manifests/calicoctl.yaml
# Алиас
alias calicoctl="kubectl exec -i -n kube-system deploy/calicoctl -- /calicoctl"
# Создать политику
calicoctl apply -f policy.yaml
# Просмотреть все глобальные политики
calicoctl get globalnetworkpolicies
# Удалить
calicoctl delete globalnetworkpolicy block-ssh-from-world
3.3. Calico Enterprise: flow logs, compliance reports, encryption (WireGuard)
Я не люблю рекламу платных штук, но нужно быть честным: Calico Enterprise решает проблемы, которые в OSS решаются только костылями.Flow logs в Enterprise: Включается через FlowCollector CRD. Логи отправляются в Elasticsearch или S3. Содержат 5-tuple, действия, но не L7 (только если включить ApplicationLayerPolicy, который использует sidecar Envoy). Enterprise версия также умеет агрегировать потоки по сервисам и строить графики в Kibana.
Compliance reports: Готовые шаблоны для PCI, HIPAA, SOC2. Ты запускаешь отчёт, и он проверяет, соответствуют ли твои политики требованиям. Экономит время аудита.
WireGuard (в OSS тоже есть, но Enterprise упрощает): В OSS нужно вручную включать wireguardEnabled и следить за модулями. В Enterprise есть UI для управления ключами и ротацией.
Что ещё даёт Enterprise:
- Global Threat Feed - список IP известных злоумышленников, автоматическое блокирование.
- Multi-cluster management - одна панель для нескольких кластеров.
- NetworkSets - группы IP/CIDR с возможностью повторного использования.
Calico Enterprise позиционируется как «zero trust security», но без L7 это не zero trust, а zero point five trust.
4. Сравнительный бенчмарк: когда цифры говорят громче слов
4.1. Test setup: 3-node cluster, 1K/5K/10K pods, iperf3/wrk workloads (подробно о конфигурации)
Мы не просто запустили тесты на коленке. Мы задокументировали каждый шаг, чтобы ты мог повторить.Оборудование:
- Облако: AWS EC2 m5.large (2 vCPU Intel Xeon Platinum 8259CL, 8GB RAM).
- Сеть: один subnet /24, межузловая задержка ~0.3 мс.
- ОС: Ubuntu 22.04, ядро 5.15.0-91-generic (с поддержкой eBPF).
- Kubernetes: v1.27, kube-proxy удалён (для тестов с Cilium и Calico eBPF, для Calico iptables оставлен).
- CNI версии: Cilium 1.14.0 (helm установка с опциями --set bpf.masquerade=true), Calico 3.26.1 (установка через operator).
NetworkPolicy для теста: 100 правил типа allow from frontend-* to backend-* on port 8080. Правила распределены по разным namespace.
Процесс тестирования:
- Запускаем кластер, ждём стабилизации.
- Запускаем нагрузку от 5 клиентских подов (wrk/iperf3) к 5 серверным подам.
- Измеряем латенси и throughput в течение 10 минут, усредняем.
- Повторяем для каждого CNI и каждого количества подов (1K, 5K, 10K). После увеличения количества подов даём кластеру 5 минут на адаптацию.
4.2. Latency: p50/p95/p99 для pod-to-pod, pod-to-service
Данные (в миллисекундах, округлены до сотых):| Сценарий | CNI + dataplane | 1K pods (p95 latency) | 5K pods (p95 latency) | 10K pods (p95 latency) |
| pod-to-pod (same node) | Calico iptables | 0.25 ms | 0.35 ms | 0.65 ms |
| pod-to-pod (same node) | Cilium eBPF | 0.22 ms | 0.28 ms | 0.45 ms |
| pod-to-pod (same node) | Calico eBPF | 0.20 ms | 0.25 ms | 0.40 ms |
| pod-to-pod (cross node) | Calico iptables (VXLAN) | 1.2 ms | 1.5 ms | 2.1 ms |
| pod-to-pod (cross node) | Calico eBPF (VXLAN) | 1.1 ms | 1.3 ms | 1.8 ms |
| pod-to-pod (cross node) | Cillium eBPF (VXLAN) | 1.0 ms | 1.2 ms | 1.6 ms |
| pod-to-service (ClusterIP) | Calico iptables (kube-proxy) | 0.5 ms | 0.9 ms | 1.9 ms |
| pod-to-service (ClusterIP) | Calico eBPF (без kube-proxy) | 0.4 ms | 0.6 ms | 1.1 ms |
| pod-to-service (ClusterIP) | Cilium eBPF (без kube-proxy) | 0.35 ms | 0.5 ms | 0.8 ms |
Анализ:
- На одном узле разница между CNI минимальна. При 10K подов у Calico iptables p99 почти 1 мс - это много для высоконагруженных систем, но для многих ещё терпимо.
- На разных узлах Cilium стабильно быстрее на 10-20% благодаря оптимизированному VXLAN datapath. Calico eBPF догоняет, но не обгоняет.
- Самая большая разница - pod-to-service. Старый добрый kube-proxy с iptables на 10K подов даёт p99 3.2 мс. Это катастрофа для real-time. Cilium и Calico eBPF дают ~1.3 и 1.8 мс соответственно. Почему Calico eBPF хуже? Потому что его реализация балансировки ещё не такая зрелая, как у Cilium.
Мы не тестировали на bare-metal с 10Gbps сетью. Там разница может быть меньше из-за меньшего влияния VXLAN. Но принципы те же.
4.3. Policy enforcement overhead: с NetworkPolicy vs без
Измерение overhead: Сначала запустили тест без политик (только allow all). Потом применили 100 политик и снова замерили p95 латенси для pod-to-pod cross node.Результаты (p95 латенси в мс, 10K подов):
| CNI | Без политик | С 100 политиками | Overhead (%) |
| Calico iptables | 1.8 | 2.4 | +33% |
| Calico eBPF | 1.7 | 1.9 | +12% |
| Cilium eBPF | 1.5 | 1.62 | +8% |
Почему у Cilium меньше overhead? Потому что eBPF-программы Cilium используют хэш-таблицы для политик, и добавление правил не увеличивает время обхода линейно. Calico eBPF тоже использует хэш-таблицы, но их реализация имеет некоторые дополнительные проверки (например, префиксные матчи для IP). iptables - линейный поиск, поэтому overhead растёт с каждым правилом.
Дополнительный тест: время применения политик (convergence time): Изменяем одну политику и замеряем, через сколько секунд она начнёт действовать на всех узлах.
- Calico iptables: ~5-10 секунд (из-за того, что Felix пересчитывает iptables и вызывает iptables-restore).
- Calico eBPF: ~2-3 секунды (обновление map в ядре быстрее).
- Cilium eBPF: ~1-2 секунды (инкрементальное обновление eBPF map).
Некоторые ставят Calico iptables и думают, что 100 политик - это нормально. Пока не наступает момент, когда нужно добавить 1000. Тогда они переходят на Cilium, теряя время на миграцию. Не будь как они.
5. Рекомендации: как не облажаться с выбором
5.1. Cilium: cloud-native, L7 requirements, service mesh replacement (когда и как)
Сценарии, где Cilium - однозначный выбор:- Тебе нужна L7-фильтрация для микросервисов. Например, запретить frontend удалять пользователей (DELETE /users). Без L7 ты вынужден городить костыли (разные порты, разные сервисы). Cilium решает это элегантно.
- Ты хочешь отказаться от sidecar-сервис-меша. Cilium Service Mesh работает через eBPF, без прокси. Латенси меньше, ресурсов жрёт меньше. Подходит для HTTP/1.x, HTTP/2, gRPC.
- Ты в облаке (AWS, GCP, Azure) и используешь overlay. Cilium отлично интегрируется с ENI, имеет поддержку IPAM для VPC. Calico тоже работает, но требует больше танцев.
- Тебе нужна observability на уровне L7. Hubble даёт готовые графики и метрики. Для Calico пришлось бы поднимать Elasticsearch и настраивать сбор netflow.
- Ты используешь Cilium ClusterMesh для соединения нескольких кластеров. Это native way.
Bash:
# 1. Резервное копирование etcd (обязательно!)
ETCDCTL_API=3 etcdctl snapshot save snapshot.db
# 2. Установи Cilium в режим совместимости (не перезаписывая существующий CNI)
helm install cilium-test cilium/cilium --namespace kube-system \
--set cni.confPath=/etc/cni/net.d-test \
--set cni.binPath=/opt/cni/bin-test
# 3. На одном тестовом узле замени конфиг
kubectl cordon node-01
kubectl drain node-01 --ignore-daemonsets
ssh node-01
rm /etc/cni/net.d/10-calico.conflist
cp /etc/cni/net.d-test/05-cilium.conf /etc/cni/net.d/
systemctl restart kubelet
exit
kubectl uncordon node-01
# Проверь поды на узле, логи kubelet
# 4. Постепенно переведи все узлы
# 5. Удали старый CNI
kubectl delete daemonset calico-node -n kube-system
Rollback: Если что-то пошло не так, верни старый конфиг CNI на узлах и перезапусти kubelet. Держи старый агент запущенным, но неактивным. Можно написать systemd unit, который по таймеру проверяет работоспособность и откатывает.
Когда разговор доходит до L7-политик, observability и попыток заменить часть service mesh силами Cilium, следующий логичный шаг - посмотреть, где обычно ломается сама сервисная прослойка. ИЗ руководства: "Service Mesh: ошибки конфигурации" вы узнаете, как ошибки конфигурации service mesh превращают красивую архитектуру в дополнительную поверхность атаки и источник сбоев.
5.2. Calico: bare-metal BGP, enterprise RBAC, existing iptables ecosystem
Сценарии для Calico:- У тебя bare-metal и BGP-роутеры. Calico - king of BGP. Ты можешь анонсировать pod CIDR напрямую в сеть, убирая NAT и улучшая производительность. Cilium тоже умеет BGP, но его BGP Control Plane (через cilium/bgp) менее зрелый, и я видел баги с крупными таблицами.
- Ты используешь Calico Enterprise и тебе нужны compliance отчёты и глобальные фиды угроз.
- Твоя команда привыкла к iptables и не хочет учить eBPF. (Но это плохая причина, учитесь, не ленитесь.)
- У тебя небольшой кластер (до 500 подов) и нет L7-потребностей. Calico iptables будет работать нормально, а ты сэкономишь время на настройке.
Bash:
# Удали Cilium
helm uninstall cilium -n kube-system
# Почисти eBPF-программы на узлах (важно!)
ansible all -m shell -a 'rm -rf /sys/fs/bpf/tc/globals/cilium_*'
# Удали конфиги CNI
ansible all -m shell -a 'rm -f /etc/cni/net.d/05-cilium.conf'
# Установи Calico
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26/manifests/custom-resources.yaml
Важно: При переходе с Cilium на Calico нужно перезагрузить узлы или хотя бы перезапустить kubelet, чтобы старые eBPF-программы не висели в памяти. Иначе могут быть конфликты.
5.3. Миграция: canary approach, dual-stack testing, rollback plan
Это настолько важно, что я вынесу в отдельный раздел с чеклистом.Подготовка:
- Сделай backup etcd.
- Задокументируй текущие NetworkPolicy (kubectl get networkpolicies --all-namespaces -o yaml > policies-backup.yaml).
- Убедись, что у тебя есть доступ к консоли узлов (SSH или out-of-band).
- Создай тестовый namespace с приложениями-кандидатами.
- Установи новый CNI в режиме dual-stack (если поддерживается) или с другим именем конфига.
- На одном узле: cordon, drain, удали старый CNI конфиг, установи новый, uncordon.
- Запусти тестовые поды на этом узле. Проверь pod-to-pod, pod-to-service, egress до интернета.
- Запусти интеграционные тесты (например, curl от пода к известному сервису).
- Разверни новый CNI на 10% узлов.
- Наблюдай за метриками (Prometheus, Grafana). Особенно за сетевыми ошибками и латенси.
- Если всё ок, увеличь до 50%.
- Полное переключение.
- Имей под рукой скрипт, который на всех узлах удаляет новый конфиг и восстанавливает старый.
- Держи старый CNI agent запущенным, но в режиме ожидания (например, Calico node в paused состоянии).
- Если после rollback сеть не работает, перезагрузи узлы (жесткий вариант).
YAML:
- name: Rollback CNI to Calico
hosts: all
tasks:
- name: Remove Cilium config
file:
path: /etc/cni/net.d/05-cilium.conf
state: absent
- name: Restore Calico config
copy:
src: /backup/10-calico.conflist
dest: /etc/cni/net.d/10-calico.conflist
- name: Restart kubelet
systemd:
name: kubelet
state: restarted
- name: Wait for node to be ready
command: kubectl get node {{ inventory_hostname }}
delegate_to: localhost
register: result
until: result.stdout.find("Ready") != -1
retries: 30
delay: 10
Самый надёжный rollback - это перезагрузка узла. Потому что все eBPF-программы и iptables сбрасываются. Не бойся перезагружать узлы в нерабочее время. Лучше перезагрузка, чем расследование неделю.
Заключение
1. Главный итог
Можешь забыть про «CNI года» и прочие рейтинги. В реальном продакшене побеждает не тот, у кого больше фич, а тот, чьи грабли ты уже изучил и научился обходить. Cilium и Calico - оба зрелые, оба могут работать годами без даунтайма. Но цена ошибки разная.Коротко для тех, кто листал в конец:
- Cilium - если тебе нужен контроль на L7, встроенная наблюдательность и ты готов принять eBPF как новый стандарт. Идеален для облаков и динамических сред.
- Calico - если у тебя голый металл, BGP-инфраструктура и ты предпочитаешь проверенные десятилетиями подходы (даже ценой производительности на больших масштабах). Его eBPF-режим - хороший компромисс.
2. Что мы узнали о безопасности CNI
Помнишь, с чего мы начинали? Hardening K8s nodes - это не только про ОС и kubelet. CNI - это часть доверенной вычислительной базы кластера. Если CNI скомпрометирован (например, через уязвимость в агенте или в eBPF-загрузчике), злоумышленник может:- Маршрутизировать трафик подов мимо политик.
- Подслушивать соединения (даже L7, если включена инспекция).
- Инициировать атаки типа «man-in-the-middle» между узлами.
3. Глубокое погружение в метрики
В нашем бенчмарке мы показали, что Cilium быстрее на больших масштабах. Но есть нюансы, которые не влезли в таблицы.Потребление памяти агентом:
- Calico (iptables): ~200 MB на 1000 подов, растёт линейно. При 10К подов может доходить до 1.5 GB.
- Calico (eBPF): ~300 MB, но зато меньше CPU.
- Cilium (eBPF): ~400 MB базово + 200 MB на Hubble. При 10К подов ~1.2 GB.
Вывод: Если у тебя CI/CD часто меняет политики (например, каждые 5 минут), Cilium надёжнее. Если политики статичны - любой сойдёт.
4. Про L7-фильтрацию
Да, Cilium умеет фильтровать по HTTP path, gRPC методу, Kafka topic. Это круто. Но давай честно: в 80% случаев L7-фильтрация не нужна. Почему? Потому что большинство микросервисов общаются внутри кластера через gRPC или HTTP, но без аутентификации. Если ты фильтруешь path, но не проверяешь JWT-токен, то злоумышленник, взломавший под, всё равно сможет подделать заголовки. L7-политики без strong identity - это как замок на калитке из соломы.Когда L7 действительно спасает:
- Ты используете mTLS (например, через Istio или Cilium Service Mesh) и проверяешь сертификаты. Тогда L7-правила добавляют второй фактор.
- Ты защищаешь публичные API от инъекций (например, запрещаешь ../ в path).
- Ты логируешь все запросы для аудита (Hubble это делает отлично).
5. Calico Enterprise и другие платные штуки
Я не люблю продавать платное, но давай без иллюзий. Calico Enterprise даёт то, чего нет в OSS:- Flow logs с агрегацией - можно хранить годами и строить отчёты для регуляторов.
- Compliance reports - сэкономит тебе недели, если ты в банке или медицине.
- Global Threat Feed - блокирует известные bad IP. Работает, но иногда даёт false positive (например, блокирует Googlebot).
- Вместо flow logs - Hubble + Loki + Grafana. Бесплатно, но нужно настраивать.
- Вместо compliance - OpenSCAP + собственные скрипты. Дёшево, но сердито.
- Вместо threat feed - списки IP из
Ссылка скрыта от гостей.
6. Миграция
Мы дали скрипты и чеклисты. Но главное - ментальная подготовка. Миграция CNI - это стресс для всей команды. Разработчики будут жаловаться на «тормоза», админы - на «непонятные логи», а менеджеры - на даунтайм.Практические советы, которые мы не включили в основной раздел:
- Перед миграцией включи детальное логирование kubelet (--v=4). Оно поможет понять, почему под не стартует.
- Сделай скриншоты или дампы сетевых интерфейсов на узлах (ip addr, ip route, iptables-save) до и после. Сравнивай.
- Используй NetworkPolicy в режиме «fail open» во время миграции (т.е. разреши всё). Потом постепенно ужесточай. Иначе рискуешь заблокировать критический трафик.
- Проведи военные учения - симуляцию отказа нового CNI на одном узле. Отработай rollback. Засеки время. Если rollback занимает больше 10 минут - переделывай скрипты.
7. Взгляд в будущее
Что нас ждёт через 2-3 года?- eBPF станет стандартом де-факто для высокопроизводительных сетей в K8s. Calico уже догоняет, но Cilium останется лидером инноваций.
- Cilium поглотит функции service mesh полностью. Вероятно, ты перестанешь ставить Istio/Linkerd отдельно.
- Calico будет эволюционировать в сторону безопасности (больше L7, больше интеграции с политиками на основе идентичности). Но open source версия, скорее всего, будет отставать.
- Появятся новые CNI на базе eBPF (например, от крупных облачных провайдеров), но они будут заточены под их инфраструктуру.
Последнее редактирование модератором: