Для обеспечения устойчивой работы приложений и равномерного распределения трафика между подами в 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
может быть произвольным.
После создания балансировщик будет отображаться в панели управления в разделе «Балансировщики».
Обратите внимание, что после создания балансировщика изменять его конфигурацию следует через
kubectl
, а не из панели управления, чтобы избежать конфликтов.
В правилах балансировщика вы можете заметить, что порт, с которого выполняется балансировка, отличается от того, что был указан в Service. В правилах балансировщика будет указан NodePort.
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:
Параметр |
Назначение |
|
Задает конфигурацию балансировщика. По умолчанию выбирается минимальная конфигурация для зоны. Получить id тарифов можно при помощи API. |
|
Алгоритм балансировки: |
|
Интервал между проверками доступности (в секундах). |
|
Таймаут проверки доступности (в секундах). |
|
Количество неудачных проверок перед отключением апстрима. |
|
Количество успешных проверок для восстановления апстрима. |
|
Отключение внешнего публичного IP для балансировщика. |
|
Выделение внешнего IP с защитой от DDoS. |
|
Исключает сервис из обработки балансировщиком Timeweb Cloud. Может быть полезно, если используется другой |
Для демонстрации работы балансировщика создадим два деплоймента Nginx, каждый из которых будет отображать свою HTML-страницу. Балансировщик случайным образом распределит запросы между подами, и в зависимости от этого будет показана одна из страниц.
Для удобства управления и быстрого удаления всех ресурсов, связанных с балансировщиком, создадим отдельный неймспейс. Это упростит тестирование и последующее удаление ресурсов, сохраняя основной кластер чистым.
Выполните команду для создания неймспейса:
kubectl create namespace test-namespace
После создания используем этот неймспейс для всех дальнейших ресурсов, включая балансировщик, деплойменты и ConfigMap
. Для этого добавьте namespace: test-namespace
в каждый манифест, связанный с примером.
Начнем с создания 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
Теперь создадим два деплоймента, каждый из которых будет использовать разные 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
Этот способ автоматически удалит все ресурсы, связанные с тестовым окружением.
Здравствуйте, а что на счёт аннотаций для включения proxy-protocol?