- 网络安全
- 网络
- IDS
【免费下载链接】zeek
Zeek is a powerful network analysis framework that is much different from the typical IDS you may know.
集群环境下,事件在节点之间经由后端(Backend)序列化、发布与接收,其规模、分布与流向直接影响集群的负载健康度。Cluster::Telemetry是 Zeek 为此提供的内置遥测模块:它通过少量可重定义(&redef)的配置项,控制核心后端(Core)与 WebSocket 后端分别记录哪些维度的事件指标,并借助 Zeek 的 telemetry 框架 将计数、标签与直方图暴露给 Prometheus 等监控系统。读完本文,你将掌握Cluster::Telemetry::Type三种指标级别的语义与生成的指标名、四个配置项的默认值与调优方法、topic 归一化机制,以及从脚本配置到 C++ 装配触发的完整实现链路。
一、模块概览:为谁记录、记录什么
集群遥测解决的问题很具体:在核心后端(如 Broker/ZeroMQ)与 WebSocket 后端上,入站(incoming)与出站(outgoing)事件各自经历了多少次、多大体积、来自哪些 handler 与 topic。Cluster::Telemetry模块不负责传输本身,而是在事件序列化/反序列化路径上挂接“探针”,把每次发布与接收的现场信息转换成遥测指标。
模块的脚本定义位于 scripts/base/frameworks/cluster/telemetry.zeek,其 API 文档(即本文主题)位于 doc/scripts/base/frameworks/cluster/telemetry.zeek.rst。C++ 侧接口与实现在 src/cluster/Telemetry.h 与 src/cluster/Telemetry.cc。
在 C++ 中,遥测被建模为挂在Backend之上的一个抽象实例(zeek::cluster::detail::Telemetry),并通过TelemetryScope区分Core与WebSocket两种作用域(见 src/cluster/Telemetry.h)。核心后端与 WebSocket 后端各自维护独立的启用集合,因此两者可以有不同的指标粒度。
二、指标级别:INFO / VERBOSE / DEBUG
模块的核心类型是枚举Cluster::Telemetry::Type,它决定了“记录到什么粒度”,三个枚举值定义于 scripts/base/frameworks/cluster/telemetry.zeek,语义如下:
| 枚举值 | 指标形态 | 标签 | 典型用途 |
|---|---|---|---|
INFO | 计数器(Counter) | 无标签 | 只关心集群整体的事件吞吐 |
VERBOSE | 计数器族(CounterFamily) | topic(归一化后)、handler | 分析具体事件类型/处理函数的流量分布 |
DEBUG | 直方图族(HistogramFamily) | topic、handler、script_location(仅出站) | 诊断序列化消息体积与脚本调用位置 |
INFO:无标签计数
INFO为每个后端创建两个无标签计数器指标:
zeek_cluster_<name>_outgoing_events:出站事件总数;zeek_cluster_<name>_incoming_events:入站事件总数。
其中<name>取core或websocket。对应实现见 src/cluster/Telemetry.cc,指标名通过util::fmt("cluster_%s_outgoing_events", name)生成,并以zeek为前缀注册到 telemetry 管理器;每次事件触发时仅执行out->Inc()/in->Inc()(src/cluster/Telemetry.cc),开销极小,因此也是默认启用的级别。
VERBOSE:带 topic 与 handler 的计数
VERBOSE为每个后端创建带标签的计数器族:
zeek_cluster_<name>_verbose_outgoing_eventszeek_cluster_<name>_verbose_incoming_events
标签为topic(归一化后的topic 名)与handler(事件处理函数名),见 src/cluster/Telemetry.cc。指标采用CounterFamily+GetOrAdd动态创建标签组合的方式(src/cluster/Telemetry.cc),因此每个不同的(topic, handler)组合都会产生一条独立的时间序列。
DEBUG:消息体积直方图
DEBUG使用序列化后的消息字节数作为观测值,为每个后端创建直方图族:
zeek_cluster_<name>_debug_outgoing_event_sizeszeek_cluster_<name>_debug_incoming_event_sizes
标签为topic、handler,出站指标额外携带script_location(触发发布的脚本文件与行号),入站指标则刻意去掉该标签(因为入站事件的“来源位置”在远端,无本地方言意义)。实现见 src/cluster/Telemetry.cc:出站通过determine_script_location()回溯脚本调用栈,从CallExpr的位置信息中提取文件:行号,并缓存到location_cache避免重复计算(src/cluster/Telemetry.cc)。直方图的桶由message_size_bounds决定(见下文)。
三个级别通过CompositeTelemetry组合(src/cluster/Telemetry.h):只要某级别被启用,对应子实例就被加入组合器,事件触发时逐个转发,互不干扰。
三、配置项详解:四个&redef选项
模块暴露四个可重定义选项,全部带&redef属性,可被脚本层增量修改。
1.core_metrics与websocket_metrics:开关集合
## The telemetry types to enable for the core backend. const core_metrics: set[Type] = { INFO, } &redef; ## The telemetry types to enable for WebSocket backends. const websocket_metrics: set[Type] = { INFO, } &redef;二者类型均为set[Cluster::Telemetry::Type],默认只启用INFO。core_metrics作用于核心后端(例如 src/zeek-setup.cc 中的configure_backend_telemetry(*cluster::backend, "core")),websocket_metrics作用于 WebSocket 后端(src/cluster/websocket/WebSocket.cc 中的configure_backend_telemetry(*backend, "websocket", {{"app", application_name}}),注意 WebSocket 后端会额外附加app静态标签,其值为应用名)。
开启更细粒度级别的典型写法是+=:
redef Cluster::Telemetry::core_metrics += { Cluster::Telemetry::VERBOSE, }; redef Cluster::Telemetry::websocket_metrics += { Cluster::Telemetry::DEBUG, };启用的级别越多,指标基数越大,尤其是在VERBOSE/DEBUG下 topic 与 handler 的组合数量可能很多,需结合“指标爆炸”风险评估(见第六节)。
2.message_size_bounds:DEBUG 直方图桶
## For the DEBUG metrics, the histogram buckets to use. const message_size_bounds: vector of double = { 10.0, 50.0, 100.0, 500.0, 1000.0, 5000.0, 10000.0, 50000.0, } &redef;类型为vector of double,默认 8 个桶:10.0, 50.0, 100.0, 500.0, 1000.0, 5000.0, 10000.0, 50000.0(单位为字节)。它仅影响DEBUG指标:configure_backend_telemetry在装配DebugTelemetry时读取该向量并转换成 C++ 的std::vector<double>(src/cluster/Telemetry.cc),随后注册到HistogramFamily(src/cluster/Telemetry.cc)。
当VERBOSE/DEBUG需要观察的消息体积区间与默认桶明显不符时(例如集群普遍传输 MB 级载荷),可以整体重定义:
redef Cluster::Telemetry::message_size_bounds = { 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, };3.topic_normalizations:归一化含随机部分的 topic
## Table used for normalizing topic names that contain random parts. ## Map to an empty string to skip recording a specific metric ## completely. const topic_normalizations: table[pattern] of string = { [/^zeek\/cluster\/nodeid\/.*/] = "zeek/cluster/nodeid/__normalized__", } &ordered &redef;类型为table[pattern] of string,带&ordered属性(保证 pattern 按声明顺序匹配)。它的存在是为了解决一个真实的监控问题:含随机部分的 topic 会导致指标基数无限增长。例如节点 ID topiczeek/cluster/nodeid/<随机ID>/...每启动一个节点就产生一组新标签,直接进VERBOSE/DEBUG指标必然拖垮监控系统。该表把这类 topic 归一到固定模板,例如把上述随机 ID 归一为zeek/cluster/nodeid/__normalized__。
两处细节值得注意:
- 匹配不上时原样返回:
TableTopicNormalizer通过LookupPattern查询,无匹配则返回原始 topic(src/cluster/Telemetry.cc); - 映射为空字符串 = 跳过该指标:文档明确说明“Map to an empty string to skip recording a specific metric completely”,即把某类 topic 映射为
""可完全停止记录对应指标。
ZeroMQ 后端的真实重定义示例:由于 ZeroMQ 后端使用点分隔符(dot separator)构造 topic,而 base 层默认表用的是斜杠分隔,因此 scripts/policy/frameworks/cluster/backend/zeromq/options.zeek 用+=追加了对应规则:
redef Cluster::Telemetry::topic_normalizations += { [/^zeek\.cluster\.nodeid\..*/] = "zeek.cluster.nodeid.__normalized__", };这正是文档中“Redefinition”一节展示的内容:在加载 ZeroMQ 策略后,点分式 nodeid topic 也被归一。由此可以看到该表的设计意图——不同后端、不同部署形态都可以通过redef ... +=增量补充自己的归一规则,且&ordered保证规则顺序可控。
四、指标装配:从配置到后端的一次性注入
脚本层的set/vector/table如何变成后端实例上的指标?关键函数是configure_backend_telemetry(src/cluster/Telemetry.cc),其流程为:
- 根据
name(core或websocket,其他值直接FatalError)拼接变量名Cluster::Telemetry::<name>_metrics,读取对应的set; - 遍历集合中的每个
Type枚举值:INFO→ 实例化InfoTelemetry(无标签计数器);VERBOSE→ 实例化VerboseTelemetry,注入TableTopicNormalizer(即读取topic_normalizations表);DEBUG→ 实例化DebugTelemetry,注入TableTopicNormalizer与message_size_bounds桶;- 其他值 →
FatalError;
- 把各子实例加入
CompositeTelemetry,最后backend.SetTelemetry(...)注入后端。
两个调用点分别对应两类后端:
- 核心后端:Zeek 启动流程中,集群后端实例化完成后立即调用(src/zeek-setup.cc);
- WebSocket 后端:
WebSocket.cc内装配后端时调用,并携带app静态标签(src/cluster/websocket/WebSocket.cc)。
五、触发点:事件进出后端的钩子位置
遥测并不旁路事件流,而是内嵌在 Backend 的默认发布/接收实现中,见 src/cluster/Backend.cc:
- 出站:
DoPublishEvent在event_serializer->SerializeEvent(...)序列化完成后,用buf.size()构造SerializationInfo并调用Telemetry().OnOutgoingEvent(topic, event.HandlerName(), ...)(src/cluster/Backend.cc)。这里的SerializationInfo正是 DEBUG 直方图观测值的来源; - 入站:
ProcessEventMessage在UnserializeEvent成功解析后,用payload.size()调用Telemetry().OnIncomingEvent(topic, r->HandlerName(), ...)(src/cluster/Backend.cc)。
可见:无论走哪个具体后端(Broker/ZeroMQ/WebSocket),只要继承Backend的默认序列化路径,遥测钩子就自动生效,指标口径天然与“实际序列化字节数”一致。
指标最终经由 Zeek 的 telemetry 管理器注册到底层 Prometheus 库(基于 prometheus-cpp):CounterInstance/CounterFamily/HistogramFamily统一使用zeek前缀并拼出完整 Prometheus 指标名(src/telemetry/Manager.cc)。因此所有cluster_*指标的外部名称形如zeek_cluster_core_outgoing_events、zeek_cluster_websocket_debug_incoming_event_sizes等,可直接被 Prometheus 抓取。
六、实战建议与验证方法
监控过载的配套指标
scripts/policy/frameworks/cluster/backend/zeromq/options.zeek 明确指出:ZeroMQ 部署下应监控zeek_cluster_zeromq_xpub_drops_total与zeek_cluster_zeromq_onloop_drops_total,任何非零值都意味着集群过载;而要更深入了解“发布/接收的事件本身”,则应借助Cluster::Telemetry::core_metrics/websocket_metrics打开更细粒度的事件遥测。两者配合使用:drops 告诉你“有没有丢”,事件遥测告诉你“在传什么、传多大”。
按需启用,警惕指标爆炸
- 仅需整体吞吐 → 保持默认
INFO; - 需要区分事件类型/处理函数 → 追加
VERBOSE; - 需要诊断消息体积与脚本热点 → 追加
DEBUG,并根据实际负载调整message_size_bounds; - 遇到带随机 ID 的 topic(节点 ID、会话 ID 等)→ 务必在
topic_normalizations中补充归一规则,防止标签基数失控;不需要的类别可映射为空字符串以完全跳过记录。
用 btest 测试验证配置行为
仓库自带完整的遥测验证测试,可直接作为“如何启用并读取指标”的参考:
- testing/btest/cluster/telemetry/two-nodes.zeek:双节点 ZeroMQ 集群,在公共脚本中
redef Cluster::Telemetry::core_metrics += { Cluster::Telemetry::VERBOSE, };,并在zeek_done()中用Telemetry::collect_metrics("zeek", "cluster_core_*")与cluster_websocket_*前缀收集全部指标,逐个打印前缀、名称、标签名、标签值与数值; - testing/btest/cluster/telemetry/ws.zeek:同时启用
core与websocket的VERBOSE,通过 WebSocket 客户端发送 100 个 ping 事件并回包,最后断言zeek_cluster_*指标数量并打印明细,覆盖了入站/出站两个方向与 topic 标签维度。
测试中的redef ... +=用法与Telemetry::collect_metrics()收集方式,是生产环境排查时“确认遥测已生效”的最直接手段。
七、小结
Cluster::Telemetry用四个&redef选项把“集群事件观测”这件事收敛得非常克制:默认零额外开销(仅INFO计数器),需要时可逐级放开到带标签计数(VERBOSE)乃至消息体积直方图(DEBUG);topic_normalizations则从机制上防止随机 topic 拖垮指标基数。底层由 src/cluster/Telemetry.cc 的三类实现(InfoTelemetry/VerboseTelemetry/DebugTelemetry)挂接在Backend的序列化路径上,与 Prometheus 指标体系无缝衔接。对于 Zeek 集群运维者,这是一组“低门槛、高价值”的内置观测能力:先盯住 drops 指标发现过载,再按需打开事件遥测定位流量构成,即可快速形成一套完整的事件链路可观测闭环。
- 网络安全
- 网络
- IDS
【免费下载链接】zeek
Zeek is a powerful network analysis framework that is much different from the typical IDS you may know.
相关推荐
Authelia 遥测(Telemetry)配置指南:启用 Prometheus 指标采集与监控
Authelia 遥测(Telemetry)配置指南:启用 Prometheus 指标采集与监控 本文基于 Authelia 官方配置文档,系统讲解 telem
后端认证鉴权单点登录身份认证应用安全Zeek Telemetry Framework 实战指南:从指标类型到 Prometheus 采集
Zeek Telemetry Framework 实战指南:从指标类型到 Prometheus 采集 Telemetry 框架是 Zeek 内建的运行时度量体系
网络安全网络IDSCoroot Cluster Agent 配置完全指南:集群级遥测采集与数据库监控
Coroot Cluster Agent 配置完全指南:集群级遥测采集与数据库监控 Coroot 的可观测性体系由两类 Agent 组成:部署在每个节点上的 c
可观测性指标监控链路追踪APM
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考