<div><img src="https://top-fwz1.mail.ru/counter?id=3548135;js=na" style="position:absolute;left:-9999px;" alt="Top.Mail.Ru" /></div>
Бесплатная миграция IT-инфраструктуры в облако
На главную
25eb9e0a-a5a8-472a-ace7-940b8bd2adf0
Облачные сервисы

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

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

Базовая конфигурация балансировщика нагрузки

Для создания балансировщика нагрузки в Kubernetes создадим ресурс типа Service с типом LoadBalancer. Пример базового манифеста:

apiVersion: v1
kind: Service
metadata:
  name: example-balancer
  namespace: kubernetes-dashboard
spec:
  selector:
    app.kubernetes.io/name: nginx
  ports:
    - port: 80            # Внешний порт для доступа к приложению
      targetPort: 80      # Порт пода, на который перенаправляется трафик
  type: LoadBalancer

В этом примере балансировщик будет перенаправлять трафик с порта 80 на порт 80 внутри подов, соответствующих селектору app.kubernetes.io/name: nginx.

Если вам нужно добавить несколько правил для балансировки, обязательно указывайте атрибут name для каждого порта:

apiVersion: v1
kind: Service
metadata:
  name: example-balancer
  namespace: kubernetes-dashboard
spec:
  selector:
    app.kubernetes.io/name: nginx
  ports:
    - port: 80
      targetPort: 80
      name: http
    - port: 443
      targetPort: 443
      name: https
  type: LoadBalancer

Значение атрибута name может быть произвольным.

После создания балансировщик будет отображаться в панели управления в разделе «Балансировщики».

Screenshot 11 07 24 12:37:19

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

В правилах балансировщика вы можете заметить, что порт, с которого выполняется балансировка, отличается от того, что был указан в Service. В правилах балансировщика будет указан NodePort.

Screenshot 11 13 24 18:07:32

NodePort — это специальный порт на каждом узле Kubernetes, который позволяет перенаправлять внешний трафик на конкретный сервис внутри кластера. Он служит промежуточным шагом между балансировщиком нагрузки и внутренними подами, чтобы связать внешний трафик с сервисом. Увидеть его можно, выполнив следующую команду:

kubectl describe service <имя_сервиса> -n <имя_неймспейса>

При создании сервиса с типом LoadBalancer, Kubernetes автоматически назначает NodePort, чтобы обеспечить возможность входящего трафика через узлы в кластере. Трафик, направляемый на этот порт на любом из узлов (в данном случае, например, 31154), будет перенаправляться к сервису, а затем — к целевым подам.

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

Для более гибкой настройки балансировщика нагрузки в Kubernetes можно использовать дополнительные параметры. Они указываются в виде меток (labels) в манифесте Service

Пример манифеста с дополнительными параметрами:

apiVersion: v1
kind: Service
metadata:
  name: example-balancer
  namespace: kubernetes-dashboard
  labels:
    k8s.timeweb.cloud/attached-loadbalancer-algo: "leastconn"    
    k8s.timeweb.cloud/attached-loadbalancer-ddos-guard-external-ip: "true" 
spec:
  selector:
    app.kubernetes.io/name: nginx
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

В этом примере задаются два дополнительных параметра:

  • k8s.timeweb.cloud/attached-loadbalancer-algo: алгоритм балансировки — leastconn (выбирает сервер с наименьшим числом активных подключений).
  • k8s.timeweb.cloud/attached-loadbalancer-ddos-guard-external-ip: выделяет балансировщику внешний IP с защитой от DDoS.

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

В таблице ниже перечислены доступные параметры для настройки балансировщика нагрузки. Каждый параметр задается в виде метки в манифесте Service:

Параметр

Назначение

k8s.timeweb.cloud/attached-loadbalancer-preset-id: "391"

Задает конфигурацию балансировщика. По умолчанию выбирается минимальная конфигурация для зоны. Получить id тарифов можно при помощи API.

k8s.timeweb.cloud/attached-loadbalancer-algo: "roundrobin"

Алгоритм балансировки: roundrobin или leastconn.

k8s.timeweb.cloud/attached-loadbalancer-healthcheck-check-interval: "10"

Интервал между проверками доступности (в секундах).

k8s.timeweb.cloud/attached-loadbalancer-healthcheck-timeout: "5"

Таймаут проверки доступности (в секундах).

k8s.timeweb.cloud/attached-loadbalancer-healthcheck-error-count: "3"

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

k8s.timeweb.cloud/attached-loadbalancer-healthcheck-recover-count: "2"

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

k8s.timeweb.cloud/attached-loadbalancer-no-external-ip: "true"

Отключение внешнего публичного IP для балансировщика.

k8s.timeweb.cloud/attached-loadbalancer-ddos-guard-external-ip: "true"

Выделение внешнего IP с защитой от DDoS.

k8s.timeweb.cloud/ignore-timeweb-cloud-loadbalancer: "true"

Исключает сервис из обработки балансировщиком Timeweb Cloud. Может быть полезно, если используется другой LoadBalancer, например, kube-vip или MetalLB.

Практический пример использования балансировщика

Для демонстрации работы балансировщика создадим два деплоймента Nginx, каждый из которых будет отображать свою HTML-страницу. Балансировщик случайным образом распределит запросы между подами, и в зависимости от этого будет показана одна из страниц.

Подготовка окружения

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

Выполните команду для создания неймспейса:

kubectl create namespace test-namespace

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

Создание ConfigMap для HTML-страниц

Начнем с создания ConfigMap, в котором будут храниться две HTML-страницы. Под 1 будет отображать страницу с заголовком «Pod 1», а Под 2 — с заголовком «Pod 2». Эти страницы подключаются к Nginx в подах.

Файл nginx-pages-configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-pages
  namespace: test-namespace
data:
  index-page1.html: |
    <html>
    <body>
      <h1>Pod 1</h1>
      <p>This is page served by Pod 1.</p>
    </body>
    </html>
  index-page2.html: |
    <html>
    <body>
      <h1>Pod 2</h1>
      <p>This is page served by Pod 2.</p>
    </body>
    </html>

Здесь мы создаем ConfigMap с двумя HTML-файлами: index-page1.html и index-page2.html. Они будут монтироваться в подах Nginx, позволяя каждому поду отображать свою страницу.

Примените ConfigMap:

kubectl apply -f nginx-pages-configmap.yaml

Создание деплойментов Nginx

Теперь создадим два деплоймента, каждый из которых будет использовать разные HTML-страницы из ConfigMap. Деплойменты используют селектор app: nginx — это метка, которую балансировщик будет использовать для выбора подов, участвующих в распределении нагрузки.

Файл nginx-deployment-pod1.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pod1
  namespace: test-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
          - name: nginx-pages
            mountPath: /usr/share/nginx/html/index.html
            subPath: index-page1.html
        ports:
          - containerPort: 80
      volumes:
      - name: nginx-pages
        configMap:
          name: nginx-pages

Этот деплоймент создает один под (реплика 1) с образом Nginx, который монтирует страницу index-page1.html из ConfigMap в директорию /usr/share/nginx/html/index.html. Порт 80 открыт для доступа к странице.

Примените деплоймент:

kubectl apply -f nginx-deployment-pod1.yaml

Файл nginx-deployment-pod2.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pod2
  namespace: test-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          volumeMounts:
            - name: nginx-pages
              mountPath: /usr/share/nginx/html/index.html
              subPath: index-page2.html
          ports:
            - containerPort: 80
      volumes:
        - name: nginx-pages
          configMap:
            name: nginx-pages

Этот деплоймент также создает под Nginx, но монтирует страницу index-page2.html, отличающуюся содержимым.

Примените второй деплоймент:

kubectl apply -f nginx-deployment-pod2.yaml

Настройка балансировщика нагрузки

Теперь создадим балансировщик, который будет направлять запросы на поды с меткой app: nginx.

Файл nginx-loadbalancer.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
  namespace: test-namespace
spec:
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

В этом Service указываем type: LoadBalancer, что создает балансировщик нагрузки, и selector: app: nginx, который направляет запросы на поды Nginx из наших деплойментов. Запросы, поступающие на балансировщик, распределяются между подами при помощи алгоритма roundrobin, так как этот алгоритм выбирается по умолчанию.

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

kubectl apply -f nginx-loadbalancer.yaml

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

После создания балансировщика его внешний IP-адрес можно увидеть в панели управления или выполнив команду:

kubectl get services -n test-namespace

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

Удаление ресурсов после проверки

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

kubectl delete service nginx-loadbalancer -n test-namespace
kubectl delete deployment nginx-pod1 -n test-namespace
kubectl delete deployment nginx-pod2 -n test-namespace
kubectl delete configmap nginx-pages -n test-namespace

Эти команды удалят балансировщик, деплойменты подов и ConfigMap, созданные ранее.

Либо удалите неймспейс полностью, выполнив:

kubectl delete namespace test-namespace

Этот способ автоматически удалит все ресурсы, связанные с тестовым окружением.

Была ли статья полезна?
Ваша оценка очень важна
Комментарии 1
Елена
15.11.2024, 07:13

Здравствуйте, а что на счёт аннотаций для включения proxy-protocol?