kube-proxy — самый незаметный компонент Kubernetes: он молча превращает виртуальный IP сервиса в адрес конкретного пода. Пока сервисов десятки, о нём никто не вспоминает. Проблемы начинаются на масштабе — и в 2026 году у этого старого механизма появился серьёзный повод для замены.
Почему iptables-режим упирается в потолок
kube-proxy в режиме по умолчанию для каждого пакета линейно обходит цепочку iptables-правил. До ~1000 сервисов это незаметно; выше — расход CPU растёт пропорционально размеру каталога. Но хуже масштаба — слепота. iptables выбирает backend-под случайно: ядро «бросает взвешенную монету», и маршрутизация не видит ни latency, ни длину очереди соединений, ни health пода. Трафик уйдёт в перегруженный под или через соседнюю зону доступности, даже если рядом на той же ноде есть здоровый. Под нагрузкой это вырождается в retries → каскадные сбои → скачки P99.
1.36 убрал IPVS, а nftables лечит не то
В Kubernetes 1.36 режим IPVS у kube-proxy удалён — у тех, кто когда-то бежал от iptables в IPVS ради constant-time lookup, выбор сузился. С версии 1.31 kube-proxy переехал на nftables-backend: это чинит масштабирование и скорость обновления правил, но не трогает корень проблемы. Решения по-прежнему принимаются на уровне L4 и остаются слепыми к состоянию приложения.
Как eBPF меняет правила игры
Cilium заменяет kube-proxy одним флагом — kubeProxyReplacement: true. Вместо обхода цепочки правил — constant-time lookup в скомпилированной eBPF-программе прямо в ядре. Ментальная модель проста: iptables спрашивает «какое правило подходит этому пакету?», eBPF отвечает «я уже знаю, что делать».
Главный трюк — socket-LB. Классический kube-proxy делает DNAT на пакете после connect(), и каждый пакет проходит через conntrack. Cilium переписывает destination на уровне syscall — до того, как пакет вообще создан. Нет conntrack, нет SNAT-оверхеда, latency ниже. Поверх этого Maglev consistent hashing закрепляет один 5-tuple (src/dst IP, src/dst port, протокол) за одним и тем же подом — критично для кэш-слоёв вроде Redis, где случайный выбор backend'а распыляет запросы и убивает hit-rate. Побочный эффект для отладки: tcpdump на стороне пода покажет уже переписанный destination, а не ClusterIP сервиса — это первое, что сбивает с толку.
Где это окупается, а где нет
Честный контрапункт важнее маркетинга. На кластере из 1–3 нод kube-proxy на iptables может обойти Cilium по latency на чистом pod-to-pod трафике: eBPF-оверхед не окупается на маленькой conntrack-таблице из пары сотен сервисов. Cilium дороже в эксплуатации — требует ядра Linux ≥5.x, добавляет ручек, а eBPF-инциденты отлаживать сложнее, чем читать iptables-правила.
Решающее правило: замена kube-proxy через eBPF оправдана при ≥5 нодах, ≥100 сервисах либо когда явно нужны L7-политики, observability через Hubble или Cluster Mesh. Это осознанный выбор под нагрузку, а не «по умолчанию всегда».
С чего начать
Сначала проверьте версию ядра (≥5.x) на всех нодах — это жёсткое предусловие, а не рекомендация. Раскатывайте через canary-ноды: сетевые проблемы на уровне ядра пугают сильнее, чем отладка iptables. Сразу включайте Hubble — flow-visibility превращает «пакет куда-то пропал» в «датапас дропнул пакет по конкретной причине», и это окупается с первого же инцидента. На bare-metal стеке (kubeadm + Cilium с kubeProxyReplacement=true) такой набор давно стал стандартным.
И обратное: если L7-политики, mesh и продвинутая observability не нужны, связка Calico + kube-proxy остаётся полностью достаточной. Главный принцип сетевого слоя тот же, что и везде в инфраструктуре, — не платить эксплуатацией за возможности, которыми не пользуешься.