Привет, Хабр! Мы в команде Nova Container Platform сделали перевод статьи для тех, кто хочет разобраться, как строить сети в Kubernetes. Делюсь им, надеюсь, вам будет полезно.

В мире Kubernetes мы каждый день слышим, как ipvs сравнивают с iptables, или, скажем, pureLB с metalLB, или же виртуальную топологию (overlay) с физической (underlay), или Nodeport с Loadbalance, и т.д. Сейчас я вам все растолкую.

А вы знаете ответы на эти вопросы?

Как управлять всеми сетевыми параметрами?

Как pureLB подключается к CNI?

Как сервис ClusterIP подключается к IPVS?

Почему, используя Nodeport, я не вижу открытый порт через netstat?

Даже если да, я, пожалуй, продолжу и, поверьте, найду, чем вас удивить.

Обзор всего, везде и сразу

Конечно, непросто в одном месте собрать полезную информацию сразу с двадцати веб-сайтов и статей, но все же я постарался, дабы облегчить вам жизнь.

Я расскажу, как все эти штуки связаны с Kubernetes и как они интегрируются. Вот вам много знакомых и не очень слов на английском: Load-balance, ipvs, iptables, BGP, bridge, CNI, PureLB, endpoint, svc, overlay, underlay, ipip, kube-proxy, ingress controller.

Давайте быстро пройдемся по каждому: 

1. Как связаны между собой плагин CNI (Container Network Interface), контроллер балансировщика нагрузки (LB controller) и сетевой прокси (Kube-proxy)

CNI: конфигурирует сеть Kubernetes, создавая и настраивая сетевой интерфейс для каждого контейнера. Агент Kubelet вызывает CNI, чтобы настроить сетевые интерфейсы и назначить им IP-адреса.

CNI работает по двум моделям:

  • Инкапсулированная (виртуальная топология, overlay)

  • Неинкапсулированная (физическая топология, underlay)

Инкапсулированная: представлена технологиями VXLAN и IPSEC. Реализует проброс L2 поверх L3 на несколько узлов Kubernetes. Уровень L2 изолирован, так что распределять маршруты не нужно. Создается IP-заголовок, который предоставляет IP-пакет. Эта модель создает мост, соединяющий рабочие узлы и поды (pods). Управление соединениями реализуется через CRI (Container Runtime Interface).

Неинкапсулированная: маршрутизирует пакеты между контейнерами на L3. Рабочие узлы нужны, чтобы управлять распределением маршрутов с помощью BGP и, как следствие, распределять имеющуюся у подов информацию о маршрутизации. Эта модель подразумевает реализацию сетевого маршрутизатора на нескольких рабочих узлах.

CNI может использовать обе архитектуры.

Контроллер балансировщика нагрузки: MetalLB, PureLB…  работает в Kubernetes как сервис типа LoadBalancer (балансировщик нагрузки).

При создании сервиса балансировщика нагрузки (LB) назначенный внешний IP-адрес будет создан как вторичный адрес для основного интерфейса, что позволит маршрутизатору BGP BIRD захватывать IP-адреса и добавлять маршруты, адреса и прочие настройки.

Когда назначен новый IP-адрес:

В случае виртуальной сети будут применяться IPVS или iptables.

В случае физической сети дополнительно будет применяться еще и таблица маршрутизации.

Kube-proxy: задает сетевые правила в iptables, ipvs…

Kube-proxy добавляет сетевые политики, трансляцию сетевых адресов (NAT), правила переадресации и т.п.

Вот вам простой пример:

Когда вы создаете svc, kube-proxy добавляет правила в iptables.

Кстати, netfilter можно заменить на EBPF, а IPtables – на IPVS.

Итак, резюмируем:

  • Kube-proxy: задает сетевые правила в IPTABLES, IPVS и т.д.

  • CNI: предоставляет общий интерфейс для базовых сетей, маршрутизирует трафик до мест назначения и выполняет другие сопутствующие функции.

  • Контроллер балансировщика нагрузки: балансирует нагрузку и обновляет интерфейс хоста для добавления вторичных IP-адресов.

2. С пода на под / из контейнера в контейнер – одноузловая конфигурация (на базе IP-адреса)

Через среду выполнения контейнеров, например containerd, CRI-O или Mirantis, создается пользовательский мост (CBR), Veth (виртуальный Ethernet), Ethernet (eth), и задаются все сетевые параметры. Большинство интерфейсов сред выполнения контейнеров (CRI) используют для этого плагины CNI, в том числе опции Calico, Flannel и Cilium.

Все контейнеры внутри пода используют одну и ту же сеть, поскольку находятся внутри одного и того же пространства сетевых имен.

Контейнер pause отвечает за сетевые соединения и межпроцессное взаимодействие (IPC) в Kubernetes.

Виртуальное устройство Veth будет создано под CBR для каждого пода, и L2-маршрутизация будет идти по этому мосту. Например, пакеты из под1 в под2 идут через CBR, а NAT в этом случае не используется.

3. С пода на под / из контейнера в контейнер – многоузловые конфигурации (на базе IP-адреса)

Как IP-адрес пода маршрутизируется по сети узлов?

  • Оба узла находятся в одной и той же сети, т.е. могут видеть друг друга;

  • CNI создает на каждом узле маршрут к каждому поду.

Поскольку на CBR в узле-1 нет MAC-адреса пода4, пакеты идут через интерфейс, указанный в таблице маршрутизации. Это может быть туннель, другой интерфейс, eth0 или... На самом деле все зависит от структуры.

У каждого узла в Kubernetes есть свой собственный метод бесклассовой адресации (CIDR), который позволяет маршрутизировать трафик на правильный узел.

4. С пода на под / из контейнера в контейнер – многоузловые конфигурации (на базе IP-адреса службы)

В случае служб ключевую роль играет IPTABLES/IPVS. В Netfilter IP-адрес службы произвольно изменится на IP-адрес связанного пода (по алгоритму балансировки нагрузки). Kube-proxy отвечает за актуализацию правил Netfilter и назначение IP-адресов подов службам.

Когда узел получает пакет, предназначенный для svc, в Netfilter правила сопоставляются со службой, а пакет маршрутизируется на IP-адрес пода назначения.

Но как?

Службы обновляют совокупности конечных точек (endpoint slices) IP-адресами подов, сопоставляя метки подов, указанные в селекторе службы. Когда селектор сопоставляет метки подов, соответствующая информация (IP-адреса, порты, протоколы и пр.) извлекается и вставляется в совокупность конечных точек (endpoint slice), ассоциированную со службой.

Помните, что службы, конечные точки, Nodeports и LB – всего лишь правила в IPTABLES/IPVS.

Что произойдет, если вызвать службу по имени? До сих пор мы упоминали лишь маршрутизацию по IP-адресу.

В Kubernetes есть DNS-сервер, обычно CoreDNS или KubeDNS.

DNS-под видится извне как служба kubernetes со статическим IP-адресом кластера, парсинг которого до каждого контейнера выполняется при запуске.

Теперь все просто: имена будут разрешаться внутри контейнеров DNS-сервером Kubernetes.

Готовы увидеть все, везде и сразу? Самое время

Это реализация CNI (Calico), IPVS, PURELB, IPIP (виртуальная сеть) и ingress-контроллера – все вместе на одной картинке (вместе с ролями).
Это реализация CNI (Calico), IPVS, PURELB, IPIP (виртуальная сеть) и ingress-контроллера – все вместе на одной картинке (вместе с ролями).

Calico: Все сетевое взаимодействие выполняется через Calico, виртуальную (IPIP) и физическую (BGP) сети.

  • Как я писал выше, IP-адреса всех подов назначаются мосту CBR, чьи функции в данном случае выполняет интерфейс моста kube-ipvs;

  • У каждого пода есть свой собственный виртуальный интерфейс;

  • tunl0 (IPIP) – виртуальный интерфейс, который соединяет узлы друг с другом в архитектуре виртуальной сети. Иными словами, все IP-адреса пода проходят через этот туннель;

  • PureLB - контроллер балансировщика нагрузки, который также управляет сетью хоста, реализуя kube-lb0 как виртуальный интерфейс, и добавляет IP-адреса балансировщика нагрузки в основной интерфейс хоста в качестве вторичных IP-адресов;

  • PureLB также совместим с протоколами маршрутизации с BGP, OSPF… Поскольку у нас маршрутизатор BGP BIRD уже реализован с помощью Calico, PureLB понимает это и не будет создавать другой маршрутизатор BGP;

  • BGP захватывает все IP-адреса, назначенные интерфейсам, и задает маршрут к ним в таблице маршрутизации.

До тех пор, пока пакет из пода 1 не захочет попасть в под 5 в другом узле, kube-ipvs не сможет выдать в ответ то, чего сам не знает, так что следующий уровень – это таблица маршрутизации, обновленная с помощью BGP. Маршрутизация до места назначения будет выполняться через интерфейс tunl0, потому что у нас архитектура виртуальной сети. Если вызвать службу, то в игру вступят правила ipvs.

Теперь мы знаем, что конечные точки, службы, Nodeports и LB – всего лишь правила в IPVS. Давайте это запомним:

У нас есть служба типа LoadBalancer для нашего ingress-контроллера, а это значит, что ingress доступен извне. Когда мы вызываем этот IP-адрес, пакеты направляются на нужный узел, и потом IPVS переадресует их на NodePort (NAT) для маршрутизации между узлами и поиска правильного узла.

Затем NodePort ассоциируется с ClusterIP, который знает IP-адреса подов ingress-контроллера. Это полезная настройка, потому что, как только ingress-контроллер получает пакет, он по заданным правилам маршрутизирует его на нужную службу и потом на под назначения.

В этой статье я ставил себе целью не дать исчерпывающее объяснение по каждому компоненту, а собрать в одном месте информацию для тех, кто уже в теме.

Я брал информацию из нескольких источников. Вот ссылки на них:

https://medium.com/thermokline/comparing-k8s-load-balancers-2f5c76ea8f31 

https://medium.com/@seifeddinerajhi/kube-proxy-and-cni-the-hidden-components-of-kubernetes-networking-eb30000bf87a 

https://docs.tigera.io/calico/latest/networking/ 

https://purelb.gitlab.io/docs/how_it_works/overview/ 

Комментарии (0)