抓包不如“开天眼”:用 eBPF 搭一条实时流量取样与可视化流水线

举报
Echo_Wish 发表于 2026/02/26 15:07:41 2026/02/26
【摘要】 抓包不如“开天眼”:用 eBPF 搭一条实时流量取样与可视化流水线

抓包不如“开天眼”:用 eBPF 搭一条实时流量取样与可视化流水线

作者:Echo_Wish

很多做运维的兄弟,排查问题第一反应是什么?

tcpdump 走起。

然后抓一堆包,导到 Wireshark,CPU 飙升,磁盘爆满,线上同事盯着你:“哥,别搞了行不行?”

说句实在话,传统抓包是“事后诸葛亮”
我们真正需要的是——

实时、低开销、可持续运行的流量观测能力。

这几年让我彻底改观的技术,就是:

eBPF

它让我们不用改内核,不用重启机器,就能在内核里插“探针”。
不是抓全量,而是聪明地取样

今天我带你搭一条完整的实时流量取样 + 可视化流水线:

eBPF 程序 → 用户态收集 → 流式聚合 → 可视化展示

我们一步步拆。


一、为什么不是 tcpdump,而是 eBPF?

传统抓包:

  • 全量抓
  • 高 I/O
  • 高 CPU
  • 不适合长期运行

而 eBPF:

  • 在内核层过滤
  • 只上传关键数据
  • 取样可控
  • 性能开销极低

你可以把它理解成:

在内核里装了一个“聪明的流量筛子”。


二、核心思路:内核只做取样,不做重活

我们先写一个简单的 eBPF 程序,挂载在 tc ingress 点,做流量采样。

使用 Python 的 bcc 框架(底层也是基于 eBPF):

from bcc import BPF

program = """
#include <uapi/linux/ptrace.h>
#include <linux/skbuff.h>

BPF_HASH(packet_cnt, u32, u64);

int count_packets(struct __sk_buff *skb) {
    u32 key = 0;

    // 简单采样:1/100 概率
    if (bpf_get_prandom_u32() % 100 != 0) {
        return TC_ACT_OK;
    }

    u64 *val, zero = 0;

    val = packet_cnt.lookup_or_init(&key, &zero);
    (*val)++;

    return TC_ACT_OK;
}
"""

b = BPF(text=program)
fn = b.load_func("count_packets", BPF.SCHED_CLS)

注意这里的逻辑:

bpf_get_prandom_u32() % 100

这就是采样控制点。

不是抓 100%,
而是 1%。

这意味着什么?

如果你的机器 10Gbps 流量,
你只处理 100Mbps 的元数据。

这就是性能差距。


三、别在内核里做复杂分析

很多人第一次写 eBPF,会忍不住想:

  • 统计 RTT
  • 解析 HTTP
  • 计算延迟分布

我劝一句:别。

内核只负责采样与计数。

真正的分析放在用户态。

我们可以在用户态读取 map:

import time

while True:
    time.sleep(1)
    for k, v in b["packet_cnt"].items():
        print("sampled packets:", v.value)

这一步,你就已经实现了:

  • 实时采样
  • 每秒输出统计
  • 几乎无性能影响

四、升级:按源IP聚合

我们改造一下,让它按源 IP 统计。

BPF_HASH(ip_cnt, u32, u64);

int count_packets(struct __sk_buff *skb) {
    if (bpf_get_prandom_u32() % 100 != 0) {
        return TC_ACT_OK;
    }

    u32 src_ip = skb->remote_ip4;

    u64 *val, zero = 0;
    val = ip_cnt.lookup_or_init(&src_ip, &zero);
    (*val)++;

    return TC_ACT_OK;
}

然后在用户态做聚合:

for k, v in b["ip_cnt"].items():
    print("IP:", k.value, "count:", v.value)

这时候你已经拥有:

实时 Top IP 监控能力。

比起传统流量分析工具,
它的优势是:

  • 无需 sidecar
  • 不侵入应用
  • 内核级可见性

五、把数据推入可视化流水线

观测不是为了打印日志。

我们要画图。

推荐两种方案:

  • 推送到 Prometheus
  • 或发给 Apache Kafka

例如,推到 Prometheus:

from prometheus_client import Gauge, start_http_server

g = Gauge('sampled_packets', 'Sampled packets per second')

start_http_server(8000)

while True:
    total = 0
    for k, v in b["packet_cnt"].items():
        total += v.value
    g.set(total)
    time.sleep(1)

然后用:

Grafana

画出实时流量趋势图。

这就是完整流水线:

eBPF → Python exporter → Prometheus → Grafana

六、真实生产场景怎么玩?

场景一:防止流量突增

采样统计 QPS,如果瞬间翻倍:

  • 自动触发告警
  • 自动扩容
  • 或启用限流策略

场景二:检测异常 IP

通过 Top N 分析:

  • 发现 DDoS 早期征兆
  • 识别异常扫描行为

场景三:流量画像

  • 内部服务调用关系
  • TCP 重传率
  • 延迟分布

eBPF 能挂的点非常多:

  • kprobe
  • tracepoint
  • tc
  • XDP

真正牛的团队,是把它当成“内核观测操作系统”。


七、性能对比的真实感受

我做过一次测试:

  • tcpdump 全量抓:CPU 40%
  • eBPF 1% 采样:CPU 3%

差距不是一点点。

而且 eBPF 程序运行在内核安全沙箱里,不会崩机器。

这就是它的恐怖之处。


八、别走偏:eBPF 不是银弹

我要泼点冷水。

eBPF 很强,但:

  • 调试难度高
  • 版本依赖多
  • 内核差异坑不少

如果只是偶尔排查问题,
你不一定非要上它。

但如果你在做:

  • 高并发系统
  • 金融级稳定性要求
  • 边缘节点监控

那它几乎是必备能力。


九、一个更成熟的架构

如果你想进阶,可以参考:

Cilium
Pixie

这些系统本质上都是:

eBPF + 流式处理 + 可视化平台

它们已经帮你封装好了复杂逻辑。


最后的思考

运维的本质,不是救火。

是让系统“自我可见”。

以前我们是:

出事了再抓包。

现在我们应该是:

实时看到趋势,提前干预。

eBPF 给我们的不是工具。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。