Модуль 21. Kubernetes Networking
В Kubernetes сеть — это три плоскости:
- Pod ↔ Pod (E-W, east–west) внутри кластера: за это отвечает CNI-плагин (подсети PodCIDR, маршрутизация/оверлей, NetworkPolicy, иногда L4/L7).
- Клиенты ↔ сервисы (N-S, north–south): публикация через Service/Ingress/Gateway API (иногда с внешним LB/MetalLB/edge-прокси).
- Pod ↔ внешние системы (egress): SNAT с узла/через egress-шлюз/через корпоративный прокси, политики egress/FQDN.
«Единые правила»:
- Каждый Pod получает уникальный IP (адресуемость без NAT внутри кластера).
- Service — стабильная точка доступа (ClusterIP/NodePort/LoadBalancer/Headless).
- NetworkPolicy изолирует трафик на L3/4 (некоторые CNI дают L7).
- DNS (CoreDNS) — сервис-дискавери (*.svc.cluster.local, SRV/Headless).
Планирование подсетей и dataplane
- Pod CIDR и Service CIDR не должны пересекаться между собой и с вашей «подложкой» (underlay).
- Подумайте о dual-stack (IPv4/IPv6) — полезно для будущей совместимости, но усложняет диагностику.
- MTU: если у вас оверлей (VXLAN/Geneve), MTU у Pod интерфейсов должна учитывать инкапсулы (часто 1450 вместо 1500). Несогласованная MTU = скрытые потери/таймауты.
-
kube-proxy dataplane:
- iptables — просто, но хуже масштабируемость.
- IPVS — лучше при тысячах сервисов/эндпоинтов.
- eBPF (в Cilium/Calico eBPF-режиме) — самый быстрый dataplane, может заменить kube-proxy полностью.
CNI-плагины: сравнение и выбор
Flannel
- Что это: простой оверлей (VXLAN/host-gw).
- Плюсы: минимальная сложность, быстрый старт, мало «магии».
- Минусы: базовая функциональность, NetworkPolicy нет (если отдельно не ставить Calico-policy). Не лучший выбор для мульти-тенант/безопасных сред.
Calico
- Что это: маршрутизация (BGP/overlay), NetworkPolicy L3/L4, есть eBPF-режим, Typha для масштабов, Egress Gateway, HostEndpoint-политики.
- Плюсы: гибкость (overlay или BGP до ToR), зрелые политики, хорошие инструменты для крупной on-prem-сети.
- Минусы: BGP требует сетевой компетенции; eBPF-режим — внимательно к совместимости ядра.
Cilium
- Что это: eBPF-dataplane, NetworkPolicy L3–L7, замена kube-proxy, Hubble (наблюдаемость потоков), ClusterMesh (мультикластер), Egress Gateway/FQDN-policy.
- Плюсы: высокая производительность, глубокая наблюдаемость, L7-политики, современный стек.
- Минусы: зависимость от возможностей ядра, внимательность при апгрейдах.
Выбор по задачам:
- Малый/средний кластер без сложной безопасности → Flannel/Calico (overlay).
- Крупный on-prem, дружим с сетью → Calico с BGP (или eBPF).
- Нужны L7-политики/observability/без kube-proxy → Cilium.
Service Types: как правильно публиковать
- ClusterIP — доступ внутри кластера. По умолчанию.
- Headless (ClusterIP: None) — без kube-proxy, DNS возвращает реальные Pod IP (нужно для stateful, шардов, gRPC, ClickHouse/Trino workers).
- NodePort — пробрасывает порт на все ноды. Просто, но: ограниченный порт-диапазон, hairpin-NAT/маскарад, часто нужен внешний L4/L7 поверх.
- LoadBalancer — облачный балансировщик (в on-prem — MetalLB или сетевой LB).
- ExternalName — CNAME на внешний FQDN (не проксирует трафик).
Важные параметры:
- externalTrafficPolicy: Local — исходный client IP сохраняется (важно для GeoIP/логов), но трафик придёт только на ноды с живыми эндпоинтами.
- sessionAffinity — «прилипание» по source IP (аккуратно с NAT).
- EndpointSlice — масштабируемая замена Endpoints; проверьте, что включена (обычно по умолчанию).
Ingress vs Gateway API
Ingress
- Объект L7 HTTP/HTTPS-публикации, «один контроллер — много Ingress».
- Плюсы: простой ресурс, «де-факто стандарт» много лет, масса аннотаций (nginx/traefik/haproxy).
- Минусы: перегружен аннотациями, ограничен HTTP/S; TCP/UDP — отдельные CRD у контроллера.
Gateway API (современная модель)
- Ресурсы: Gateway (плоскость данных/точка входа), HTTPRoute/TCPRoute/UDPRoute/TLSRoute (правила маршрутизации), GatewayClass (реализация).
- Плюсы: более чёткое разделение ролей (платформа/приложение), мульти-провайдерный подход, явная поддержка TCP/UDP/TLS, масштабируемая делегация прав.
- Минусы: молодая экосистема (хотя уже зрелая у основных провайдеров).
Практика: если стартуете с нуля — планируйте Gateway API, но в проде часто используется гибрид: Ingress (историка) + Gateway API (новые сервисы).
DNS в Kubernetes (CoreDNS)
- CoreDNS обслуживает *.svc.cluster.local, *.pod.cluster.local, резолвит Headless сервисы по Pod-IP, создаёт SRV-записи.
- NodeLocal DNSCache снижает латентность DNS и сетевой шум (особенно при большом QPS).
- Stub-domains/forwarders — проксирование внутренних доменов (corp.local) на внешние DNS.
- dnsConfig в Pod — точечные search/servers/опции (не злоупотреблять).
- Важно: циклические форварды (CoreDNS ↔ внешние резолверы) и «задушенные» UDP-пакеты (MTU/firewall) создают призрачные таймауты.
Мини-фрагмент (идея NodeLocalDNS/форвардов — не копируйте без адаптации):
# CoreDNS: форвард внешних доменов forward corp.local 10.10.10.10
Egress: выход из кластера
Варианты SNAT:
- Masquerade с узла: дефолт — просто, но Pod IP «утекают» в логи/ACL и сложно «пофильтровать» по приложениям.
- Egress Gateway/Policies (Calico/Cilium): трафик из выбранных Pod/Namespace уходит через выделенный egress-узел/IP, удобно для firewall/allowlist.
- Корпоративный HTTP(S)/SOCKS прокси — полезно для интернета, но не для всех протоколов.
- Вендорские фичи (EgressIP/OpenShift и аналоги) — закрепить исходящий IP за namespace/подмножеством.
Политики egress:
- Базово — default-deny egress + явные разрешения (CIDR/FQDN/порт).
- FQDN-policy (в Cilium/Calico FQDN) — динамически разрешает IP из DNS-ответов (учитывайте TTL).
- Для облаков — используйте VPC endpoints/PrivateLink к S3/регистрам, чтобы не гонять в интернет.
Риски и анти-паттерны
|
Риск |
Симптомы |
Как избежать |
|---|---|---|
|
Утечки IP (Pod-IP видны снаружи, «серые» адреса в логах) |
Нарушение сегментации, неожиданные ACL-блоки |
Egress через шлюз/выделенный IP, SNAT/маскарад, не анонсируйте PodCIDR наружу |
|
Неправильная маршрутизация (асимметрия) |
«Плавающие» timeouts, часть запросов «пропадает» |
Согласуйте BGP/маршруты, используйте Local/Cluster policy осознанно, проверяйте обратные маршруты |
|
MTU несогласована |
Пакеты > MTU теряются, странные таймауты |
Установите MTU в CNI под underlay-значение минус overhead; проверьте ping DF |
|
conntrack overflow |
5xx/таймауты под нагрузкой |
Увеличьте nf_conntrack_max, сократите idle-таймауты, включите IPVS/eBPF |
|
kube-proxy масштаб не тянет |
Высокая латентность сервисов при тысячах эндпоинтов |
IPVS или eBPF dataplane, EndpointSlice, уменьшить «шумные» сервисы |
|
«Дыры» в NetworkPolicy |
«Всё всем доступно» |
default-deny + allow-лист, покрытие egress/ingress, тесты пингами/сканерами |
|
DNS петли/узкие места |
Периодические резолв-таймауты |
NodeLocal DNS, корректный форвардинг, без циклов и огромных search-доменов |
Практика (лабораторка с проверками)
Шаг 1. Выбор CNI и базовые тесты
- Разверните Calico или Cilium.
- Проверка E-W: Pod из ns-a видит Pod в ns-b.
- Создайте default-deny в обоих ns и разрешите только нужное.
Пример (идейный) NetworkPolicy default-deny + allow DNS:
# default-deny
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata: {name: deny-all, namespace: team-a}
spec: {podSelector: {}, policyTypes: ["Ingress","Egress"]}
# allow DNS + intra-namespace
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata: {name: allow-dns-and-same-ns, namespace: team-a}
spec:
podSelector: {}
egress:
- to: [{namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: kube-system}}}]
ports: [{protocol: UDP, port: 53}, {protocol: TCP, port: 53}]
- to: [{namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: team-a}}}]
ingress:
- from: [{namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: team-a}}}]
Шаг 2. Публикация сервиса
- Создайте Headless Service для stateful-компонента, убедитесь, что DNS выдает Pod-IP и SRV-записи.
- Поднимите Ingress (nginx/traefik) или Gateway API; проверьте TLS (cert-manager), externalTrafficPolicy: Local (если нужен реальный клиент IP).
Шаг 3. Egress-паттерн
- Включите Egress Gateway (Calico/Cilium) для ns-a на отдельный egress-узел/IP. Убедитесь, что внешний мир видит именно его IP.
- Если нельзя — настройте SNAT с нод и проверьте ACL/failover.
Шаг 4. DNS-устойчивость
- Включите NodeLocal DNSCache, измерьте p95 резолва до/после (synthetic checks).
- Настройте форвард внутренних доменов (corp.local) в CoreDNS и проверьте отсутствие циклов.
Шаг 5. Тест MTU/conntrack
- ping -M do -s <size> между Pod (чтобы найти безопасный payload).
- Снимите nf_conntrack_count/max под нагрузкой, внесите пороги-алерты.
Чек-лист «готово к продакшену (сеть)»
- Подсети PodCIDR/ServiceCIDR спланированы, не пересекаются.
- CNI выбран (Calico/Cilium/Flannel) и соответствует требованиям безопасности/масштаба.
- MTU согласована (overlay/underlay), тест DF прошёл.
- kube-proxy в IPVS или eBPF-dataplane при большом числе сервисов; EndpointSlice включен.
- NetworkPolicy: default-deny + минимально необходимые allow; покрыт egress.
- Ingress/Gateway API развёрнуты, TLS (cert-manager), externalTrafficPolicy выставлен осознанно.
- Egress: SNAT или egress-шлюз, FQDN-policy (если нужно), VPC endpoints к S3/регистрам.
- DNS: CoreDNS + NodeLocal DNSCache, корректные форварды, мониторинг резолв-латентности.
- Алерты: conntrack, p95 latency сервисов, поды/эндпоинты без бэкендов, MTU-ошибки (drop), проблемы health-checks у LB.
- Runbook’и: «утечка IP», «Conntrack overflow», «MTU mismatch», «Ingress 5xx/таймауты», «DNS деградация».
Вопрос-ответ
В: Что выбрать: Ingress или Gateway API?
О: Если у вас зелёныйfield — берите Gateway API: он чище по ролям, поддерживает TCP/UDP/TLS, удобнее для делегации. Если много исторического Ingress — живите в гибриде и мигрируйте постепенно.
В: Calico или Cilium?
О: Для on-prem и дружбы с сетью (BGP) — Calico. Если хотите eBPF-dataplane, богатые L7-политики и Hubble — Cilium. По производительности оба отличные; смотрите на компетенции команды и требования.
В: Как сохранить реальный IP клиента в логах?
О: externalTrafficPolicy: Local + корректные X-Forwarded-For/proxy-protocol в Ingress/LB. Учтите, что Local требует, чтобы бэкенд был на той же ноде, куда пришёл трафик.
В: Нужны ли Headless-сервисы?
О: Да, для stateful/шардированных систем (PG реплики, ClickHouse, Kafka, Trino workers). Они дают прямой доступ к Pod-IP и SRV-записи.
В: Как «закрыть» исходящий трафик?
О: Делайте default-deny egress, разрешайте по FQDN/CIDR/портам, используйте egress-шлюз/выделенный IP и VPC endpoints к облачным сервисам.
В: Почему у меня «периодические» таймауты HTTP?
О: Чаще всего MTU/фрагментация, conntrack overflows, асимметрия роутинга или DNS-петли. Пройдитесь по чек-листу: MTU ping DF, conntrack метрики, маршруты, NodeLocal DNS.
В: Что лучше: LB в облаке или MetalLB on-prem?
О: В облаке — нативный LoadBalancer. On-prem — MetalLB (L2/BGP) или внешний сетевой LB (F5/HAProxy/NGINX Plus) + Ingress.
В: Как проверить, что NetworkPolicy реально работает?
О: Поставьте тестовый Pod (netshoot/амбасадор) и пробуйте соединения в/из разных ns. Добавьте автоматы (e2e-тесты политики) в CI.
Сеть в Kubernetes — это не «одна галочка CNI». Это согласованные решения про CIDR/MTU/dataplane, публикацию сервисов (Service/Ingress/Gateway), строгие NetworkPolicy, устойчивый DNS, и управляемый egress без утечек IP. Если вы выбрали правильный CNI, включили default-deny, осознанно опубликовали сервисы, настроили NodeLocal DNS, egress-шлюз и алерты на conntrack/MTU — у вас будет стабильная, предсказуемая сеть, которая масштабируется вместе с продуктом.



