Связь между подами в Kubernetes
Одним из ключевых элементов Kubernetes является под - логическая группа из одного или нескольких тесно связанных контейнеров. Понимание того, как поды обмениваются данными друг с другом, критично, если вы хотите строить устойчивые и масштабируемые приложения в кластере Kubernetes. В этой заметке мы подробно разберёмся, как работает связь «pod-to-pod» и посмотрим на разные паттерны и техники взаимодействия.
Разбираемся в сетевом взаимодействии подов
В Kubernetes каждый под получает свой уникальный IP-адрес внутри кластера, что позволяет им общаться напрямую. По умолчанию под изолирован и обладает собственным IP, благодаря чему не возникает конфликтов портов, а обмен данными остаётся достаточно безопасным. Эти адреса доступны только внутри сетевого пространства кластера, если, конечно, вы специально не настраиваете доступ извне.
Модель сетей Kubernetes
Связь «pod-to-pod» на одном узле. Когда несколько подов запускаются на одном и том же узле, они могут взаимодействовать напрямую, используя localhost или loopback-интерфейс. На деле же обмен идёт через IP, который назначен поду в рамках кластера, обычно через пару виртуальных Ethernet-интерфейсов (veth). Всё это происходит на сетевом уровне, так что поды на одном узле получают быструю и низколатентную связь.
Связь «pod-to-pod» между разными узлами. Если подам нужно общаться между узлами, Kubernetes подключает сетевые решения вроде CNI и разные SDN-технологии. Они создают виртуальную сетевую «прослойку», которая охватывает весь кластер и делает возможным обмен данными между подами, где бы они ни находились. Среди популярных CNI можно назвать Calico, Flannel, Weave и Cilium. Эти решения гарантируют, что IP-адрес пода остаётся доступным и что сетевое взаимодействие выглядит прозрачным, независимо от того, на каком узле в итоге работает под.
Внутрикластерное взаимодействие
По умолчанию поды внутри кластера Kubernetes могут свободно общаться друг с другом, используя внутренние IP-адреса. Эта связь идёт через виртуальную сетевую прослойку, которую предоставляет контейнерный рантайм или сетевой плагин. Внутренние IP назначаются сетевым решением кластера и маршрутизируются только внутри него.
DNS-ориентированное обнаружение сервисов
Kubernetes из коробки предоставляет DNS-службу, которая помогает подам находить друг друга. Сервисы выступают стабильными точками входа и скрывают «живые» поды за собой. Каждый сервис получает DNS-имя, которое резолвится в IP адреса подов, стоящих за этим сервисом. Благодаря этому поды могут обращаться друг к другу по имени сервиса, не завязываясь на конкретные IP отдельных подов.
Балансировка нагрузки сервисами
Если несколько подов обслуживают одно и то же приложение, Kubernetes умеет распределять трафик между ними автоматически. Достаточно создать объект Service и связать его с нужными подами - дальше кластер сам равномерно раскидает входящие запросы. Такой механизм помогает приложению оставаться доступным и масштабируемым.
Сетевые политики
Kubernetes позволяет задавать сетевые политики, чтобы контролировать обмен данными между подами. Политики задают правила, определяющие, какие поды могут взаимодействовать друг с другом, основываясь на IP-адресах, портах или протоколах. Это позволяет сегментировать трафик приложения и добавлять ещё один уровень безопасности.
Внешние коммуникации
Поды нередко должны обращаться к внешним ресурсам - внешним сервисам, базам данных и т. д. Для этого Kubernetes предлагает несколько подходов. Можно «вытащить» под или группу подов наружу с помощью сервиса типа LoadBalancer или NodePort, чтобы к ним могли подключаться внешние клиенты. Другой вариант - использовать Ingress-контроллер, который направляет внешний трафик в нужные поды согласно заданным правилам.
Service Mesh
Для более продвинутых сетевых сценариев можно подключить service mesh - типа, Istio или Linkerd. Mesh работает поверх кластера и добавляет возможности вроде маршрутизации трафика, наблюдаемости и расширенной безопасности. С ним вы получаете тонкую настройку взаимодействия между подами: сложные правила маршрутизации, circuit breaking, распределённый трей싱 и многое другое.
Пример
Чтобы наглядно показать, как можно настроить связь между подами в Kubernetes, разберём простой пример. Мы создадим два пода и организуем взаимодействие между ними через сервис.
1.Создаём Pod A. Сначала подготовим Pod A с простым веб-приложением. Создайте файл pod-a.yaml и добавьте туда такой контент:
apiVersion: v1
kind: Pod
metadata:
name: pod-a
spec:
containers:
- name: web-app
image: your-web-app-image
ports:
- containerPort: 8080
Замените your-web-app-image на нужное вам изображение веб-приложения. Эта спецификация создаёт под с именем pod-a, запускает указанный контейнер и открывает порт 8080.
2.Создаём Pod B. Теперь подготовим Pod B — это будет клиент, который будет обращаться к Pod A. Создайте файл pod-b.yaml и добавьте туда такой контент:
apiVersion: v1
kind: Pod
metadata:
name: pod-b
spec:
containers:
- name: client-app
image: your-client-app-image
command: ["sleep", "infinity"]
Замените your-client-app-image на образ вашего клиентского приложения. Эта спецификация создаёт под pod-b и запускает контейнер, который просто спит бесконечно, чтобы под не завершался.
3.Создаём сервис. Чтобы Pod A и Pod B могли общаться, добавим сервис, который станет стабильной точкой входа. Создайте файл service.yaml и добавьте туда:
apiVersion: v1
kind: Service
metadata:
name: pod-service
spec:
selector:
app: web-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
Эта спецификация создаёт сервис pod-service, который выбирает поды с меткой app: web-app (её мы добавим в Pod A). Сервис слушает порт 80 и перенаправляет трафик на порт 8080 в выбранных подах.
4.Применяем конфигурации. Запустите созданные манифесты командами:
kubectl apply -f pod-a.yaml kubectl apply -f pod-b.yaml kubectl apply -f service.yaml
После этого в кластере появятся Pod A, Pod B и сервис.
5.Тестируем связь. Чтобы протестировать взаимодействие, зайдите в Pod B и отправьте запрос в Pod A через DNS-имя сервиса:
kubectl exec -it pod-b -- sh
Когда окажетесь в оболочке Pod B, можно воспользоваться, например, curl, чтобы отправить запрос. Если в манифесте сервиса вы указали другое имя — подставьте его:
curl pod-service
Команда отправит запрос в сервис, а тот распределит трафик и перенаправит его на Pod A.
На этом всё! Вы только что настроили связь между подами в Kubernetes через сервис. Дальше можно развивать пример: попробовать другие модели взаимодействия, добавить сетевые политики или подключить дополнительные возможности Kubernetes под ваши задачи.
