Давайте дружить в Телеграме: рассказываем про новые фичи, общаемся в комментах, прислушиваемся к вашим идеям Подписаться

Как отследить pod-to-pod-трафик Kubernetes

Роман Андреев
Роман Андреев
Технический писатель
29 января 2024 г.
37
7 минут чтения
Средний рейтинг статьи: 5

Эта статья для тех, кто ищет простое и понятное введение в организацию и управление кластерами Kubernetes или же хочет оптимизировать свой проект. Мы поговорим о тонкостях сетевых технологий Kubernetes и рассмотрим некоторые принципы и те механизмы, которые управляют взаимодействием между подами. Сетевую модель мы будем рассматривать, используя схему VirtualBox. Изучив настройки этого решения, предлагаемого пользователям по умолчанию, вы получите ясное представление о том, как осуществляется связь между подами в среде Kubernetes и сможете применить полученные знания на практике, так всё написанное будет подкреплено примерами. Но сначала немного теории.

Два стандарта Kubernetes

Вместо жесткой сетевой реализации в Kubernetes используются стандарты CRI и CNI, предлагающие собственные плагины с множеством вариантов настройки кластера Kubernetes. Таким образом вместо единого инфраструктурного решения предлагается весьма широкий набор альтернативных. И каждое такое решение позволяет реализовать уникальную структуру кластерной сети. Это позволяет выбрать тот подход, который лучше всего соответствует вашим требованиям с учетом масштабируемости, производительности, отказоустойчивости, а также совместимости с вашей инфраструктурой. Конечно, такая вариативность несет с собой и ряд проблем с конкретными сетевыми решениями. Но при правильной настройке вы обеспечите оптимальную производительность своей сети, надежную связь и удобное управление своими кластерами.

Добавим, что оба стандарта предлагают несколько популярных решений. Если говорить о CRI, то это прежде всего containerd и cri-o, а у CNI есть Calico и Flannel. Все они предоставляют необходимые функции для сред выполнения контейнеров, позволяя вам выбирать параметры, которые лучше всего соответствуют вашим требованиям и предпочтениям. При этом данные плагины чаще всего не исключают, а дополняют друг друга. Разумеется, такие сочетания требуют некоторых усилий в плане конфигурирования, чтобы гарантировать стабильную работу всей сборки. И эту задачу существенно облегчают дистрибутивы, в которых чаще всего плагины CRI и CNI уже настроены должным образом для того, чтобы пользователь мог сразу же приступить непосредственно к настройке приложений Kubernetes.

Из платных дистрибутивов можно отметить, например, Red Hat Openshift, но есть и достаточно функциональные бесплатные продукты, и прежде всего это OKD, minikube, а также areguera-k8s-lab, на примере которого мы и будем учиться отслеживать межподовый трафик.

О кластерной архитектуре

В vagrant-k8-lab вшиты containerd и Flannel на каждой ноде, что обеспечивает такую структуру:

Image4

Источник изображения: medium.com

Здесь следует отметить, что к каждому узлу в данном случае подключено сразу 4 интерфейса, eth0, eth1, cni0 и lo. Каждый из них имеет свою цель, и сейчас мы их подробно разберем. А еще вы наверняка заметили, что в кластере уже развернуты несколько подов, которые также понадобятся нам для проведения последующих тестов.

Трафик нода-интернет, eth0

Чтобы иметь возможность загружать образы контейнеров извне, плагину CRI требуется исходящий трафик. Менеджеру пакетов ОС также нужно получать доступ к удаленным репозиториям. Когда ноды Kubernetes развертываются с помощью VirtualBox, то eth0 там подключается по умолчанию в режиме NAT. Гостевая ОС получает IP 10.0.2.15 и обменивается данными с VirtualBox через IP 10.0.2.3. Это настройки по умолчанию, которые обеспечивают взаимодействие виртуальных машин с «внешним миром» при условии, что у хоста с работающим VirtualBox, есть необходимое подключение. Вот как это выглядит схематично:

Image3

Источник изображения: medium.com

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

В сетевой схеме VirtualBox по умолчанию соединения между виртуальными машинами обрабатываются индивидуально. Каждая виртуальная машина подключена к собственной изолированной сети 10.0.2.0/24 внутри VirtualBox, используя уникальный виртуальный канал для каждой внутренней сети. Таким образом, виртуальные машины взаимодействуют с внешним миром, но не могут взаимодействовать между собой.

Теперь давайте создадим под с использованием образа:

[vagrant@node-1 ~]$ kubectl run nginx --image=nginx:latest

Затем посмотрим на его статус:

[vagrant@node-1 ~]$ kubectl get pods/nginx
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          10m

Если статус Running, значит, всё в порядке и под активен на ноде 1, если, конечно, эта нода была выбрана в планировщике Kubernetes. Чтобы проверить это, вводим последовательно:

[vagrant@node-1 ~]$ kubectl describe pods/nginx
[vagrant@node-1 ~]$ journalctl -f -u containerd

Трафик нода-нода, eth1

Для подключения нод к одному внешнему каналу необходимо их прямое соединение. Поэтому eth0 не подходит для этой цели, и нужно использовать другой тип сетевого подключения. Здесь нас выручает eth1, и реализуется вот такая простая и эффективная схема:

Image5

Источник изображения: medium.com

Как видим, для каждой ноды задан свой IP в определенном диапазоне, начиная с 192.168.56.10/24 для главной, 192.168.56.11/24 для первой рабочей ноды и 192.168.56.12/24 — для второй.

Теперь давайте проверим параметры подключения для обеих рабочих нод (в терминологии Kubernetes они называются workers), последовательно вводя следующие команды:

[vagrant@controlplane ~]$ traceroute -n 192.168.56.11
[vagrant@controlplane ~]$ traceroute -n 192.168.56.12

В случае успешного подключения вы увидите количество переданных пакетов и время их передачи в миллисекундах.

Трафик между подами в пределах одной ноды, cni0

Межподовый трафик возникает при запуске приложений Kubernetes на одном узле. В этом случае подам для обмена данными необходимо иметь уникальные IP. При этом вы знаете, что поды имеют определенный срок существования и уничтожаются так же легко, как и создаются. Это реализуется с помощью плагина CNI, а схематично выглядит так:

Image1

Источник изображения: medium.com

Теперь давайте создадим под из образа:

[vagrant@node-1 ~]$ kubectl run httpd --image=httpd

Далее нам нужно узнать IP созданного пода, что делается при помощи:

[vagrant@controlplane ~]$ kubectl get pods -o wide

Теперь через образ busybox мы создаем новый под, подставив вместо IP полученное значение:

[vagrant@node-1 ~]$ kubectl run traceroute --image=busybox -- traceroute IP

И, наконец, проверяем параметры подключения, введя следующую команду для вывода лога:

[vagrant@node-1 ~]$ kubectl logs traceroute

Если в логе будет указан только один переход при определении маршрутизации (traceroute), значит, мы имеем дело с cni0, то есть трафик между подами осуществляется в пределах одной ноды.

Межнодовый трафик pod-to-pod

Одноузловые кластеры Kubernetes хороши в тестировании, однако при использовании в реальных проектах они не обеспечивают должного уровня отказоустойчивости. Ведь стоит единственной ноде отключиться, как рушится и всё приложение. Поэтому разработчики создают многоузловые кластеры, в которых нагрузка между нодами нередко распределяется равномерно. Для этой цели используется плагин Flanel, обеспечивающий «умную» маршрутизацию трафика без необходимости контролировать процесс маршрутизации вручную. А вот как выглядит многоузловой кластер:

Image2

Источник изображения: medium.com

Создаем под из образа и при этом проверяем, что под будет размещен на соответствующей ноде (в нашем случае на первой рабочей):

[vagrant@controlplane ~]$ kubectl run httpd --image=httpd \
--overrides= '{"spec": { "nodeSelector": {"kubernetes.io/hostname": "node-1"}}}'

Далее вводим еще одну знакомую команду:

[vagrant@controlplane ~]$ kubectl get pods -o wide

Теперь, снова как в прошлом примере, через образ busybox мы создаем новый под, только на второй рабочей ноде, подставив вместо IP полученное значение:

[vagrant@controlplane ~]$ kubectl run traceroute --image=busybox \
--overrides='{"spec": { "nodeSelector": {"kubernetes.io/hostname": "node-2"}}}' \
-- traceroute IP

И в завершение выполняем команду для отслеживания маршрутизации:

[vagrant@controlplane ~]$ kubectl logs traceroute

Если всё работает корректно, то мы увидим 3 перехода, соответствующие схеме cni0-eth1-cni0.

Заключение

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

Зарегистрируйтесь и начните пользоваться
сервисами Timeweb Cloud прямо сейчас

15 лет опыта
Сосредоточьтесь на своей работе: об остальном позаботимся мы
165 000 клиентов
Нам доверяют частные лица и компании, от небольших фирм до корпораций
Поддержка 24/7
100+ специалистов поддержки, готовых помочь в чате, тикете и по телефону