Перейти к основному содержимому

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:

  1. Балансировщик сохраняет source-IP сам — облачный NLB или MetalLB в режиме, который не делает SNAT, вместе с externalTrafficPolicy: Local. Код CP при этом не меняется.
  2. PROXY protocol — балансировщик передаёт реальный адрес клиента в заголовке PROXY перед TLS, а CP его читает (QF_AGENT_PROXY_PROTOCOL). Подходит для L4-балансировщика с поддержкой send-proxy.

Две поверхности — разные требования

ТрафикПортКак публиковать
REST API + Web UI8080Обычный Ingress / L7 (терминация TLS допустима)
Агенты: gRPC-стрим + enrollment8443, 8444L4 / 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 не зависят от точки входа.

Проверка

  1. Агент подключается через балансировщик (стрим установлен, статус хоста active).
  2. last_seen_ip хоста — реальный адрес агента, а не адрес балансировщика.
  3. Правило с CIDR-группой, куда попадает адрес агента, компилируется и применяется на хосте.

Если last_seen_ip показывает адрес балансировщика, нужно проверить externalTrafficPolicy: Local в варианте 1 либо QF_AGENT_PROXY_PROTOCOL, QF_TRUSTED_PROXIES и send-proxy в варианте 2.