Сеть и балансировщик нагрузки Kubernetes

В этой статье описана сетевая модель и принципы работы Kubernetes-сети. Также рассмотрено создание Kubernetes-балансировщиков для доступа к приложениям.

Если вы не знакомы с понятиями сервисов и подов (единиц развертывания) – начните со статьи “Основы Kubernetes”.

Сетевая модель кластера

В кластере Kubernetes каждый под получает собственный IP-адрес (идентификатор устройства в компьютерной сети) из диапазона Pod CIDR (бесклассовая междоменная маршрутизация), заданного при создании кластера. Поды могут обращаться друг к другу напрямую по IP-адресам, независимо от того, на какой ноде (группе серверов) они работают.

Для стабильного доступа к группе подов используются сервисы – они предоставляют постоянный адрес и распределяют трафик между подами.

Типы сервисов

  • ClusterIP – доступен только внутри кластера. Сервис получает виртуальный IP-адрес из диапазона адресов сервисов. Используется для связи между компонентами приложения.
  • NodePort – открывает фиксированный порт на каждой ноде кластера. Трафик, поступающий на этот порт, перенаправляется к подам сервиса.
  • LoadBalancer – создает балансировщик нагрузки на стороне платформы. Подходит для предоставления доступа к приложению извне.

Создание сервиса ClusterIP

ClusterIP – тип сервиса по умолчанию. Он предоставляет стабильный внутренний адрес для группы подов, доступный только изнутри кластера. Используйте его для связи между компонентами приложения – например, чтобы frontend (внешний интерфейс) обращался к backend (серверная часть) по фиксированному имени.

apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: default
spec:
  selector:
    app: backend
  ports:
  - port: 8080
    targetPort: 8080
  type: ClusterIP

После применения манифеста сервис будет доступен внутри кластера по имени backend (или полному DNS-имени (от англ. Domain Name System – система доменных имен) backend.default.svc.cluster.local) и по выделенному ClusterIP:

kubectl apply -f backend-service.yaml
kubectl get svc backend

NAME      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
backend   ClusterIP   10.96.45.12    <none>        8080/TCP   5s

Другие поды в кластере могут обращаться к этому сервису по имени:

http://backend:8080

Создание сервиса NodePort

NodePort открывает фиксированный порт (из диапазона 30000–32767) на каждой ноде кластера. Трафик, поступающий на этот порт любой ноды, перенаправляется к подам сервиса.

apiVersion: v1
kind: Service
metadata:
  name: frontend
  namespace: default
spec:
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

После применения сервис будет доступен на порту 30080 каждой ноды кластера:

kubectl apply -f frontend-nodeport.yaml
kubectl get svc frontend

NAME       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
frontend   NodePort   10.96.78.90    <none>        80:30080/TCP   5s
Обратите внимание!
Для production-нагрузок (рабочих нагрузок) рекомендуется использовать LoadBalancer вместо NodePort – он обеспечивает единую точку входа и распределение трафика.

Балансировщик нагрузки

Обратите внимание!
На время публичной бета-версии балансировщики нагрузки не тарифицируются.

При создании сервиса типа LoadBalancer платформа автоматически выделяет балансировщик, который распределяет входящий трафик между подами приложения.

Внешний и внутренний балансировщик

Тип балансировщика задается аннотацией lb.beget.com/type:

external – балансировщику назначается публичный IP-адрес, доступный из интернета. Подходит для:

  • Веб-сайтов и веб-приложений
  • Публичных API (интерфейсов программирования приложения)
  • Любых сервисов, к которым обращаются внешние пользователи

internal – балансировщик доступен только внутри приватной сети. Подходит для:

  • Внутренних API и межсервисного взаимодействия
  • Баз данных и других сервисов, которые не должны быть доступны извне
  • Компонентов, взаимодействующих только с другими сервисами в облаке

Создание внешнего балансировщика

Сохраните манифест в файл loadbalancer-external.yaml:

apiVersion: v1
kind: Service
metadata:
  annotations:
    lb.beget.com/algorithm: round_robin
    lb.beget.com/healthcheck-interval-seconds: "60"
    lb.beget.com/healthcheck-timeout-seconds: "5"
    lb.beget.com/type: external
  name: nginx
  namespace: default
spec:
  allocateLoadBalancerNodePorts: true
  ports:
  - port: 80
    targetPort: nginx
  selector:
    app: nginx
  type: LoadBalancer

Примените манифест:

kubectl apply -f loadbalancer-external.yaml

Создание внутреннего балансировщика

Сохраните манифест в файл loadbalancer-internal.yaml:

apiVersion: v1
kind: Service
metadata:
  annotations:
    lb.beget.com/algorithm: round_robin
    lb.beget.com/healthcheck-interval-seconds: "60"
    lb.beget.com/healthcheck-timeout-seconds: "5"
    lb.beget.com/type: internal
  name: internal-api
  namespace: default
spec:
  allocateLoadBalancerNodePorts: true
  ports:
  - port: 8080
    targetPort: api
  selector:
    app: internal-api
  type: LoadBalancer

Примените манифест:

kubectl apply -f loadbalancer-internal.yaml

Аннотации балансировщика

Управление параметрами балансировщика выполняется через аннотации в поле metadata.annotations манифеста.

Тип балансировщика

  • lb.beget.com/type – значения: external, internal. Тип балансировщика: публичный или приватный

Алгоритм балансировки

  • lb.beget.com/algorithm – значения: round_robin, least_connections. Алгоритм распределения трафика между подами

Проверки работоспособности (healthcheck)

Healthcheck-аннотации определяют, как балансировщик проверяет доступность backend-сервисов. Если сервис не отвечает в пределах тайм-аута, балансировщик перестает направлять на него трафик до восстановления.

  • lb.beget.com/healthcheck-interval-seconds – положительное целое число. Интервал между проверками (в секундах). По умолчанию – 5.
  • lb.beget.com/healthcheck-timeout-seconds – положительное целое число. Тайм-аут ожидания ответа (в секундах). По умолчанию – 30.

Проверка статуса балансировщика

После применения манифеста убедитесь, что балансировщик создан и получил адрес:

kubectl get svc <имя-сервиса>

Вместо <имя-сервиса> укажите имя из поля metadata.name вашего манифеста. В нашем примере это nginx:

Ожидаемый вывод для внешнего балансировщика:

NAME    TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
nginx   LoadBalancer   10.96.162.132   155.212.142.254   80:31160/TCP   10s
  • CLUSTER-IP – внутренний адрес сервиса в кластере
  • EXTERNAL-IP – адрес, по которому балансировщик доступен извне (для external) или внутри приватной сети (для internal)
  • PORT(S) – порт сервиса и назначенный NodePort

Если в колонке EXTERNAL-IP отображается <pending>, балансировщик еще создается. Повторите команду через некоторое время или используйте флаг --watch для отслеживания:

kubectl get svc nginx --watch

Обычно выделение IP-адреса занимает не более минуты. Если статус <pending> сохраняется дольше нескольких минут – проверьте события сервиса командой kubectl describe svc nginx.

Удаление балансировщика

Для удаления балансировщика удалите соответствующий сервис:

kubectl delete svc nginx

После удаления сервиса балансировщик на стороне платформы также будет удален, а выделенный IP-адрес освобожден.

Все статьи раздела

  1. Kubernetes (K8s) – обзор сервиса Managed Kubernetes (управляемый Kubernetes)
  2. Основы Kubernetes – ключевые понятия: кластер, ноды, поды, сервисы
  3. Создание и настройка кластера – конфигурация master-нод (узлов управляющего контура), сеть и worker-группы (групп узлов)
  4. Подключение к кластеру и работа с kubectl (консольный инструмент для управления Kubernetes) – kubeconfig (конфигурационный файл Kubernetes), подключение и первые команды
  5. Управление кластером – добавление нод, изменение конфигурации, обновление, удаление
  6. Сеть и балансировщик нагрузки – вы здесь
  7. Лимиты, квоты и ограничения – ограничения платформы, что можно и нельзя изменить

Если возникнут вопросы, напишите нам, пожалуйста, обращение в панели управления аккаунта (раздел “Помощь и поддержка”), а если вы захотите обсудить эту статью или наши продукты с коллегами по цеху и сотрудниками Beget – ждем вас в нашем сообществе в Telegram.