Для организации внутрикластерного взаимодействия в Deckhouse Kubernetes Platform рекомендуется использовать сервисы вместо обращения напрямую к подам. Они обеспечивают балансировку нагрузки между подами, стабильное сетевое взаимодействие и интеграцию с DNS для удобного обнаружения сервисов. Также сервисы поддерживают различные сценарии доступа и обеспечивают изоляцию и безопасность сетевого трафика.
При необходимости можно использовать стандартный балансировщик на базе сервисов или расширенный балансировщик на базе модуля service-with-healthchecks
.
Стандартный балансировщик
В Kubernetes за внутреннюю и внешнюю балансировку запросов отвечает ресурс типа Service. Этот ресурс:
- распределяет запросы между рабочими подами приложения;
- исключает из балансировки повреждённые экземпляры подов.
Для проверки способности пода обрабатывать входящие запросы применяются readiness-пробы, которые указываются в спецификации контейнеров, входящих в этот под.
Ограничения стандартного балансировщика Service
Стандартный инструмент балансировки Service подходит для большинства задач облачных приложений, но имеет два ограничения:
- Если хотя бы один контейнер в поде не проходит проверку готовности (readiness-пробу), весь под считается как
NotReady
и исключается из балансировки всех сервисов, с которыми он связан. - Для каждого контейнера можно настроить только одну пробу, поэтому невозможно создать отдельные пробы для проверки, например, доступности чтения и записи.
Примеры сценариев, где стандартного балансировщика недостаточно:
- База данных:
- Работает в трёх подах —
db-0
,db-1
иdb-2
, каждый из которых содержит один контейнер с запущенным процессом базы данных. - Необходимо создать два сервиса (Service) —
db-write
для записи иdb-read
для чтения. - Запросы на чтение должны балансироваться между всеми подами.
- Запросы на запись балансируются только на тот под, который назначен мастером средствами самой базы данных.
- Работает в трёх подах —
- Виртуальная машина:
- Под содержит единственный контейнер, в котором запущен процесс
qemu
, выполняющий роль гипервизора для гостевой виртуальной машины. - В гостевой виртуальной машине запущены независимые процессы, например, веб-сервер и SMTP-сервер.
- Требуется создать два Service —
web
иsmtp
, каждый из которых будет иметь свои readiness-пробы.
- Под содержит единственный контейнер, в котором запущен процесс
Пример сервиса для стандартного балансировщика
apiVersion: v1
kind: Service
metadata:
name: productpage
namespace: bookinfo
spec:
ports:
- name: http
port: 9080
selector:
app: productpage
type: ClusterIP
Пример стандартного балансировщика для работы с PostgreSQL-кластером
Создание StatefulSet для PostgreSQL
Для корректной работы StatefulSet потребуется создать стандартный сервис (Service) для формирования DNS-имени отдельных подов. Этот сервис не будет использоваться для прямого доступа к базе данных.
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
selector:
app: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
Пример манифеста StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
name: my-ns
spec:
serviceName: postgres
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: example
Расширенный балансировщик
В отличие от стандартного балансировщика, где readiness-пробы привязаны к состоянию контейнеров, ресурс ServiceWithHealthcheck, который используется в балансировщике, позволяет настраивать активные пробы на отдельные TCP-порты. Таким образом, каждый балансировщик, обслуживающий один и тот же под, может работать независимо от других.
Внутреннее устройство балансировщика
Балансировщик состоит из двух компонентов:
- контроллер — работает на master-узлах кластера и управляет ресурсами ServiceWithHealthcheck,
- агенты — работают на каждом узле кластера и выполняют пробы для подов, запущенных на этом узле.
Балансировщик ServiceWithHealthcheck спроектирован так, чтобы не зависеть от реализации CNI, используя при этом стандартные ресурсы Service и EndpointSlice:
- Контроллер при создании ресурса ServiceWithHealthcheck автоматически создает одноименный ресурс Service в том же пространстве имен с пустым полем
selector
. Это позволяет избежать создания стандартным контроллером объектов EndpointSlice, которые используются для настройки балансировки. - Каждый агент при появлении на своём узле подов, которые попадают под управление ServiceWithHealthcheck, осуществляет настроенные пробы и создаёт для них объект EndpointSlice со списком проверенных IP-адресов и портов. Данный объект EndpointSlice привязан к дочернему ресурсу Service, созданному выше.
- CNI сопоставит все объекты EndpointSlice со стандартными сервисами, созданными выше и осуществит балансировку по проверенным IP-адресам и портам на всех узлах кластера.
Миграция с Service на ресурс ServiceWithHealthchecks, например в рамках CI/CD, не должна вызвать затруднений. Спецификация ServiceWithHealthchecks в основе своей повторяет спецификацию Service, но содержит дополнительный раздел healthcheck
. Во время жизненного цикла ресурса ServiceWithHealthchecks создается одноименный сервис в том же пространстве имён, чтобы привычным способом (kube-proxy
или cni) направить трафик на рабочие нагрузки в кластере.
Настройка балансировщика
Настроить данный способ балансировки можно при помощи ресурса ServiceWithHealthchecks:
- Его спецификация идентична стандартному ресурсу Service с добавлением раздела
healthcheck
, который содержит набор проверок. - На данный момент поддерживается три вида проб:
TCP
— обычная проверка с помощью установки TCP-соединения.HTTP
— возможность отправить HTTP-запрос и ожидать определённый код ответа.PostgreSQL
— возможность отправить SQL-запрос и ожидать его успешного завершения.
Пример конфигурации расширенных балансировщиков ServiceWithHealthchecks
Создайте Secret для хранения учетных данных для доступа проб к базе данных:
d8 k -n my-ns create secret generic cred-secret --from-literal=user=postgres --from-literal=password=example cred-secret
Пример манифеста балансировщика для чтения:
apiVersion: network.deckhouse.io/v1alpha1
kind: ServiceWithHealthchecks
metadata:
name: postgres-read
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
selector:
app: postgres
healthcheck:
probes:
- mode: PostgreSQL
postgreSQL:
targetPort: 5432
dbName: postgres
authSecretName: cred-secret
query: "SELECT 1"
Пример манифеста балансировщика для записи:
apiVersion: network.deckhouse.io/v1alpha1
kind: ServiceWithHealthchecks
metadata:
name: postgres-write
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
selector:
app: postgres
healthcheck:
probes:
- mode: PostgreSQL
postgreSQL:
targetPort: 5432
dbName: postgres
authSecretName: cred-secret
query: "SELECT NOT pg_is_in_recovery()"
Размещение двух независимых балансировщиков на одной виртуальной машине
На виртуальной машине с операционной системой Linux работают два приложения — HTTP-сервер (TCP 8080) и SMTP-сервер (TCP 2525). Необходимо настроить два отдельных балансировщика для этих сервисов — веб-балансировщик и SMTP-балансировщик.
Создание виртуальной машины
Создайте виртуальную машину my-vm
основываясь на примерах из документации DVP.
В примере манифеста ниже добавлен лейбл vm: my-vm
для дальнейшей идентификации в балансировщиках.
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachine
metadata:
name: my-vm
namespace: my-ns
labels:
vm: my-vm
spec:
virtualMachineClassName: host
cpu:
cores: 1
memory:
size: 1Gi
provisioning:
type: UserData
userData: |
#cloud-config
ssh_pwauth: True
users:
- name: cloud
passwd: '$6$rounds=4096$saltsalt$fPmUsbjAuA7mnQNTajQM6ClhesyG0.yyQhvahas02ejfMAq1ykBo1RquzS0R6GgdIDlvS.kbUwDablGZKZcTP/'
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
lock_passwd: False
blockDeviceRefs:
- kind: VirtualDisk
name: linux-disk
Манифесты расширенных балансировщиков для веб-сервиса и SMTP
Пример манифеста веб-балансировщика:
apiVersion: network.deckhouse.io/v1alpha1
kind: ServiceWithHealthchecks
metadata:
name: web
namespace: my-ns
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
vm: my-vm
healthcheck:
probes:
- mode: HTTP
http:
targetPort: 8080
method: GET
path: /healthz
Пример манифеста SMTP-балансировщика:
apiVersion: network.deckhouse.io/v1alpha1
kind: ServiceWithHealthchecks
metadata:
name: smtp
namespace: my-ns
spec:
ports:
- port: 25
protocol: TCP
targetPort: 2525
selector:
vm: my-vm
healthcheck:
probes:
- mode: TCP
tcp:
targetPort: 2525