Wazuh 集群负载均衡实战:使用 NGINX 与 HAProxy 分发 Agent 流量并启用 HAProxy Helper 自动均衡
【免费下载链接】wazuhWazuh - The Open Source Security Platform. Unified XDR and SIEM protection for endpoints and cloud workloads.项目地址: https://gitcode.com/GitHub_Trending/wa/wazuh
导读
本指南面向部署 Wazuh 服务器集群的运维与安全工程师,讲解如何通过负载均衡器把 Wazuh Agent 的注册(enrollment,端口 1515)与事件上报(reporting,端口 1514)流量透明地分发到集群中的 master 与 worker 节点,从而提升集群的扩展性、可用性与性能。文中同时深入剖析 Wazuh 内置的 HAProxy Helper 组件——它能够根据集群实时状态自动增删后端服务器、重连并再平衡 Agent 连接,使负载均衡真正做到"免运维"。读完本文,你将能够独立完成 NGINX / HAProxy 的配置落地,以及 HAProxy Helper 的启用、验证与故障排查。
一、为什么 Wazuh 集群需要负载均衡
在 Wazuh 服务器集群中,master 节点负责集中协调、下发配置与规则,worker 节点承担 Agent 的接入与事件预处理。随着 Agent 数量增长,单个 worker 的连接压力会成为瓶颈。负载均衡器在此扮演核心角色:
- 透明接入:Agent 只需知道负载均衡器的地址,即可注册(1515 端口)并向不同服务器节点(1514 端口)上报事件,无需关心后端是哪台节点;
- 高可用:当某个节点不可用时,Agent 会自动重连到其他可用节点,避免单点故障导致的数据上报中断;
- 可扩展:新增 worker 节点后无需逐台修改 Agent 配置,负载均衡器自动把新流量引向新节点。
本仓库官方文档(docs/ref/modules/cluster/lb.md)覆盖两款常用负载均衡方案:NGINX与HAProxy,并额外介绍 Wazuh 专为 HAProxy 设计的自动化辅助组件HAProxy Helper。
二、方案一:使用 NGINX 作为 TCP 负载均衡器
NGINX 通过stream模块即可实现四层(TCP)负载均衡,非常适合代理 Wazuh Agent 的持久 TCP 连接。
2.1 安装
直接使用你所使用的 Linux 发行版官方软件源提供的 NGINX 软件包安装即可:
# Debian / Ubuntu apt install nginx # RHEL / CentOS / Rocky / AlmaLinux dnf install nginx需要说明的是,NGINX 的 TCP 代理能力由
stream模块提供,主流发行版打包的 NGINX 默认已包含该模块,无需额外编译。
2.2 配置
编辑 NGINX 主配置文件nginx.conf,在顶层加入stream配置块。下面配置直接取自仓库官方文档并保留全部细节:
stream { upstream master { server <MASTER_NODE_IP>:1515; } upstream cluster { hash $remote_addr consistent; server <MASTER_NODE_IP>:1514; server <WORKER_NODE_IP>:1514; server <WORKER_NODE_IP>:1514; } server { listen 1515; proxy_pass master; } server { listen 1514; proxy_pass cluster; } }配置要点解读:
upstream master(1515 端口):注册请求必须由 master 节点处理(注册完成后密钥会下发给 Agent),因此这里只指向 master 节点,不做负载均衡;upstream cluster(1514 端口):事件上报流量需要在 master 与所有 worker 节点之间分发,因此列出全部节点地址;hash $remote_addr consistent;:基于 Agent 源 IP 做一致性哈希,保证同一 Agent 总是被路由到同一台后端节点(对长连接与连接跟踪友好),同时节点增删时只影响少量 Agent 的映射;- 两个
server块:分别把 1515 与 1514 端口的监听流量转发到对应 upstream。
将配置中的<MASTER_NODE_IP>、<WORKER_NODE_IP>占位符替换为集群各节点的实际 IP 地址。
2.3 校验配置并热加载
nginx -t nginx -s reloadnginx -t先做语法与配置合法性检查,通过后再用nginx -s reload平滑重载配置,不会中断正在进行的 Agent 连接。
三、方案二:使用 HAProxy 作为高可用 TCP 负载均衡器
HAProxy 是专为 TCP/HTTP 高可用设计的负载均衡器,与 Wazuh Agent 的 TCP 长连接场景高度契合。
3.1 安装
既可以使用系统软件包,也可以使用 Docker 部署:
# Debian / Ubuntu apt install haproxy # RHEL / CentOS / Rocky / AlmaLinux dnf install haproxy3.2 基础配置
创建(或覆盖)配置文件/etc/haproxy/haproxy.cfg,内容同样完整保留自官方文档:
global maxconn 4000 user haproxy group haproxy daemon defaults mode tcp timeout connect 10s timeout client 1m timeout server 1m frontend wazuh_register bind :1515 default_backend wazuh_register backend wazuh_register balance leastconn server master <MASTER_NODE>:1515 check server worker1 <WORKER_NODE>:1515 check frontend wazuh_reporting bind :1514 default_backend wazuh_reporting backend wazuh_reporting balance leastconn server master <MASTER_NODE>:1514 check server worker1 <WORKER_NODE>:1514 check配置要点解读:
mode tcp:四层代理模式,直接转发 Agent 的原始 TCP 流量,适合 Wazuh 的加密通信链路(Agent 与服务器之间使用自定义加密协议,必须在四层透传);balance leastconn:最少连接数算法,HAProxy 会把新连接分配给当前活跃连接最少的后端节点,天然适配 Agent 连接数不均衡的场景;check健康检查:HAProxy 会周期性探测后端节点存活状态,节点宕机时自动摘除流量,恢复后自动重新加入;- 1515 与 1514 分别建立 frontend/backend:与 NGINX 方案一致,注册走 master(此处示例也把 worker 列入 1515,实际以你的集群拓扑为准),上报流量在所有节点间均衡。
3.3 启动服务
service haproxy start启动后,Agent 只需把服务器地址配置为负载均衡器地址,即可经由 1515/1514 端口透明接入集群。
四、进阶:HAProxy Helper —— 让负载均衡跟随集群状态自动演进
手工维护的haproxy.cfg存在一个天然短板:当集群节点动态变化(新增 worker、节点下线、地址变更)时,后端列表不会自动更新。Wazuh 在框架层内置了HAProxy Helper来解决这个问题。该组件以独立任务运行在 master 节点上,周期性地对比"Wazuh 集群实际节点"与"HAProxy 后端服务器",并自动完成增删、重连与再平衡。
4.1 Dataplane API 配置
HAProxy Helper 通过HAProxy Dataplane API(REST 接口)动态管理后端配置,因此需要先在 HAProxy 侧启用并配置该 API。创建配置文件(例如/etc/haproxy/dataplaneapi.yaml):
dataplaneapi: host: 0.0.0.0 port: 5555 user: - name: <USER> password: <PASSWORD> insecure: true haproxy: config_file: /etc/haproxy/haproxy.cfg haproxy_bin: /usr/sbin/haproxy reload: reload_cmd: service haproxy reload字段说明:
dataplaneapi.host / port:API 监听地址与端口,0.0.0.0:5555表示对所有地址开放(若 master 与 HAProxy 同机可收紧为127.0.0.1);dataplaneapi.user:API 访问账号与密码,Helper 将用同一组凭据认证;insecure: true表示该用户允许在配置变更后触发force_reload;haproxy.config_file / haproxy_bin:Dataplane API 操作的 HAProxy 配置文件路径与可执行文件路径;reload.reload_cmd:每次配置变更后用于平滑重载 HAProxy 的命令(此处为service haproxy reload)。
4.2 在 Wazuh master 上启用 Helper
编辑 master 节点的wazuh-manager.conf,在<cluster>配置块内加入<haproxy_helper>小节:
<haproxy_helper> <haproxy_disabled>no</haproxy_disabled> <haproxy_address><HAPROXY_ADDRESS></haproxy_address> <haproxy_user><USER></haproxy_user> <haproxy_password><PASSWORD></haproxy_password> </haproxy_helper>haproxy_disabled:设为no启用 Helper(默认即启用,yes可显式禁用);haproxy_address:Dataplane API 地址(与 4.1 节中的监听地址对应);haproxy_user/haproxy_password:Dataplane API 认证凭据,必须与配置文件中的user.name / password一致。
配置项说明与源码对应:这些字段在 framework/wazuh/core/cluster/utils.py 中定义,并由parse_haproxy_helper_config解析。除上述三个必填项外,Helper 还支持一系列可调参数,未配置时自动套用默认值,完整默认值见下表:
| 配置项 | 默认值 | 含义 |
|---|---|---|
haproxy_port | 5555 | Dataplane API 端口 |
haproxy_protocol | http | 与 API 通信的协议(http/https) |
haproxy_backend | wazuh_reporting | Helper 管理的 HAProxy backend 名称 |
haproxy_resolver | 无 | 连接解析器名称(使用 DNS 域名时配置) |
haproxy_cert | True | HTTPS 模式下验证 HAProxy 证书的文件路径 |
client_cert/client_cert_key/client_cert_password | 无 | HTTPS 模式下客户端证书及其私钥/口令 |
frequency | 60 | 主循环巡检间隔(秒) |
agent_chunk_size | 300 | 每批次重连的 Agent 数量 |
agent_reconnection_time | 5 | 相邻两批重连之间的等待时间(秒) |
agent_reconnection_stability_time | 60 | 重连完成后等待连接稳定的时间(秒) |
imbalance_tolerance | 0.1 | 允许的连接数偏差容忍度(比例,如 0.1 即 ±10%) |
remove_disconnected_node_after | 240 | 节点持续断开多少分钟后从后端移除(分钟) |
excluded_nodes | 无 | 不参与负载均衡的节点列表 |
以上默认值定义在 framework/wazuh/core/cluster/utils.py 的HELPER_DEFAULTS中,整数/浮点类型参数在解析时会被强校验(类型非法将抛出错误码 3004),详见同一文件的_parse_haproxy_helper_integer_values与_parse_haproxy_helper_float_values。
4.3 重启并验证
修改配置后重启管理器使配置生效:
systemctl restart wazuh-manager随后检查集群日志确认 Helper 运行状态:
tail /var/wazuh-manager/logs/cluster.log启动成功后日志中应出现Starting HAProxy Helper以及Load balancer backend is up to date/Load balancer backend is balanced等周期性巡检信息(日志内容与 framework/wazuh/core/cluster/hap_helper/hap_helper.py 主循环中的打印一致)。
五、HAProxy Helper 的工作原理与源码级解读
启用 Helper 后,它到底做了什么?从源码可以还原出完整的工作机制。
5.1 启动流程
HAPHelper.start()(hap_helper.py)按以下顺序初始化:
- 读取
wazuh-manager.conf中的haproxy_helper配置,并从<remote>小节读取实际连接端口(默认 1514,定义于CONNECTION_PORT); - 依据协议配置构建
ProxyAPI客户端:若配置为https但缺少证书文件,会回退为 HTTP 并记录警告; - 构建
Proxy(封装对 Dataplane API 的 backend/frontend/server 增删查改)与WazuhDAPI(通过分布式 API 查询集群节点与 Agent 分布); - 初始化并健康检查 Dataplane API(
initialize_proxy); - 校验 HAProxy 上不存在与 1514 端口冲突的多个 frontend(
check_multiple_frontends),确保只有与目标 backend 关联的 frontend 在监听; - 若 HAProxy 尚未配置
hard-stop-after,则动态计算并写入(详见 5.3); - 进入无限巡检主循环。
ProxyAPI(proxy.py)完整封装了 Dataplane API v2 的 REST 接口:/services/haproxy/configuration/{backends,frontends,servers,binds}与/services/haproxy/runtime/...,并维护_version乐观锁以保证并发变更安全,每个写操作都携带force_reload: true即时生效。
5.2 巡检主循环:节点增删与连接平衡
核心逻辑位于manage_wazuh_cluster_nodes()(hap_helper.py),每个frequency秒执行一轮:
- 健康检查:扫描后端服务器,若发现某节点处于
DRAIN状态则自动恢复为READY(backend_servers_state_healthcheck); - 对比集群节点与后端列表(
obtain_nodes_to_configure):- Wazuh 集群中存在、但后端缺失 → 加入
add_nodes; - 地址变更的节点 → 先移除再添加;
- 后端存在、但已不在集群中的节点 → 若已断开超过
remove_disconnected_node_after分钟则移除(check_node_to_delete会读取节点状态与lastchg时间判断);
- Wazuh 集群中存在、但后端缺失 → 加入
- 迁移旧连接(
migrate_old_connections):等待新节点UP(超时 60 秒则抛错 3041),随后把需要搬迁的 Agent 分块重连到新节点; - 均衡检测(
check_for_balance):读取各后端节点当前活跃连接数(scur指标),计算均值后与imbalance_tolerance比较,超出容忍范围即视为不均衡; - 执行再平衡(
balance_agents):对连接数超标的节点,按其超出数量选取 Agent 并分块重连(每批agent_chunk_size个,批间休眠agent_reconnection_time秒),重连完成后等待agent_reconnection_stability_time秒让连接稳定。
一个值得注意的细节:只有版本不低于 4.3 的 Agent 才支持被 Helper 强制重连。
WazuhAgent.can_reconnect()(wazuh.py)通过正则解析 Agent 版本号vX.Y.Z判断兼容性,不兼容的 Agent 会跳过强制重连,其连接随后由负载均衡算法自然再分配。
5.3 动态计算hard-stop-after:保障重连不丢连接
HAProxy 在执行重载(reload)时,旧进程需要在一定时间内优雅关闭旧连接,这个宽限期由全局参数hard-stop-after控制。Helper 会根据集群规模动态计算该值(set_hard_stop_after_value,proxy.py):
hard_stop_after = (active_agents / (n_managers * chunk_size)) * n_managers * agent_reconnection_time + (n_managers * server_admin_state_delay * 2)即:把全部活跃 Agent 按"每批 chunk_size 个、批间休眠 agent_reconnection_time 秒"的速度重连所需的总时间,再加上节点管理状态切换的额外延迟,确保在旧 HAProxy 进程超时退出前,Agent 重连已全部完成。由于该值随 Agent 数量动态变化,Helper 在每次节点变更后都会重新计算并写入。
5.4 典型错误码速查
Helper 与 Dataplane API 通信失败时,会在日志中输出定义于 framework/wazuh/core/exception.py 的错误码,便于快速定位:
| 错误码 | 含义 |
|---|---|
| 3041 | 新增服务器后等待其UP状态超时 |
| 3042 | Helper 配置无效(如 HTTPS 协议未配置证书) |
| 3043 | 无法初始化 Proxy API(检查网络连通性与wazuh-manager.conf配置) |
| 3044 | 无法连接 HAProxy Dataplane API |
| 3045 | 无法连接 HAProxy(API 返回异常) |
| 3046 | Dataplane API 认证凭据无效 |
| 3047 | Dataplane API 规格配置无效 |
| 3048 | 未检测到与 Dataplane API 关联的有效 HAProxy 进程 |
六、方案选型建议
- Agent 规模小、集群节点固定:直接使用 NGINX(一致性哈希保证同源 Agent 固定落点)或 HAProxy(
leastconn+check保证均衡与故障转移)的手工配置即可,运维成本最低; - 集群节点频繁伸缩、追求全自动均衡:优先选择HAProxy + HAProxy Helper组合。Helper 运行在 master 节点,通过 Dataplane API 动态维护后端列表、自动迁移与再平衡 Agent 连接,并把
hard-stop-after调优为与集群规模匹配的值; - 无论选择哪种方案,都应保证负载均衡器所在主机可稳定访问集群所有节点的 1514/1515 端口,且 Agent 配置中的服务器地址统一指向负载均衡器。
相关实现与测试可进一步参阅:hap_helper.py、proxy.py、wazuh.py、utils.py、test_hap_helper.py、test_proxy.py 与 test_utils.py,后者通过参数化用例验证了配置解析、默认值填充与非法类型报错(错误码 3004/3042)等边界行为。
【免费下载链接】wazuhWazuh - The Open Source Security Platform. Unified XDR and SIEM protection for endpoints and cloud workloads.项目地址: https://gitcode.com/GitHub_Trending/wa/wazuh
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考