Vector 在 Kubernetes 中的聚合器横向扩展与负载均衡:基于 HAProxy 的架构方案解析
【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector
导读:本文以 Vector 官方 RFC 7469(2021-05-17《Scaling and load balancing for Vector aggregators in Kubernetes》)为主体,系统讲解 Vector 作为聚合器(Aggregator)在 Kubernetes 中横向扩展时面临的负载均衡问题、HAProxy 反向代理方案的动机与取舍,并结合当前仓库中 vector-aggregator 的 Helm 生成的 Kubernetes 清单(StatefulSet、headless Service、ConfigMap)与
vectorsink 的load_balance路由策略源码,帮助读者掌握在 Kubernetes 中部署多副本 Vector 聚合器并接入 HAProxy 动态服务发现的完整思路与落地配置。
背景与动机:为什么聚合器需要负载均衡
在 Vector 的典型部署架构中,聚合器(Aggregator)承担着接收来自大量 Agent 的数据、执行聚合/处理、再转发到下游目的地(如 Datadog、S3、Elasticsearch)的角色。RFC 指出,在方案提出之前,Vector 聚合器仅能以单实例形态工作,横向扩展(增加副本数)完全依赖人工操作,这带来了两个核心问题:
- 可靠性:单实例是明显的单点故障(single point of failure),任何一个节点或进程故障都会导致整个数据管线中断;
- 性能上限:单实例的吞吐能力受限于可分配给它的资源(CPU、内存、网络),且存在尚未探明的上限。
Vector 的定位是厂商中立(vendor neutral),因此它需要提供一种与环境、与上游事件采集器无关的横向扩展与负载均衡能力,让用户无需替换已有基础设施即可可靠地以聚合器形态采用 Vector。RFC 将讨论范围聚焦到 Kubernetes 场景下的三个具体接入场景:
- Vector Agent → Vector 聚合器(Vector 内部组件间通信,使用
vectorsource/sink); - Datadog Agent → Vector 聚合器(
datadog_agentsource); - Syslog(TCP)Agent → Vector 聚合器(
syslogsource)。
同时明确排除的范围包括:Kafkasource的扩展,以及 Kubernetes 之外的平台上的扩展与负载均衡——后者意味着本方案以 Kubernetes 的服务发现能力(DNS / headless Service)为前提。
内部提案:随 vector-aggregator Helm Chart 内置专用反向代理
RFC 的核心提案是:在 vector-aggregator Helm Chart 中内置一个专用反向代理(dedicated reverse proxy)的配置,开箱即用地提供"基础但可用"的配置,让用户能够"一键"将 Vector 部署为可水平扩展的聚合器。代理需要:
- 动态解析下游 Vector 实例:能够根据 Kubernetes 的服务发现动态获取所有聚合器副本;
- 允许用户调整负载均衡策略:在需要一致目标(如聚合类 transform)的场景下,提供更一致的命中目标(如
source亲和策略)。
候选代理选型上,RFC 明确首选HAProxy,其次考虑NGINX或Envoy。选型理由是:
| 对比维度 | HAProxy | NGINX |
|---|---|---|
| 可观测性 | 暴露更丰富的指标(JSON 或 Prometheus 格式) | 指标能力相对有限 |
| 服务发现 | 原生支持,可动态填充配置 | 需借助 Lua 脚本(如 nginx-ingress-controller 的做法) |
| UDP 支持 | 支持有限(2.3 起可转发 syslog,但不支持动态后端) | — |
HAProxy 动态服务发现配置示例
RFC 给出了一个利用 Kubernetes 集群 DNS 做服务发现的基础 HAProxy 配置:
resolvers coredns nameserver dns1 kube-dns.kube-system.svc.cluster.local:53 hold timeout 600s hold refused 600s frontend vector bind *:9000 default_backend vector_template backend vector_template balance roundrobin option tcp-check server-template srv 10 _vector._tcp.vector-aggregator-headless.vector.svc.cluster.local resolvers coredns check逐段解读这段配置的工程含义:
resolvers coredns:定义 DNS 解析器指向 Kubernetes 集群内的 CoreDNS(kube-dns.kube-system.svc.cluster.local:53),这是 HAProxy 动态服务发现的"数据源";hold timeout/hold refused:DNS 解析结果的有效期与拒绝缓存时长(600 秒),控制服务发现更新的节奏;frontend vector:监听*:9000(与聚合器syslogsource 的默认端口对齐),default_backend指向后端模板;backend vector_template:balance roundrobin指定轮询策略;option tcp-check启用 TCP 健康检查;server-template srv 10 _vector._tcp.vector-aggregator-headless.vector.svc.cluster.local:关键的一行——通过 Kubernetes 的headless Service(vector-aggregator-headless)暴露的 SRV 记录_vector._tcp动态发现最多 10 个后端实例,并持续用resolvers coredns刷新、用check做健康探测。
这里的 SRV 记录依赖正是仓库中 service-headless.yaml 所定义的clusterIP: None的 headless Service。当前仓库中该 Service 暴露了聚合器接收数据的全部端口(均为 TCP):
| 端口 | 名称 | 对应 source |
|---|---|---|
| 8282 | datadog-agent | datadog_agent |
| 24224 | fluent | fluent |
| 5044 | logstash | logstash |
| 8080 | splunk-hec | splunk_hec |
| 8125 | statsd | statsd |
| 9000 | syslog | syslog |
| 6000 | vector | vector(v2) |
| 9090 | prom-exporter | prometheus_exporter(内部指标) |
这些端口的 source 定义可以在 configmap.yaml 中的aggregator.yaml里看到完整对应关系——例如syslog使用mode: tcp监听0.0.0.0:9000,vector使用version: "2"监听0.0.0.0:6000。这也印证了 RFC 中"每个 source 需要独立端口"的设定。
与当前仓库的落地形态对照
虽然 RFC 中规划的 HAProxy 部署并未出现在仓库的 vector-aggregator 清单目录中(该目录由helm template生成,包含 configmap、service-headless、service、serviceaccount、statefulset),但从现有清单可以清晰看到支撑负载均衡的底层基础设施已经就位:
- StatefulSet 形态:statefulset.yaml 使用
StatefulSet(podManagementPolicy: OrderedReady,serviceName: vector-headless),副本以稳定、有序的方式扩容,适合作为动态后端; - headless Service:service-headless.yaml 设置
clusterIP: None,使每个 Pod 拥有独立 DNS 记录,并可通过 SRV 记录(_vector._tcp)被 HAProxy 的server-template发现; - 就绪探针:StatefulSet 配置了
/health的readinessProbe(端口 8686,即 Vector API 端口),代理层可据此将流量只导向就绪副本; - Agent 侧对称清单:vector-agent 的 service-headless.yaml 暴露同样的端口集合,说明 Agent 与 Aggregator 之间的
vectorv2 通信端口(6000)在两侧保持一致。
方案论证:选择外部反向代理的 Rationale
RFC 为"外部反向代理"方案给出了明确的论证理由:
- 与上游 Agent 解耦:无论上游是什么采集器(Vector Agent、Datadog Agent、syslog 等),只要流量先经过代理,负载均衡就对上游透明;
- 覆盖面广、工程成本低:一个专用反向代理可以支持绝大多数
source类型,相比为每个 source 单独实现均衡逻辑,是覆盖面与成本的平衡点; - 不绑定 Vector 生态:方案位于 Vector 之外,用户可以在不替换现有基础设施的前提下可靠地采用 Vector 聚合器;
- 运维认知友好:大多数组织对某种反向代理的运维都很熟悉;
- 关注点分离:专用反向代理专注于其任务,Vector 专注数据管道,各司其职。
权衡与缺点:为方案付出的代价
RFC 同样如实记录了该方案的缺点:
- 第三方组件维护负担:团队需要维护一个第三方应用的配置,并持续跟进其安全漏洞与版本更新;
- 集成测试成本:需要将反向代理纳入新的或现有的集成测试,防止提供的配置与代理版本之间出现回归;
- 部署复杂度上升:端到端部署会多出一个应用,调试时可能造成误导,也增加运维负担;
- UDP 支持受限:HAProxy 对 UDP 代理支持有限,因此初始实现无法为 UDP 类型的
source提供负载均衡; - syslog over UDP 明确不支持:HAProxy 的 syslog 转发不支持动态后端服务器,因此初始实现仅覆盖 syslog over TCP。
这一点与 RFC 开篇的 Scope 完全呼应——三个初始用例(Vector Agent、Datadog Agent、Syslog TCP)全部基于 TCP 协议。仓库中聚合器清单的syslogsource 也明确使用mode: tcp(见 configmap.yaml),与 RFC 的取舍一致。
备选方案对比:为什么最终不选它们
RFC 系统评估了四类备选方案,并说明了各自的不足:
什么都不做(Do Nothing)
聚合器可以继续单实例运行、垂直扩展。这固然降低了复杂度,但会导致单点故障,并给吞吐量带来上限——这正是 Motivation 中要解决的问题本身。
仅客户端侧负载均衡(Only Client-side Load Balancing)
驱动 v2 Vectorsink/source的库本身具备客户端负载均衡能力,但这只覆盖"单一 sink → source"配对。对于 Beats、Logstash 这类客户端,虽然可以实现 Elasticsearch 兼容 API 来利用它们原生的负载均衡,但这类做法一般是按 source 逐个实现,无法覆盖所有 source。值得注意的是,RFC 在"Outstanding Questions"中也确认,内置负载均衡能力(尤其vectorsink 侧)更适合放在另一份 RFC 或按组件逐个推进——而这一方向已在当前仓库中落地,详见下文。
强制要求 Service Mesh(Require a Service Mesh)
已采用 Service Mesh 的用户可以把负载均衡下放到网格,但把 Service Mesh 作为运行和扩展 Vector 聚合器的前置条件是巨大的采用门槛。
分布式哈希环(Distributed hashring)
Thanos、Loki 等项目用哈希环实现多租户,可以确保事件被转发到正确的聚合器,但 RFC 明确表态:"没有人想把 Vector 变成一个分布式系统"——这超出了 Vector 的产品定位。
内置负载均衡的后续演进:vectorsink 的load_balance策略
RFC 的 "Outstanding Questions" 中确认了"是否要探索内置负载均衡能力"这一问题,结论是内置方案更适合单独推进。这一方向在仓库源码中已经实现:当前 src/sinks/vector/config.rs 中定义了EndpointStrategy枚举,为vectorsink 提供三种跨端点路由策略:
LoadBalance(默认):使用 Vector 的 Tower distributed service 在健康端点间分发请求,端点健康状态由routing.health跟踪,不健康的端点按配置退避(backoff)并重新探测。该模式不保活单个活动端点,也不偏好第一个配置的端点;Failover:同一时刻只使用一个端点,活动端点失败后按顺序切换到下一个端点,直到成功;请求被串行化以保证"单一活动端点"语义;FailoverPrimary:与Failover类似,但活动端点失败后从配置顺序的头部重试,从而在接收端(如设置了max_connection_age_secs连接回收)可用时收敛回第一个配置的主端点。
其中LoadBalance模式在配置上依赖routing.health(config.rs),健康检查在启动时对所有配置的端点执行(见测试用例load_balancing_healthchecks_all_configured_endpoints_even_with_override_uri,config.rs)。这正是 RFC 设想中"内置负载均衡能力(where possible)"的落地:当 Vector 集群内部组件间使用vectorsink 时,客户端侧即可完成均衡,而外部 Agent(Datadog、syslog)仍需依赖 RFC 主推的 HAProxy 方案。
与高可用部署实践的衔接
RFC 的负载均衡方案并非孤立存在,它与仓库中 high-availability.md 描述的高可用策略相互配合:
- 节点/进程故障:由"负载均衡器 + 平台级自愈(如 Kubernetes controller)"共同兜底——负载均衡器在某个 Vector 进程不可达时自动故障转移;
- 负载均衡器自身故障:通过服务发现或 DNS 故障转移到备用负载均衡器(这正是 RFC 中
resolvers coredns+server-template动态发现机制的价值所在); - 聚合器整体故障:同样依赖服务发现与 DNS 完成故障转移。
从 aggregator.md 的生产部署建议也能看到一致的导向:"在每个网络边界内部署多个聚合器""使用 DNS 或服务发现将 Agent 流量路由到聚合器""尽量使用基于 HTTP 的协议""使用vectorsource 与 sink 做 Vector 间通信"。这与 RFC 的 HAProxy + headless Service 方案形成了架构层面的一致闭环。
规划中的实施路径(Plan Of Attack)
RFC 为方案落地列出了明确的实施清单,可视为该能力从设计到交付的路线图:
- 手工验证 Vector Agent、Datadog Agent、syslog 三类流量经过代理后的功能正确性;
- 将(可选的)代理部署纳入 vector-aggregator Chart,加入 Kubernetes e2e 测试套件并补充文档;
- 提供 Datadog Agent 在多个 Vector 聚合器间负载均衡的开箱即用配置,加入 e2e 测试与文档;
- 提供开箱即用的代理可观测性数据采集与处理配置(Datadog Agent 与 Vector 双通道),让用户可以像路由其他数据一样路由代理的日志与指标,并补充文档。
这条路线体现了 RFC 的一个设计原则:负载均衡能力必须"开箱即用",同时把可观测性(代理自身的日志、指标、健康)也纳入统一的数据管道——这也解释了 HAProxy 被选为首选代理的原因之一(原生 Prometheus / JSON 指标输出)。
总结
RFC 7469 为 Vector 聚合器在 Kubernetes 中的水平扩展给出了清晰、务实的答案:用一个随 Chart 交付、支持 DNS 动态服务发现的 HAProxy 反向代理,把来自 Vector Agent、Datadog Agent 与 syslog(TCP)的流量均衡到 headless Service 背后的一组 StatefulSet 副本上。它通过"外部代理 + Kubernetes 原生服务发现"的组合,兼顾了协议覆盖面、运维友好度与厂商中立性,同时明确划定了 UDP 支持的边界;而"内置负载均衡"的演进方向则在后续版本中以vectorsink 的LoadBalance策略在源码层面得到了实现。对于希望在 Kubernetes 中以高可用、可水平扩展方式运行 Vector 聚合器的用户,本文的配置与权衡分析可直接作为架构决策与落地参考。
【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考