Control Plane за балансировщиком
При подключении агентов через L4-балансировщик Control Plane (CP) должен получать исходный IP агента. Балансировщик либо сохраняет IP сам, либо передаёт его через PROXY protocol. REST API и Web UI публикуются отдельно через L7-балансировщик.
Почему это требует настройки
CP использует реальный source-IP агента для сопоставления хостов с CIDR-группами (host-set'ы в правилах). Любой L4-балансировщик, который делает SNAT, подменяет source-IP агента своим адресом — тогда все агенты приходят «с одного адреса», и CIDR-резолюция ломается.
Есть два способа сохранить source-IP:
- Балансировщик сохраняет source-IP сам — облачный NLB или MetalLB в режиме, который не делает SNAT, вместе с
externalTrafficPolicy: Local. Код CP при этом не меняется. - PROXY protocol — балансировщик передаёт реальный адрес клиента в заголовке PROXY перед TLS, а CP его читает (
QF_AGENT_PROXY_PROTOCOL). Подходит для L4-балансировщика с поддержкойsend-proxy.
Две поверхности — разные требования
| Трафик | Порт | Как публиковать |
|---|---|---|
| REST API + Web UI | 8080 | Обычный Ingress / L7 (терминация TLS допустима) |
| Агенты: gRPC-стрим + enrollment | 8443, 8444 | L4 / TCP passthrough (mTLS остаётся сквозным) |
Агентский канал — это mTLS с клиентским сертификатом и долгоживущие стримы. Балансировщик для него должен работать в TCP-passthrough (не терминировать TLS — у него нет клиентских сертификатов) с большими таймаутами. Телеметрия агента идёт внутри того же gRPC-стрима на 8443 — отдельного порта для неё нет.
Публикация агентского порта через Helm
Чарт разворачивает выделенный Service для агентских портов ({release}-grpc), отдельно от REST/UI, чтобы externalTrafficPolicy: Local не влиял на REST-путь.
agentService:
enabled: true
type: LoadBalancer # NodePort | LoadBalancer
externalTrafficPolicy: Local
loadBalancerIP: "10.0.0.50" # опциональный фиксированный VIP
annotations: {} # напр. пул адресов MetalLB
# для type: NodePort
grpcNodePort: 31443
enrollNodePort: 31444
type: LoadBalancer— для MetalLB или облачного LB.type: NodePort— для bare-кластера без LB-провайдера (тогда балансировщик ставится перед узлами вручную и указывает на NodePort'ы).externalTrafficPolicy: Localнужен для сохранения IP агента балансировщиком.
Вариант 1: source-IP-сохраняющий LoadBalancer (без изменения CP)
Если LB сохраняет source IP, достаточно type: LoadBalancer и
externalTrafficPolicy: Local. QF_AGENT_PROXY_PROTOCOL не нужен. Критерий успешной
настройки: last_seen_ip хоста содержит IP агента, а не балансировщика.
MetalLB в режиме L2 анонсирует VIP с одного узла-лидера — трафик приходит на один узел, балансировки между узлами нет (только отработка отказа). Для распределения по узлам нужен режим BGP.
Вариант 2: PROXY protocol (любой L4-балансировщик)
Если LB выполняет SNAT, реальный адрес агента передаётся в CP через PROXY protocol.
На CP:
QF_AGENT_PROXY_PROTOCOL=true
QF_TRUSTED_PROXIES=10.0.0.0/24 # адрес(а) балансировщика
QF_AGENT_PROXY_PROTOCOLвключает чтение заголовка PROXY на портах8443/8444.QF_TRUSTED_PROXIES— список доверенных балансировщиков. Заголовку PROXY доверяют только от этих адресов; с любого другого адреса заголовок игнорируется и берётся реальный TCP-адрес. Это защита от подмены: клиент, подключившийся в обход балансировщика, не сможет подделать чужой source-IP. Если список пуст — заголовок не используется никогда (source-IP останется адресом балансировщика), CP выдаёт предупреждение при старте.
Балансировщик должен отправлять PROXY protocol в backend. Пример для HAProxy в режиме TCP passthrough:
defaults
mode tcp
timeout client 1h
timeout server 1h
frontend agent_stream
bind :8443
default_backend cp_stream
backend cp_stream
balance roundrobin
server cp1 CP_NODE_1:8443 check send-proxy-v2
server cp2 CP_NODE_2:8443 check send-proxy-v2
(Аналогично для enrollment на 8444.) send-proxy-v2 заставляет HAProxy слать заголовок PROXY v2 к CP; mode tcp — passthrough, mTLS не терминируется.
Как агенты находят балансировщик
Агенты выводят адреса из одного эндпоинта. Их DNS-имя CP должно указывать на VIP
балансировщика, а не на отдельный узел. Серверный сертификат CP должен включать это
имя в SAN (QF_CP_HOST). Смена адреса не требует повторного энролмента: клиентский
сертификат и доверие к CA не зависят от точки входа.
Проверка
- Агент подключается через балансировщик (стрим установлен, статус хоста
active). last_seen_ipхоста — реальный адрес агента, а не адрес балансировщика.- Правило с CIDR-группой, куда попадает адрес агента, компилируется и применяется на хосте.
Если last_seen_ip показывает адрес балансировщика, нужно проверить
externalTrafficPolicy: Local в варианте 1 либо QF_AGENT_PROXY_PROTOCOL,
QF_TRUSTED_PROXIES и send-proxy в варианте 2.