惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
量子位
腾讯CDC
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
B
Blog
S
SegmentFault 最新的问题
P
Privacy & Cybersecurity Law Blog
T
Threatpost
博客园 - 聂微东
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
C
Check Point Blog
N
Netflix TechBlog - Medium
D
DataBreaches.Net
爱范儿
爱范儿
IT之家
IT之家
S
Secure Thoughts
M
MIT News - Artificial intelligence
NISL@THU
NISL@THU
C
Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
有赞技术团队
有赞技术团队
A
Arctic Wolf
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
Schneier on Security
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
G
GRAHAM CLULEY
雷峰网
雷峰网
Project Zero
Project Zero
博客园 - Franky
H
Heimdal Security Blog
A
About on SuperTechFans
Security Latest
Security Latest
Webroot Blog
Webroot Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】SLO 工程:可靠性的量化管理 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计】DDD 战略设计:限界上下文与上下文映射 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 排序基准测试:用数据说话
【可观测性工程】网络可观测性:Cilium Hubble、Pixie、DeepFlow、Tetragon
2026-04-22 · via 土法炼钢兴趣小组的算法知识备份

网络可观测性(Network Observability)是可观测性工程中最靠近基础设施、却又越来越靠近业务语义的一个方向。传统运维视角下的网络监控,关注的是带宽、丢包、重传、路由这些链路层与传输层指标;而微服务时代的网络可观测性,更多是回答这样的问题:

  • 为什么前端调用订单服务偶发 502?是应用返回的,还是 Envoy 返回的,还是 kube-proxy 转发过程中连接被重置?
  • 一个 gRPC 请求从 A 服务到 B 服务,中间跨了几次网络跳数?每一跳的时延是多少?
  • 某条 MySQL 查询耗时 800 毫秒,到底是 SQL 慢,还是 TLS 握手慢,还是 TCP 层出现了重传?
  • 某 Pod 的异常出站连接是正常的服务调用,还是被植入的挖矿程序在外联?

要回答这些问题,单纯靠应用内埋点(即 APM)是不够的,因为很多问题根本不在应用的代码路径上;而只看传统的 SNMP、NetFlow 也不够,因为它们看不到 L7 协议语义,也看不到 Kubernetes 的容器上下文。

扩展可编程内核的伯克利包过滤器(eBPF,extended Berkeley Packet Filter)技术的成熟,使得”在内核中直接捕获网络事件、在采集点注入容器元数据、在用户态做 L7 协议解析”这条路径变得工程化可行。本文围绕这条主线,依次讲解:

  • 网络可观测性的分层模型;
  • eBPF 采集点的几种典型 Hook;
  • 目前业界主流的网络可观测工具:Cilium Hubble、Tetragon、Pixie、DeepFlow;
  • TLS 解密、HTTP/2 解析、服务拓扑发现等工程难点;
  • 大流量场景下的坑与选型建议。
网络可观测性分层与 eBPF 采集点

一、网络可观测性的层次

网络可观测性必须分层来看。每一层能回答的问题不同,采集成本、实现难度也不同。

1.1 分层视角

按照开放系统互连(OSI,Open Systems Interconnection)模型,网络可观测性一般聚焦三层:

  • L3(IP 层):关注 IP 报文的路由、丢包、分片、因特网控制报文协议(ICMP,Internet Control Message Protocol)事件。典型指标:每秒丢包数、路由跳数、目的不可达率。
  • L4(传输层 TCP/UDP):关注连接的生命周期、重传、往返时延(RTT,Round-Trip Time)、窗口缩放、连接重置。典型指标:建连成功率、重传率、单连接吞吐、TCP 队列长度。
  • L7(应用层):关注 HTTP 状态码、gRPC 响应码、DNS 查询结果、数据库 SQL 语句及耗时、Redis 命令、Kafka 消息体 Header 等。典型指标:每秒请求数(RPS,Requests Per Second)、错误率、P99 时延。

三者并不是彼此替代的关系,而是互相补充。一个 5xx 错误爆发时,L7 指标会告诉你”哪个接口、哪个客户端、错误码是多少”,L4 指标会告诉你”是不是背后有大量连接被 RST 掉了”,L3 指标会告诉你”底层有没有物理丢包或路由黑洞”。

1.2 为什么 L7 对微服务最关键

单体架构时代,一次用户请求的路径基本就是:浏览器 → 负载均衡(LB)→ 应用服务器 → 数据库。监控这四个节点就基本看清了全貌。

微服务架构下,一次用户请求可能涉及几十次内部调用,调用之间通过 HTTP/gRPC/消息队列(MQ,Message Queue)串联。此时:

  1. L3/L4 指标即使全部正常,应用层也可能大量报错(例如服务端返回 400/500)。
  2. 出问题时,绝大多数问题定位需要 L7 的语义信息(“是哪个接口挂了”“是哪个下游返回了错误码”)。
  3. 调用链追踪(Tracing)虽然能补上这一块,但需要代码侵入式埋点,在异构语言栈、老系统、第三方组件里无法覆盖完全。

所以,L7 网络可观测性填补的恰恰是 APM 埋点覆盖不到的盲区:无侵入、面向东西向流量、以”网络行为”为第一视角来看服务间交互。

1.3 各层可回答问题对比

下面这张表是一个粗略的能力对比。

能力 L3(IP) L4(TCP/UDP) L7(应用)
网络是否通 间接
是否丢包 / 重传 有限
建连耗时 间接
请求耗时(应用视角) 近似
错误码 / 业务错误
区分用户、租户、接口
成本(CPU/存储)
是否需要协议解析
能否反映 TLS 内的细节 是(需要解密)

1.4 传统网络监控 vs eBPF 方案

传统网络监控的数据来源包括:

  • 简单网络管理协议(SNMP,Simple Network Management Protocol):拉取设备指标,面向网络设备。
  • NetFlow / sFlow / IPFIX:网络设备导出的流记录,以五元组为粒度。
  • 网络分流镜像(SPAN/TAP)+ 旁路嗅探:通过镜像流量到旁路分析设备。
  • libpcap / tcpdump:在主机侧抓包,开销较高。

这些方案的共性局限:

  1. 拿不到容器 / Pod 上下文。NetFlow 只知道 IP,对 Kubernetes 来说,Pod IP 是朝生暮死的。
  2. 看不透 L7,或要靠深度包检测(DPI,Deep Packet Inspection)硬件盒子,价格昂贵。
  3. 对加密流量无能为力。

基于 eBPF 的方案则具备:

  1. 在内核中直接采集,开销可控。
  2. 通过挂载到 sched_process_execcgroup 相关钩子,可以在事件源头就带上容器元数据。
  3. 通过 uprobe 挂到 OpenSSL/Go crypto 等库,可以在加密前/解密后取明文。
  4. 可以做到无须在物理设备上架设旁路,采集、过滤、聚合都在主机侧完成。

这是本文所有工具的共同技术底座。

二、eBPF 网络数据采集机制

不同工具采用的 eBPF Hook 点差别不小,理解这些 Hook 点的语义,是看懂工具架构的前提。

2.1 套接字过滤器(Socket Filter,SK_FILTER)

套接字过滤器是最古老的 BPF 程序类型之一。程序被挂到一个套接字(socket)上,内核会把该 socket 上收到的数据包拷贝一份传给程序,程序返回保留多少字节(0 表示丢弃该副本)。

特点:

  • 只能观测,不能修改或丢弃原始数据包(丢弃的是拷贝)。
  • 有数据包复制开销。
  • 不具备容器/进程上下文,但可以通过 socket cookie 关联。

典型使用者:tcpdump(libpcap 会生成 cBPF 程序)、BCC 工具链里的一些抓包脚本。

/* 伪代码:一个最朴素的 socket filter,保留所有 TCP 报文 */
SEC("socket")
int sk_filter_prog(struct __sk_buff *skb) {
    if (skb->protocol != __constant_htons(ETH_P_IP))
        return 0;
    __u8 proto = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));
    if (proto != IPPROTO_TCP)
        return 0;
    return -1;  /* -1 表示全部保留 */
}

在网络可观测性产品中,socket filter 通常不是主力,因为它的副本开销在高吞吐场景偏大。

2.2 流量控制挂钩(TC Hook)

Linux 流量控制(Traffic Control,简称 TC)子系统提供了 clsact 这个特殊 qdisc,允许把 eBPF 程序分别挂到入向(ingress)和出向(egress)。

特点:

  • 运行在网络协议栈较深的位置(IP 层之上、设备层之下),可以看到完整以太网帧。
  • 可以修改、重定向、丢弃数据包,因此不仅能观测,还能做策略执行、NAT、负载均衡等。
  • 延迟低于 socket filter,因为不需要副本。
  • 天然适合 Kubernetes 容器场景,每个 Pod 的虚拟以太网对(veth pair)都可以独立挂载。

Cilium 对 TC Hook 的使用最为激进:策略执行、服务负载均衡、可观测性采集都通过 TC 程序实现。Cilium Hubble 的流日志,主力来源就是挂在 TC ingress/egress 上的程序。

SEC("tc")
int tc_ingress(struct __sk_buff *skb) {
    struct flow_key key = {};
    parse_l3_l4(skb, &key);
    struct flow_stats *st = bpf_map_lookup_elem(&flow_map, &key);
    if (!st) {
        struct flow_stats zero = {};
        bpf_map_update_elem(&flow_map, &key, &zero, BPF_ANY);
        st = bpf_map_lookup_elem(&flow_map, &key);
    }
    if (st) {
        __sync_fetch_and_add(&st->rx_packets, 1);
        __sync_fetch_and_add(&st->rx_bytes, skb->len);
    }
    return TC_ACT_OK;
}

2.3 快速数据路径(XDP,eXpress Data Path)

XDP 是 Linux 网络栈中最早的可编程点,挂在网卡驱动(甚至网卡硬件,如部分 Mellanox 网卡)上。

特点:

  • 拦截点最早,甚至可以在分配 sk_buff 之前就判断是否要丢弃,单核 PPS 可达数千万量级。
  • 常用于:分布式拒绝服务(DDoS,Distributed Denial of Service)缓解、四层负载均衡(如 Facebook 的 Katran)、路由转发。
  • 没有 socket / 进程上下文,因为还未进入协议栈。

因此 XDP 并不适合直接用来做 L7 可观测性,但它可以承担:

  • 过滤掉不感兴趣的流量,减轻上层采集压力;
  • 做粗粒度的 L3/L4 统计,例如每秒同步泛洪(SYN Flood)包数。

Cilium 在 XDP 层做过负载均衡加速;Tetragon、Hubble 在可观测路径上主要还是靠 TC 与 kprobe。

2.4 内核函数探针(kprobe)

kprobe 允许在任意内核函数入口/返回处挂探针。网络可观测性里常用的几个:

  • tcp_sendmsg / tcp_recvmsg:采集应用写入/读取 TCP 缓冲区的大小、所处进程上下文。
  • tcp_close:连接关闭时计算连接总时长、重传计数。
  • sk_data_ready:有数据到来时触发,可以关联到具体 socket。
  • inet_csk_accept:TCP accept 完成时,采集服务端新连接信息。
  • kfree_skb:内核丢包入口,用于精细化分析丢包原因(通过 kfree_skb_reason,Linux 5.17+)。

kprobe 的优点是灵活:没有 TC 程序那么严格的限制,能直接拿到内核结构体字段。缺点是与内核版本强绑定,函数签名或内部结构变动会打破程序。

一站式编译一次到处运行(CO-RE,Compile Once – Run Everywhere)和 BPF 类型格式(BTF,BPF Type Format)缓解了这个问题,Hubble 和 DeepFlow 都以 CO-RE 方式分发 eBPF 程序。

2.5 用户态函数探针(uprobe)与 TLS 库

应用层流量越来越多使用传输层安全协议(TLS,Transport Layer Security)加密。从 TC/socket filter 这种”网卡之后、应用之前”的位置看,拿到的是密文,无法解析 HTTP 等应用协议。

解决思路是在用户态库里挂 uprobe:

  • OpenSSLSSL_read / SSL_write,入口拿到缓冲区指针,返回时缓冲区中是明文。
  • BoringSSL:类似 OpenSSL。
  • Go 标准库 crypto/tls:Go 将 TLS 实现自带,因此需要对 Go 二进制里的 crypto/tls.(*Conn).Readcrypto/tls.(*Conn).Write 做 uprobe;由于 Go 的栈布局与 ABI 与 C 不同,还需要特殊的 uretprobe 实现,详见 Pixie 的 go_tls_tracer
  • Java SSLEngine:Java 虚拟机(JVM,Java Virtual Machine)里的 TLS 由 JSSE 实现,可以挂到 sun.security.ssl.* 相关 JNI 符号,但覆盖面有限;实务中常配合字节码织入。
  • Node.js:基于 OpenSSL,可直接复用。

这样在不拿到服务端私钥、不做中间人代理的前提下,就能在源进程与目的进程两端的用户态”明文位置”采集到 HTTP/gRPC 明文。DeepFlow、Pixie、Hubble 的 L7 TLS 解析都采用这条路径。

Cilium 是基于 eBPF 的 Kubernetes 容器网络接口(CNI,Container Network Interface)实现,Hubble 则是在 Cilium 之上构建的网络与安全可观测性层。

3.1 Cilium 简介

Cilium 的核心理念:

  • 把 kube-proxy 用 eBPF 替代,减少 iptables 规则爆炸;
  • 用身份(Identity)而非 IP 进行网络策略,身份基于 Pod 标签;
  • 用 TC / XDP 程序做负载均衡、服务路由、策略执行、可观测。

从可观测性视角看,Cilium 在每个 Pod 的 veth 上挂了 TC 程序,这些程序天然能看到每个数据包,且已经持有了”来自哪个 Pod、去往哪个 Pod”的身份信息。这是 Hubble 得以低成本生成 L3/L4/L7 流日志的基础。

3.2 Hubble 组件

Hubble 的组件从节点到集群呈三级结构:

  • Hubble Daemon:与 Cilium Agent 同进程,运行在每个节点上,从 eBPF Map 中读取流事件,暴露节点级 gRPC API。
  • Hubble Relay:集群级组件,连接所有节点上的 Hubble Daemon,聚合流事件,对外暴露集群视角的 gRPC API。
  • Hubble UI:前端组件,调用 Hubble Relay 展示服务依赖图、流日志。
  • Hubble CLIhubble):命令行工具,连接 Relay 或单节点 Daemon。
+--------------+      +--------------+      +--------------+
|  Hubble UI   |<---->| Hubble Relay |<---->| Hubble Daemon| (node A)
+--------------+      |              |<---->| Hubble Daemon| (node B)
        ^             +--------------+      +--------------+
        |                                           ^
        | gRPC                                      | eBPF Map
        |                                           |
   hubble CLI ----------> Hubble Relay         Cilium Agent

3.3 流日志(Flow Log)格式

Hubble 的流事件由 flow.Flow Protobuf 定义,主要字段:

  • L3/L4:源/目的 IP、端口、协议;
  • 身份:源/目的 Identity(对应 Pod 标签集合);
  • Kubernetes 元数据:Namespace、Pod 名、Service 名、Workload 名;
  • 判决:ALLOWED、DROPPED、FORWARDED、ERROR;
  • L7(可选):HTTP method、path、status code,DNS query/response,Kafka topic 等。
{
  "time": "2026-04-22T09:12:31Z",
  "verdict": "FORWARDED",
  "source": {
    "identity": 18432,
    "namespace": "frontend",
    "pod_name": "web-7c8f6d9f6b-abc12",
    "labels": ["app=web", "version=v1"]
  },
  "destination": {
    "identity": 24815,
    "namespace": "order",
    "pod_name": "order-svc-5f9c8d7b6-xyz34",
    "labels": ["app=order-svc"]
  },
  "l4": {
    "TCP": {"source_port": 51234, "destination_port": 8080}
  },
  "l7": {
    "type": "REQUEST",
    "http": {"method": "POST", "url": "/api/v1/orders", "protocol": "HTTP/1.1"}
  }
}

3.4 Hubble 指标

Hubble 提供两类指标:

  • 节点级指标:Cilium Agent 自带的 cilium_* 指标,通过 /metrics 暴露,重点反映节点上的 Cilium 数据面状态。
  • 流量指标:Hubble Daemon / Relay 可开启 hubble_* 系列指标,覆盖 L3/L4/L7 维度。

典型指标:

  • hubble_flows_processed_total:按源/目的标签、判决、L7 协议等维度计数的流事件总数。
  • hubble_drop_total:按丢包原因(policy-denied、invalid-packet 等)聚合。
  • hubble_tcp_flags_total:TCP 标志位计数,用于发现大量 RST、SYN 等异常。
  • hubble_http_requests_total / hubble_http_response_duration_seconds:L7 HTTP 维度指标。
  • hubble_dns_queries_total / hubble_dns_responses_total:DNS 观察。

这些指标默认不会全部开启,需要通过 Cilium 配置显式启用,因为 L7 维度的高基数(High Cardinality)指标会显著放大 Prometheus 的成本。

3.5 Hubble CLI 实战

以下命令在实际运维中高频使用。

# 查看最近的流事件,带 Kubernetes 上下文
hubble observe --namespace order

# 仅看 L7 HTTP 流量,且状态码 >= 500
hubble observe --protocol http --http-status '5..'

# 查看丢包事件,按丢包原因分组
hubble observe --verdict DROPPED --output json | jq '.drop_reason' | sort | uniq -c

# 查看某 Pod 的出入流量
hubble observe --pod order/order-svc-5f9c8d7b6-xyz34

# 按服务标签过滤
hubble observe --to-label app=payment --from-label app=web

# 查看 DNS 查询
hubble observe --protocol dns

典型输出:

Apr 22 09:12:31.517  frontend/web-...abc12:51234 -> order/order-svc-...xyz34:8080 HTTP/1.1 POST /api/v1/orders FORWARDED
Apr 22 09:12:31.519  order/order-svc-...xyz34:8080 -> frontend/web-...abc12:51234 HTTP/1.1 500 Internal Server Error (12.3ms) FORWARDED

3.6 服务拓扑图

Hubble UI 基于累积的流事件自动生成服务依赖图:节点是 Pod/Service/Workload,边是观察到的调用方向,边的属性包含请求速率、错误率、时延。

这张图的工程价值在于:

  • 自动绘制,不需要手工维护架构图;
  • 随服务关系变化持续更新;
  • 可以按 Namespace 过滤,便于对齐组织结构;
  • 点击任意边,可以下钻到流日志。

3.7 网络策略可视化

Cilium 使用 CiliumNetworkPolicy(CNP)描述网络策略。Hubble 可以清楚展示:

  • 哪些流量被策略放行、哪些被拒绝;
  • 拒绝的具体策略对象是哪一个;
  • 策略变更前后的流量对比(配合 Hubble 的历史数据)。

这在灰度收紧零信任网络(Zero Trust Network)策略时非常关键:你可以先把策略跑在”审计模式”,用 Hubble 观察会被拒绝哪些流量,再真正开启强制执行。

3.8 部署与 Prometheus/Grafana 集成

以下是最小化的 Cilium + Hubble Helm 部署片段。

# values.yaml
kubeProxyReplacement: strict
k8sServiceHost: kube-apiserver.cluster.local
k8sServicePort: 6443

hubble:
  enabled: true
  metrics:
    enabled:
      - dns:query;ignoreAAAA
      - drop
      - tcp
      - flow
      - icmp
      - http
  relay:
    enabled: true
  ui:
    enabled: true

对应安装:

helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium \
  --namespace kube-system \
  -f values.yaml

# 访问 Hubble UI
cilium hubble ui

Prometheus 侧,给 Hubble Relay / Daemon 加 ServiceMonitor

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: hubble
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: hubble
  endpoints:
    - port: hubble-metrics
      interval: 30s

Grafana 侧,Cilium 官方提供了一整套仪表盘,覆盖 L3/L4/L7 指标与策略审计。

四、Tetragon:安全与可观测融合

Tetragon 同样出自 Isovalent(Cilium 团队),但关注点不同:它不是为了做流量分析,而是为了做运行时安全可观测。

4.1 Tetragon 定位

  • 运行时安全观测:在内核事件层(进程创建、文件打开、网络连接、能力变更)采集结构化事件,用于安全审计、威胁检测。
  • 强制执行(Enforcement):不仅能看,还能阻断(kill 进程、返回错误码)。
  • 声明式策略:使用 TracingPolicy 这个自定义资源(CR,Custom Resource)描述要挂哪些 kprobe、过滤条件、以及命中后的动作。

4.2 TracingPolicy 示例

下面这条策略,观测并记录所有对 /etc/shadow 的读取,且来自容器内进程的操作会被杀死:

apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: audit-etc-shadow
spec:
  kprobes:
    - call: "security_file_permission"
      syscall: false
      args:
        - index: 0
          type: "file"
        - index: 1
          type: "int"
      selectors:
        - matchArgs:
            - index: 0
              operator: "Equal"
              values:
                - "/etc/shadow"
          matchActions:
            - action: Sigkill

再来一个:监控对外发起的 TCP 连接,过滤非集群内的目的地址,辅助发现横向移动或 C2 外联。

apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: egress-connect-monitor
spec:
  kprobes:
    - call: "tcp_connect"
      syscall: false
      args:
        - index: 0
          type: "sock"
      selectors:
        - matchArgs:
            - index: 0
              operator: "NotDAddr"
              values:
                - "10.0.0.0/8"
                - "172.16.0.0/12"

4.3 与 Falco 的差异

Falco 同样是运行时安全工具,但:

  • Falco 既支持 eBPF,也支持内核模块;其规则是用自定义语法写的过滤表达式。
  • Tetragon 完全基于 eBPF,规则是 Kubernetes 原生 CR,与 Cilium 配套更紧密。
  • Tetragon 可以做内核级阻断(在系统调用返回前改写返回值),Falco 传统上偏向审计。
  • Tetragon 对进程树、容器上下文的构建更完整,天然与 Cilium Identity 对齐。

两者都有生产案例,选型看团队栈:以 Cilium 为底座,Tetragon 更顺滑;已有 Falco 生态则无必要切换。

4.4 与安全信息和事件管理系统(SIEM,Security Information and Event Management)集成

Tetragon 事件可以通过 JSON 流输出:

kubectl exec -n kube-system ds/tetragon -c tetragon -- tetra getevents -o compact

在生产中一般把事件通过 Fluent Bit / Vector 收敛到 Kafka,再入 SIEM(Splunk、Elastic、阿里云 SLS、腾讯 CLS 等)进行长期留存与关联分析。事件与 Hubble 的流事件可以用 Pod 身份、时间戳做 Join,把”安全事件”与”网络动作”串起来。

五、Pixie(New Relic)

Pixie 2019 年起由 Pixie Labs 开源,后被 New Relic 收购,现为云原生计算基金会(CNCF,Cloud Native Computing Foundation)沙箱项目。它的核心卖点是”零埋点、协议自动解析”。

5.1 架构

  • Pixie Edge Module(PEM):DaemonSet,每个节点一份。内部是一个使用 Arrow 列式存储的嵌入式数据库,承载采集到的事件。
  • Vizier:集群级控制面与查询引擎,接收 PxL 脚本并下发给 PEM,聚合结果。
  • Cloud / Self-hosted Cloud:用户访问入口(可部署在 New Relic 云上,也可自托管)。

整体上 Pixie 强调”数据不出集群”:默认情况下原始事件、协议负载都只存在 PEM 的内存/本地盘中,出集群的只有用户通过 PxL 脚本结果显式导出的数据。

5.2 协议自动解析

Pixie 在内核 uprobe / kprobe 以及 socket 缓冲区上采集数据,在用户态 PEM 做协议识别与解析。目前内建支持:

  • HTTP/1.x
  • HTTP/2 与 gRPC
  • DNS
  • MySQL
  • PostgreSQL
  • Redis
  • Kafka
  • 消息队列传输协议(MQTT,Message Queuing Telemetry Transport)
  • AMQP(部分版本)
  • Cassandra(CQL)

识别使用”协议指纹”策略:从 socket 的第一批字节中,尝试匹配已知协议的起始模式(如 HTTP 的方法前缀、MySQL 的握手包结构),匹配成功后,给该 socket 打上协议标签,后续按对应的状态机解析。

5.3 PxL 脚本语言

Pixie 的数据查询语言叫 PxL,语法类似 Python + Pandas:

import px

df = px.DataFrame('http_events', start_time='-5m')
df = df[df.resp_status >= 500]
df.svc = df.ctx['service']
df.latency_ms = df.latency / 1e6
df = df.groupby(['svc', 'req_path', 'resp_status']).agg(
    count=('latency_ms', px.count),
    p99=('latency_ms', px.quantiles),
)
px.display(df, 'slow_requests')

脚本在 Vizier 上解析,下发到每个 PEM 并发执行。这种模式相当于”把查询推到数据侧”,避免把原始数据集中存储。

5.4 开销与限制

官方基准显示,Pixie 默认配置下:

  • 每节点 PEM 约占用 1 个 CPU、2 GiB 内存;
  • 新增网络延迟可忽略;
  • 大流量节点(>10Gbps L7)CPU 可能爬升到 2~4 核。

限制:

  • 仅支持 Kubernetes,对虚拟机 / 裸机部署不友好;
  • 要求 Linux 内核 4.14+,某些 uprobe 特性要 5.x+;
  • 协议解析是开源内建的,扩展需改源码或通过自定义 PxL 脚本后处理。

5.5 与 OpenTelemetry 的协作

Pixie 提供 OTLP Exporter 相关能力(otel 插件及 px.export 接口),可以把 PxL 查询结果按 OpenTelemetry Metrics/Traces 协议发往外部后端。这样,Pixie 既可以作为独立观测平台使用,也可以作为 OpenTelemetry 生态里的”数据源”。

六、DeepFlow:国产开源的全栈网络可观测

DeepFlow 由云杉网络开源,是目前国内网络可观测领域最成熟的开源项目,在 CNCF Landscape 有登记。

6.1 项目定位

  • 全栈:同时覆盖网络层、服务层、应用层,主打”一套体系看穿南北向与东西向流量”。
  • 双数据面:eBPF 用于看进程、应用层协议;AF_PACKET 用于看完整网络包(容器虚拟网卡、主机网卡、物理交换机镜像),两者互补。
  • AutoTagging:自动注入 Kubernetes 元数据(Pod、Namespace、Service、Workload)和云资源元数据,所有流数据都带着语义。
  • AutoTracing:无须代码埋点,基于网络层关联跨服务请求,构建调用链。

6.2 架构

+--------------------+             +--------------------+
|  deepflow-agent    |  gRPC(fb)   |  deepflow-server   |
|  (K8s DaemonSet) |<----------->|  (Go 集群服务)    |
|  - eBPF 采集        |             |  - 元数据同步        |
|  - AF_PACKET 采集   |             |  - 流 / 指标 / 跟踪   |
|  - L7 协议解析      |             |  - ClickHouse 写入    |
+--------------------+             +--------------------+
                                             ^
                                             | SQL
                                             v
                                       +-----------+
                                       | ClickHouse|
                                       +-----------+
                                             ^
                                             |
                                       +-----------+
                                       |  Grafana  |
                                       +-----------+

deepflow-agent 用 Rust 编写,eBPF 程序使用 CO-RE 形式分发。deepflow-server 用 Go 编写,存储基于 ClickHouse。Grafana 侧有官方的 DeepFlow 数据源插件,提供专用查询语言。

6.3 AutoTagging 与 AutoTracing

AutoTagging:agent 与 Kubernetes API、云平台 API 同步资源信息,给每条流/每条 L7 记录自动打上:

  • k8s.pod、k8s.namespace、k8s.service、k8s.deployment、k8s.node;
  • 虚拟机 ID、子网、可用区;
  • 业务标签(通过 Pod 注解自定义)。

AutoTracing:在 eBPF 层采集 TCP socket 的五元组、L7 请求响应对,同时记录进程/线程上下文。当一个进程”收到请求 A 后发出请求 B”时,可以通过时间相邻、socket 关联、线程局部存储(TLS,Thread Local Storage)的令牌传递(如 HTTP 头里的 X-Request-ID)推断 A 与 B 的调用关系,从而构造无埋点的调用链。

对没有显式 Trace ID 的应用,这种启发式推断不是百分百精确,但在工程上可以覆盖 80% 的场景,对于老系统的”第一张调用图”非常有价值。

6.4 查询语言

DeepFlow 的数据存于 ClickHouse,提供专用的 SQL 扩展:

SELECT
  request_resource,
  response_code,
  countIf(response_code >= 400) AS err_count,
  quantileTDigest(0.99)(response_duration) AS p99_ms
FROM flow_log.l7_flow_log
WHERE time >= now() - INTERVAL 5 MINUTE
  AND l7_protocol = 'HTTP'
  AND pod_ns = 'order'
GROUP BY request_resource, response_code
ORDER BY err_count DESC
LIMIT 50;

Grafana 插件将这些语义化的维度暴露为下拉框,上手门槛比手写 SQL 低。

6.5 部署示例

# deepflow-values.yaml (Helm)
global:
  image:
    repository: registry.cn-beijing.aliyuncs.com/deepflow-ce
grafana:
  enabled: true
  service:
    type: NodePort
deepflow-agent:
  clusterNAME: prod-cluster
  updateStrategy:
    type: RollingUpdate
  resources:
    requests:
      cpu: 500m
      memory: 500Mi
    limits:
      cpu: 2
      memory: 2Gi
helm repo add deepflow https://deepflowio.github.io/deepflow
helm install deepflow -n deepflow --create-namespace \
  deepflow/deepflow -f deepflow-values.yaml

6.6 与 Pixie/Hubble 的对比

维度 Hubble Pixie DeepFlow
定位 Cilium 可观测层 通用 K8s 可观测 全栈(云 + 云原生)
是否绑 CNI 是(Cilium)
L7 协议覆盖 HTTP/DNS/Kafka 等 HTTP/DB/MQ 等较多 HTTP/DB/MQ/Dubbo 等最多
存储 节点内存 + 指标后端 节点内存(列式) ClickHouse(集中)
调用链 有限 基于 L7 事件 AutoTracing
自定义策略语言 PxL SQL
数据是否出集群 可选 默认不 集中存储
生态 CNCF Graduated 一部分 CNCF Sandbox CNCF Landscape(国产)
社区语言 英文 英文 中英双语,国内活跃

DeepFlow 的突出优势是”既做网络包又做 eBPF,L7 协议覆盖广”;劣势是相比 Hubble,与 Cilium 的策略联动不那么深。

七、网络性能监控(NPM)与应用性能监控(APM)的边界

7.1 两者的关注点差异

  • 网络性能监控(NPM,Network Performance Monitoring):核心关注”链路质量”。指标包括带宽、丢包率、重传率、RTT、连接建立时延、抖动。
  • 应用性能监控(APM,Application Performance Monitoring):核心关注”应用行为”。指标包括请求速率、错误率、时延分布(按端点、租户等维度)、调用链、数据库慢查询。

7.2 L7 上的重叠

当 NPM 深入到 L7(以本文讨论的 Hubble/Pixie/DeepFlow 为例),它开始能够看见:

  • HTTP 状态码、gRPC status;
  • SQL 语句及执行时间;
  • DNS 查询是否成功、解析耗时。

这恰恰是 APM 的传统地盘。但两者的视角仍然不同:

  • APM 以”请求”为第一实体,一次请求跨多少服务都串起来。
  • L7 NPM 以”连接/包”为第一实体,看到的是一段段 socket 上的明文交互,调用链需要额外构造。

7.3 互补的典型案例

场景一:NPM 能抓到,APM 抓不到。

  • Pod 之间 TCP 握手失败(RST):APM 看到的是”连接被拒绝”异常,但说不清是 kube-proxy、CNI、还是对端 iptables 的问题。Hubble 能看到 verdict 是 DROPPED,以及丢包来自哪条 CiliumNetworkPolicy。
  • 跨可用区重传突增:APM 指标只体现为”时延升高”。NPM 直接显示 tcp_retransmits 指标异常。
  • DNS 解析偶发超时:APM 在请求视角只看到”总时延拉长”,NPM 在 L7 视角直接列出 DNS 失败的 query 与响应码。

场景二:APM 能抓到,NPM 抓不到。

  • 业务语义错误:NPM 可以看到 HTTP 200,但业务响应体中包含 “code: 500, msg: xxx”。这类错误需要 APM 有针对性地埋点或响应体采样。
  • 用户维度聚合:某用户被风控拒绝,APM 可以按 userId 聚合,NPM 只看得到 Pod/Service。
  • 异步链路:消息发送端与消费端在 NPM 里看起来是两条独立流量,APM 靠消息头里的 TraceID 把它们串成一条链。

7.4 工程落地建议

  • 不要把 NPM 与 APM 对立起来。合理做法:以 APM(OpenTelemetry + Jaeger/Tempo)为业务观测主干,以 NPM(Hubble/DeepFlow/Pixie)为基础设施与黑盒兜底。
  • 在告警体系里,“业务错误率 > X%”通常由 APM 产生;“网络丢包 > Y / 重传率 > Z”由 NPM 产生。交叉告警能很快缩小故障域。

八、TLS / HTTP/2 解析

8.1 TLS 解密挑战

HTTPS、gRPC、TLS-over-MySQL 等加密协议占比越来越高。对基于网络层/传输层采集的可观测系统来说,这意味着如果不做特殊处理,只能看到密文流、统计流量大小与连接生命周期,拿不到 L7 语义。

常见解密路径有三种:

  1. 旁路 + 私钥:传统 DPI 方案。要求部署方提供服务端私钥,设备中间解密。问题:
    • 对前向保密(PFS,Perfect Forward Secrecy)套件不适用,因为密钥是会话级的;
    • 企业合规上很多场景不允许拿私钥出设备;
    • 无法解密客户端互相访问的互联网方向流量。
  2. uprobe 在 TLS 库:在 SSL_read/SSL_write(以及 Go crypto/tls、Node/Python ssl 等)函数入口/返回点采集明文缓冲区。这是 Pixie、DeepFlow、Hubble L7 HTTPS 的主流做法。关键点:
    • 不需要私钥,与 TLS 1.3 和 PFS 套件兼容;
    • 必须在应用进程内挂探针,这意味着要能访问到进程的 /proc/<pid>/root/<libpath>
    • 对静态链接的 Go 二进制尤其棘手,需要从 DWARF/pclntab 找符号偏移。
  3. 内核态 TLS(kTLS)+ eBPF:Linux 4.13 引入 kTLS,加密可下放到内核。对使用 kTLS 的工作负载,eBPF 可以在 kTLS 缓冲前后读到明文。主流 Web 服务器(Nginx 从 1.13.5 起,部分版本需编译参数)可开启 kTLS。

8.2 TLS 1.3 会话票据(Session Ticket)带来的影响

TLS 1.3 默认使用会话票据实现会话恢复,这意味着:

  • 同一条 TCP 连接上的多次请求可能跨越不同的 TLS 上下文;
  • 基于私钥解密的方案更加不适用;
  • 基于 uprobe 的方案不受影响,因为明文一定会经过 SSL_read/SSL_write

8.3 HTTP/2 连接复用问题

HTTP/2 在单条 TCP 连接上多路复用(Multiplexing)多个流(Stream),每个流用唯一的 Stream ID 标识。对协议解析器而言,这带来两个挑战:

  1. 一条 TCP 连接上会交织出现多个请求响应的二进制帧(HEADERS、DATA、WINDOW_UPDATE 等),解析器必须按 Stream ID 重组。
  2. 请求头使用 HPACK 压缩,需要维护连接级的动态表(dynamic table)。

在 eBPF 中完全实现 HPACK 解码并不现实(eBPF 指令数限制、无堆、无动态循环),主流做法:

  • 在 eBPF 程序里只抓取帧头(9 字节)与 payload 指针、长度;
  • 通过环形缓冲区把 payload 送到用户态 Agent;
  • 用户态用标准 HPACK 解码器(Go 的 golang.org/x/net/http2/hpack、Rust 的 h2 等)还原完整请求。

这也是为什么 Pixie、DeepFlow 在用户态 Agent 占 CPU 不低:真正的协议解析成本都在那里。

8.4 gRPC over HTTP/2 的追踪

gRPC 使用 HTTP/2 作为传输,content-type 为 application/grpc,方法名放在 :path 伪头里(形如 /package.Service/Method),状态码在响应 Trailer 的 grpc-status 里。解析要点:

  • 抓取 HEADERS 与 Trailer 两组 HPACK 块;
  • 关联 :path:statusgrpc-statusgrpc-message
  • 计算响应大小时注意 5 字节的 gRPC 帧头(1 字节压缩标志 + 4 字节 length)。

8.5 协议识别工程

对于”一个 socket 上跑的是什么协议”这个问题,常见识别策略:

  1. 基于端口的猜测:80 是 HTTP、6379 是 Redis。容器化环境下端口约定不可靠,只能作为候选。
  2. 基于首包指纹:HTTP 以 GETPOST 等方法开头;MySQL 以长度前缀 + 握手包;Redis 以 *<number>\r\n;Kafka 以 ApiKey。
  3. 失败回退:尝试多个解析器,若都失败则标为 unknown,避免误报。
  4. 状态机携带协议标签:识别成功后在 socket -> protocol 的 Map 中记录,后续跳过重复识别。

解析器本身要求:

  • 增量解析:TCP 是流式协议,一个请求可能跨多次读取;解析器必须能 feed(partial_bytes)
  • 失步恢复:采集可能丢包(ring buffer 溢出),解析器要能在下一个消息边界恢复。
  • 零拷贝:热路径上尽量避免 memcpy,使用索引与视图。

九、服务拓扑自动发现

9.1 拓扑的价值

“这个系统里哪些服务在互相调用”,对新接手系统、对故障影响面分析、对安全基线审计,都是最先需要回答的问题。传统做法:

  • 看代码仓库的依赖配置;
  • 看部署配置里的 Service 定义;
  • 靠架构师画图并维护。

这些都难以跟上变化速度。基于网络流量自动发现服务拓扑,是网络可观测工具的天然能力。

9.2 聚合粒度

从原始流到服务拓扑图,需要多级聚合:

  1. 包级流级:将相同五元组(源 IP、源端口、目的 IP、目的端口、协议)的数据包聚合成一条流。
  2. 流级实例级:将 IP 映射为 Kubernetes Pod / 虚拟机实例。
  3. 实例级服务级:将 Pod 按 Workload、Service 聚合。
  4. 服务级应用级 / 域级:按业务线、命名空间、团队聚合。

每一级聚合都会失去细节,但对应不同的使用者:SRE 看应用级,开发看服务级,排障看实例级,取证看流级。

9.3 各工具的实现

  • Hubble:使用 Cilium Identity 聚合,拓扑图节点就是 Identity,对应一组 Pod。UI 支持按 Namespace、Workload 等维度透视。
  • DeepFlow:基于 AutoTagging 给所有流打上丰富标签,拓扑图可以按任意标签维度重新聚合。
  • Pixie:内建 px/service_graph 脚本,按 Service / Endpoint 展示调用关系与指标。

9.4 Sidecar 场景

在 Istio / Linkerd 等基于 sidecar 的服务网格(Service Mesh)中,每个 Pod 旁边都有一个代理进程(Envoy / linkerd-proxy)。网络层看到的流量是:

app A -> envoy A -> envoy B -> app B

如果按 IP 聚合,会把 “app -> envoy” 的 127.0.0.1 回环流量与 “envoy -> envoy” 的跨节点流量都保留。拓扑图如果不做特殊处理,会出现大量”自己调自己”的边。

处理思路:

  • 识别 sidecar 进程(通常有明显的镜像名、容器名约定);
  • 在拓扑聚合时把 sidecar 节点合并到”所属 Pod”;
  • 只保留真正的跨 Pod 边。

DeepFlow、Pixie、Hubble 都有针对 Istio 的”合并 sidecar”能力,但各家实现成熟度不同,部署前建议用灰度环境验证。

十、与 Service Mesh 的关系

10.1 Istio 与网络可观测性

Istio 基于 Envoy sidecar,天然会产生丰富的 L7 指标:

  • istio_requests_total:按源/目的 workload、响应码、协议聚合的请求计数;
  • istio_request_duration_milliseconds:请求时延直方图;
  • istio_tcp_sent_bytes_total / istio_tcp_received_bytes_total:非 HTTP TCP 流量。

这些指标来自 Envoy 的 Prometheus 端点,经过 Istio 的 telemetry 配置塑形。也就是说:装了 Istio 并打开默认 telemetry,就已经有一套相当像样的 L7 观测数据了。

代价是 sidecar:每个 Pod 多出一个 Envoy 进程,资源占用(CPU 50m~200m、内存 50MiB~200MiB),延迟新增 1~3 毫秒。对大规模集群与对延迟敏感的负载,这是显著的成本。

eBPF 路径(Hubble/DeepFlow/Pixie)不需要 sidecar,资源开销通常只集中在 DaemonSet 上,但也有自己的代价:

  • 数据源是网络层 + 应用库 uprobe,不如 Envoy 的 access log 精确(Envoy 的每一条 access log 都是一次完整请求响应的正式审计记录);
  • Envoy 天然带着服务网格的路由、重试、熔断元数据,这些是网络层看不到的内部状态。

所以现实中不少团队选择共用:Istio 负责服务治理与 L7 基线指标,Hubble/DeepFlow 负责网络层排障与安全。

10.2 Cilium Service Mesh

Cilium 提供了”无 sidecar”的服务网格方案:

  • 使用 eBPF 在节点上实现 L7 路由与策略;
  • 可选启用基于 eBPF 的双向 TLS(mTLS,mutual TLS),密钥与会话管理由 Cilium 完成;
  • 可观测性直接复用 Hubble,无须额外部署 telemetry。

优势:

  • 资源开销降一个数量级(每节点一个 Agent,不是每 Pod 一个代理);
  • 延迟更低;
  • 与 CNI 合并,链路更短。

劣势:

  • 功能上相比 Istio 社区十几年的积累仍有差距(例如 Istio 的 VirtualService 精细化路由、遥测扩展生态);
  • 对 L7 的控制目前主要是 HTTP、Kafka 等协议,不如 Envoy 通过过滤器链的可扩展。

选型上:追求简洁、绝对性能、统一 eBPF 栈 → Cilium Service Mesh;需要复杂流量治理与成熟生态 → Istio。

十一、大流量下的工程挑战

11.1 内核环形缓冲区(Ring Buffer)溢出

eBPF 程序把事件送到用户态主要靠两种机制:

  • perf_event_array:较老的机制,每 CPU 一个环形缓冲区;
  • BPF_MAP_TYPE_RINGBUF(Linux 5.8+):单一全局环形缓冲区,带原子保留接口,性能更好。

在大流量下,用户态消费速度跟不上内核生产速度,缓冲区会溢出,事件丢失。工程上常见应对:

  • 合理估算峰值事件数,分配足够大的 buffer(例如 64MiB~256MiB);
  • 在内核侧做采样(见下节);
  • 用户态采用批量读取(ring buffer 提供 bpf_ringbuf_reserve/commit 配合批 poll);
  • 关键统计用 BPF Map 聚合(例如计数、直方图),而不是每事件都送到用户态。

11.2 采样策略

高吞吐链路上,采全量流日志既不经济也没必要。常见策略:

  • 连接级采样:同一条连接的事件要么全采、要么全不采,避免断链;按连接 hash 抽样可以保证这点。
  • 错误优先采样:所有 4xx/5xx、TCP RST、DNS NXDOMAIN 全采;成功事件按比例采样。
  • 自适应采样:按节点当前 CPU / buffer 使用率动态调整采样率。
  • 尾采样(Tail Sampling):类似 OpenTelemetry,先全量缓存若干秒,根据”尾部属性”决定是否留存。

11.3 聚合 vs 原始流存储

对指标(计数、直方图)用 BPF Map 内聚合,仅周期性导出,可降低几个量级的数据量。对需要排障的原始事件,则必须尽量保全。工程上常用的分层策略:

  • 秒级:原始流日志(保留 15 分钟~1 小时);
  • 分钟级:按服务对、协议、响应码聚合的指标(保留 15~30 天);
  • 小时级:Top N 聚合(慢接口、错误接口、新出现服务对),长期保留。

11.4 L7 解析的 CPU 开销

一旦进入 HPACK 解码、MySQL 协议解码这些工作,CPU 开销会显著上升。经验数据(参考 Pixie/DeepFlow 官方测试):

  • 纯 L4 流日志采集:单节点 10Gbps 线速下,eBPF 侧占用约 0.2 核;
  • L7 HTTP/1.x 解析:同样 10Gbps,用户态 Agent 约 1~2 核;
  • HTTP/2 + gRPC:由于 HPACK 与帧重组,同条件约 2~4 核;
  • 数据库协议(MySQL/PostgreSQL):根据语句长度,约 1~3 核。

生产部署一定要给 Agent 预留 CPU,并在高峰做压力测试。

11.5 连接跟踪内存

要把 TCP 连接的全生命周期串起来,必须维护一张”连接 -> 状态”的表。高峰时连接数可能达到百万级,相应 BPF Map 需要按连接条目大小 ×连接数做预留,常见配置:

  • 每连接结构约 256~512 字节;
  • 1M 连接 ≈ 256~512 MiB 的 BPF Map 内存。

超时清理策略:

  • 定时扫描 Map,清理最近 X 秒无流量的连接;
  • tcp_close 挂 kprobe,主动释放;
  • 使用 BPF_MAP_TYPE_LRU_HASH,让内核按最近使用淘汰。

十二、国内落地案例

12.1 DeepFlow 在国内运营商

云杉网络在电信、移动、联通的多个省级 IT 系统里都有 DeepFlow 部署案例,典型规模:

  • 跨多 Region、多云(私有云 OpenStack + 公有云)统一观测;
  • agent 覆盖到虚拟机与 Kubernetes Pod;
  • 每秒 L7 事件数百万级,原始流 PB 级;
  • 重点场景:跨云链路质量监控、业务支撑系统(BSS)间调用审计、VNF 网元链路可观测。

12.2 中国移动大规模 K8s 网络可观测

中国移动公有云 / 私有云的大规模 Kubernetes 平台(万级节点)在 2023~2024 年陆续把网络可观测栈从传统 NetFlow 迁移到 eBPF 方案:

  • 数据面使用 Cilium + Hubble 或自研 eBPF agent;
  • 控制面接入统一可观测平台;
  • 与 APM(基于 SkyWalking / 自研)数据做关联;
  • 重点解决跨租户流量隔离审计、零信任网络收紧过程的流量可见性。

12.3 腾讯云 TCOS / 自研 eBPF 栈

腾讯内部的容器平台(腾讯云操作系统 TCOS、TKE)在多个场景下使用 eBPF 做网络可观测:

  • tcpex 等内部工具采集 TCP 层指标,关联到容器;
  • 对腾讯内部 RPC 协议(如 TarsProtocol、WesleyProto)做 L7 解析;
  • 与自研调用链系统(例如天机阁)打通。

公开资料上,腾讯 TKE 也提供”网络可观测”增值功能,底层是基于 eBPF 的流日志 + 服务拓扑。

12.4 金融行业的网络安全可观测

国内多家大型银行在生产网与开发测试网推行零信任改造,网络可观测是其中关键一环:

  • 用 Hubble/DeepFlow 获取全量 L3/L4 流日志,作为”正常基线”;
  • 用 Tetragon / Falco 做进程与文件级审计;
  • 将事件流送入等级保护合规要求的 SIEM / 日志审计系统,留存 180 天以上;
  • 对跨生产域调用做告警(例如开发网 Pod 不应访问生产网数据库)。

这里的工程挑战不是技术不够,而是合规与留痕要求极高,任何漏采都可能在监管检查中出问题。

十三、工程坑点

13.1 TLS 解密覆盖不全

  • 静态链接的 Go 二进制:符号被去除后,uprobe 定位失败。解决:读 pclntab/.gopclntab、通过 DWARF 或 Go 版本特定的偏移表来定位。
  • 自研 TLS 库(少数大厂内部):需要定制 uprobe。
  • LD_PRELOAD 动态库替换、Alpine + musl 等不常见场景:经常出现找不到 SSL_read 符号的问题。
  • iOS / Android:移动端 App 与容器无关,但如果可观测链路覆盖边缘网关,要注意这些终端也用 TLS,且抓不到。

13.2 HTTP/2 多路复用极端场景

  • 长连接上持续有大量流:一条连接上可能持续开/关几百到几千个流,动态表容量上限(默认 4KiB)会频繁驱逐条目,解析器需要正确处理表满情况。
  • 跨读丢包:ring buffer 丢了一段 payload,导致 HPACK 解码状态与连接真实状态脱节,后续所有 header 都可能乱码。工程上通常选择在这种情况下放弃当前连接的 L7 解析,回退到 L4。

13.3 高包速下的内核丢包

当单节点 PPS 超过 100 万级,即便 eBPF 程序很精简,perf_event 或 ringbuf 仍可能丢事件。判断方法:

  • bpftool prog show 可观测 eBPF 程序运行次数;
  • ringbuf 提供 BPF_RB_AVAIL_DATABPF_RB_RING_SIZE 等字段,可计算填充率;
  • 用户态 Agent 通常会自报”丢事件数”。

应对:先在采集侧过滤(丢弃控制面流量、本地回环等),再上采样。

13.4 Hubble 数据量

默认 Hubble 仅在节点上保留最近几万条流事件(环形缓存)。要长期存储,需要:

  • 启用 Hubble Exporter(Cilium 1.13+)把事件按 JSON 写入文件,由日志收敛链路收走;
  • 或 subscribe Hubble Relay 的 gRPC 流式 API 自行消费。

忽略这一点的团队,事后排障时经常发现”事件已经被 Hubble 自己的环形缓存覆盖了”。

13.5 DeepFlow Agent 资源

DeepFlow agent 默认资源请求较低,但在高流量节点实际占用可能远超请求,触发 OOMKilled。部署清单务必:

  • 评估节点上典型流量;
  • 请求与限制都设置合理上限;
  • 配置告警,监控 agent 的 CPU/内存使用率与丢包率指标。

13.6 Pixie 的 K8s 依赖

Pixie 不支持非 Kubernetes 部署。混合环境(Kubernetes + 虚拟机 + 裸机)下,Pixie 只能覆盖一部分。这类场景下,DeepFlow 通常是更好的选择。

13.7 各 Agent 时钟同步

流事件的时间戳来自节点本地时钟,多节点合并分析时,时钟偏差会导致拓扑边乱序、P99 计算不准。建议:

  • 全部节点开启网络时间协议(NTP,Network Time Protocol)或更精确的精密时间协议(PTP,Precision Time Protocol);
  • 监控节点时钟偏差(如 node_timex_offset_seconds);
  • 在事件中同时保留纳秒时间戳与单调时钟(CLOCK_MONOTONIC),用于同机事件排序。

13.8 命名空间歧义

同名 Namespace(如多个集群都有 order 命名空间)聚合时会撞车。工程上建议:

  • 在 agent 上配置 cluster_name,所有事件统一带上集群标签;
  • 拓扑按 cluster/namespace/service 三元组渲染。

13.9 BPF verifier 失败

eBPF 程序上线时会被内核验证器校验。大的 L7 解析程序经常撞上:

  • 指令数上限(5.1 前 4096 条,5.1 后 100 万但仍有上限);
  • 栈大小 512 字节;
  • 循环必须可静态展开或使用 bpf_loop()(5.17+)。

CO-RE 工具链可以缓解,但复杂协议解析仍然要尽量把工作推到用户态。

十四、选型建议与落地清单

14.1 选型决策矩阵

场景 推荐方案
纯 Kubernetes、已用 Cilium Hubble(可加 Tetragon 做安全)
纯 Kubernetes、未用 Cilium,业务协议丰富 Pixie 或 DeepFlow
混合云:Kubernetes + VM + 裸机 DeepFlow(双数据面原生支持)
强安全合规要求 Tetragon + Hubble + SIEM
需要深度调用链且不想改代码 DeepFlow AutoTracing 或 Pixie PxL
研发主导、看重 SQL/脚本能力 DeepFlow(ClickHouse 内 SQL)或 Pixie(PxL)
追求极简、想让 NPM 与服务网格合一 Cilium Service Mesh + Hubble

14.2 生产部署清单

以下清单可作为上线 checklist:

  1. 集群规模评估:节点数、单节点 PPS、连接数、QPS。
  2. 内核版本:目标 5.10+(CO-RE、ringbuf 更友好),至少 4.19。
  3. 部署架构:agent DaemonSet、中心聚合、数据源下游(Prometheus/ClickHouse)。
  4. 资源画像:每节点 agent CPU/内存 request/limit;中心服务 CPU/内存/磁盘。
  5. 数据保留:原始流日志 N 小时、指标 N 天、聚合 N 月。
  6. 采样策略:错误全采、成功按比例、连接级一致性。
  7. 元数据接入:Kubernetes API、云 API、CMDB(Configuration Management Database)。
  8. 协议覆盖:列出业务使用的协议,确认工具覆盖情况(HTTP/gRPC/MySQL/Redis 等)。
  9. TLS 覆盖:列出主要 TLS 实现(OpenSSL/Go/Java/Node),逐一验证 uprobe 能采到。
  10. Service Mesh 兼容:如有 Istio,验证 sidecar 聚合、避免重复计费。
  11. 告警与仪表盘:错误率、丢包率、重传率、agent 健康、buffer 丢事件率。
  12. 与 APM 联动:TraceID 注入与传递、跨数据源 Join 方案。
  13. 安全事件流:Tetragon/Falco 事件 → SIEM 链路是否畅通。
  14. 升级回滚:eBPF 程序升级的金丝雀策略、agent 灰度。
  15. 故障演练:人为注入丢包、重传、5xx、DNS 超时等场景,验证工具能发现。

14.3 常见反模式

  • “装了 Hubble 就以为有 APM”:L7 NPM 与 APM 视角不同,不能互相替代。
  • “抓全量原始包到中央分析”:带宽与存储成本爆炸,99% 是无用数据。
  • “一次性打开所有 L7 协议解析”:CPU 会被吃掉。务必按需启用。
  • “用 eBPF 抓所有系统调用做安全审计”:事件量过大,应当用 TracingPolicy 收敛,只采关心的调用。

十五、参考资料

  1. Cilium 官方文档,https://docs.cilium.io/
  2. Hubble 项目 GitHub,https://github.com/cilium/hubble
  3. Tetragon 官方文档,https://tetragon.io/
  4. Pixie 官方文档,https://docs.px.dev/
  5. Pixie 源码,https://github.com/pixie-io/pixie
  6. DeepFlow 开源文档,https://deepflow.io/docs/zh/
  7. DeepFlow 源码,https://github.com/deepflowio/deepflow
  8. Brendan Gregg,《BPF Performance Tools》,Addison-Wesley,2019。
  9. Linux 内核文档:BPF and XDP Reference Guide,https://docs.cilium.io/en/stable/bpf/
  10. Liz Rice,《Learning eBPF》,O’Reilly,2023。
  11. CNCF TAG Observability,《Observability Whitepaper》,https://github.com/cncf/tag-observability
  12. IETF RFC 7540,HTTP/2 协议规范。
  13. IETF RFC 8446,TLS 1.3 协议规范。
  14. Google,《gRPC Protocol》,https://grpc.io/docs/
  15. 云杉网络博客,《DeepFlow 架构解析》系列。
  16. Isovalent 博客,《Hubble: Network, Service & Security Observability for Kubernetes》。
  17. New Relic 博客,《Introducing Pixie: Instant Kubernetes Observability》。
  18. 中国移动研究院,《云原生网络可观测性白皮书》,2024。
  19. CNCF Landscape,Observability & Analysis / Network 分类。
  20. Linux kernel bpf 子系统源码:kernel/bpf/net/core/filter.c

上一篇eBPF 可观测性全景:bcc、bpftrace、libbpf 的工程路径

下一篇Continuous Profiling:Parca、Pyroscope、Grafana Beyla

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-22 · architecture / observability

持续性能分析(Continuous Profiling):Parca、Pyroscope、Grafana Beyla

深入剖析持续性能分析(Continuous Profiling)的原理、架构与落地实践,覆盖 Parca、Pyroscope、Grafana Beyla 三大主流方案,包含 eBPF 采样、符号解析、火焰图、差异分析以及字节跳动、美团的生产案例与工程坑点。

2026-04-22 · architecture / observability

可观测性工程

从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。