主题
把数据接出去:flowprobe 与 Prometheus
前面几篇讲了该看哪些计数器、怎么读 trace。但那些都是人坐在 CLI 前的操作。 生产环境需要的是把数据持续接到监控系统里。
这一篇讲两条出口,顺便回答第 4 章留下的一个问题: DET44 免掉了会话日志,那确实需要流日志的时候用什么?
flowprobe:IPFIX 流导出
IPFIX 是 NetFlow 的标准化后继,用来把"谁和谁通信了多久多少字节"导出给采集器。
bash
# 1. 先配导出目标
set ipfix exporter collector <采集器IP> src <本机IP> [template-interval <秒>]
# 2. 配记录哪些层、两个定时器
flowprobe params record [l2] [l3] [l4] [active <秒>] [passive <秒>]
# 3. 挂到接口
flowprobe feature add-del <接口> [l2|ip4|ip6] [rx|tx|both] [disable]
show flowprobe params / feature / table / statistics不配 exporter 就一条流都不记
这个坑没有任何提示。flowprobe feature add-del 会成功, show flowprobe feature 也显示挂上了,但:
bash
vppctl show flowprobe tabletext
Dumping IPFIX table
← 空的show flowprobe statistics 里 Pool utilisation 一直是 0%。
配上 set ipfix exporter 之后,流记录立刻开始出现。
应用配置
bash
./labctl reset base
./labctl apply base 18
./labctl verify base 18配好之后:
bash
./labctl vppctl base show flowprobe tabletext
Dumping IPFIX table
rx 1/0 ... 203.0.113.1 -> 203.0.113.11 6 43665 9000
rx 1/0 ... 203.0.113.1 -> 203.0.113.11 1 0 0两条流:TCP(协议 6,端口 43665→9000)和 ICMP(协议 1)。
一个必须知道的细节:它记的是 NAT 之后的地址
上面那条记录的源地址是 203.0.113.1 —— NAT 转换后的公网地址, 尽管 flowprobe 挂的是内网口的入向。
原因在 feature arc 上:
bash
./labctl vppctl base show interface features host-eth1text
ip4-unicast:
ip4-sv-reassembly-feature
nat-pre-in2out
flowprobe-input-ip4 ← 排在 NAT 后面flowprobe-input-ip4 排在 nat-pre-in2out 之后。
这对采集侧影响很大
text
你的 IPFIX 收集器看到的是**公网侧的五元组**,
而不是"哪台内网主机干的"。想把流量归因到具体用户,还得把 flowprobe 的记录和 NAT 的会话表 (或者 DET44 的算法)对起来 —— 两份数据在时间上还得对齐。
这正好解释了第 4 章那句话:DET44 免掉的是"会话映射日志",不是"全部日志"。 你仍然需要流日志来知道用户访问了哪里,只是不再需要日志来回答 "这个公网端口是谁"。
对照一下两种方案:
text
┌──────────────────┬────────────────────┬──────────────────────┐
│ │ 传统 NAT + 流日志 │ DET44 + 流日志 │
├──────────────────┼────────────────────┼──────────────────────┤
│ 端口 → 用户 │ 查会话日志(TB 级) │ 一条命令算出来 │
│ 用户访问了哪里 │ 查流日志 │ 查流日志(同样需要) │
│ 存储量 │ 会话日志 + 流日志 │ 只有流日志 │
└──────────────────┴────────────────────┴──────────────────────┘两个定时器
bash
vppctl show flowprobe paramstext
l3 l4 active: 10 passive: 30text
active 长流每隔多久导出一次中间记录
passive 流静默多久后判定结束并导出最终记录active 太长,长连接的流量要很久才反映到监控里;太短则导出报文量暴增。 生产上常见 60s / 15s 这个量级。
Prometheus:把全部统计暴露成 HTTP 端点
VPP 的 prom 插件把内部统计以 Prometheus 格式吐出来。
bash
# 1. 启动 HTTP 服务(注意 uri 必须在第一次调用时就给)
http static server www-root /tmp/www uri tcp://0.0.0.0/80 url-handlers
# 2. 打开 prometheus 导出
prom enable
# 端点:http://<VPP接口地址>/stats.prom两个坑,都会让人卡很久
一、http static server 的 uri 必须在第一次调用时给。
如果先执行了不带 uri 的版本:
bash
vppctl http static server url-handlers # 少了 uri
vppctl http static server ... uri tcp://0.0.0.0/80 ...text
http static server: http static server already initialized...改不了,只能重启 VPP。
二、这个 HTTP 服务跑在 VPP 自己的 host stack 上,不是容器/主机的内核栈。
所以:
bash
docker exec <容器> ss -lnt | grep :80 # 什么都看不到
docker exec <容器> curl http://127.0.0.1/stats.prom # Connection refused必须从别的节点,用 VPP 的接口地址访问:
bash
docker exec clab-natbase-s1 python3 -c "
import urllib.request
print(urllib.request.urlopen('http://203.0.113.1/stats.prom').read().decode()[:200])
"我在这上面卡了几轮 —— 一直以为服务没起来, 直到从外部访问收到一个 HTTP 404(而不是连接拒绝), 才意识到服务其实在跑,只是路径写错了、而且不能从本机 loopback 访问。
"404 而不是 connection refused"是个很有价值的信号: 它说明网络这一层是通的,问题在应用层。
抓到的内容:
text
# TYPE vpp_sys_heartbeat counter
vpp_sys_heartbeat 5.00
# TYPE vpp_sys_last_stats_clear counter
vpp_sys_last_stats_clear 0.00
# TYPE vpp_sys_boottime counter
vpp_sys_boottime 1788509264.00标准的 Prometheus 文本格式,可以直接被 scrape。
一次全量抓取 1.8 MB
生产上必须筛选
VPP 把所有统计都吐出来 —— 每个接口每个方向的每个计数器。 本实验环境只有 3 个接口,一次抓取就接近 1.8 MB。
几百个接口的设备一次能到几十 MB,Prometheus 那边的存储和查询都会很难看。
bash
vppctl prom patterns add <模式> # 只导出匹配的指标
vppctl prom enable used-only # 只导出非零的
vppctl prom patterns show # 看当前筛选规则
vppctl prom enable min-scrape-interval <秒> # 限制抓取频率used-only 是最省事的一刀 —— 大量计数器恒为零,导出它们纯属浪费。
该监控什么
结合第 7 章的故障签名,最值得接进告警的:
text
┌────────────────────────────┬────────────────────────────────┐
│ 指标 │ 为什么重要 │
├────────────────────────────┼────────────────────────────────┤
│ NAT 会话数 / 上限 │ 逼近上限时新连接开始失败 │
│ out of ports 计数 │ 地址池耗尽,已经在影响用户 │
│ maximum sessions exceeded │ 会话表满 │
│ no translation 计数增速 │ 突然加速通常是会话老化误伤 │
│ ACL deny 计数 │ 突增可能是策略配错或遭遇扫描 │
│ 各接口的 drop 计数 │ 任何非零都值得看一眼 │
│ Vectors/Call │ 持续为 1 说明收包路径有问题 │
└────────────────────────────┴────────────────────────────────┘取差值,不要取绝对值
show errors 和 Prometheus 导出的都是累计值。 告警规则要基于增长速率,不是绝对数字 —— 一台跑了半年的设备累计几百万个 no translation 完全正常 (背景扫描),但每秒新增几百个就是事故。
小结
| flowprobe | IPFIX 流导出,答"用户访问了哪里" |
| 前置条件 | 必须先 set ipfix exporter,否则一条不记且无提示 |
| 位置 | arc 上排在 NAT 之后 → 记的是转换后的地址 |
| 定时器 | active(长流中间记录)/ passive(流结束判定) |
| Prometheus | http static server ... uri ... + prom enable,端点 /stats.prom |
| 坑一 | http static server 的 uri 必须首次调用就给,否则只能重启 VPP |
| 坑二 | 跑在 VPP host stack,ss 看不到,不能从 127.0.0.1 访问 |
| 生产必做 | prom patterns / used-only 筛选,否则一次抓取几十 MB |
| 告警原则 | 取增长速率,不取累计绝对值 |