网络可观测性(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 解析、服务拓扑发现等工程难点;
- 大流量场景下的坑与选型建议。
一、网络可观测性的层次
网络可观测性必须分层来看。每一层能回答的问题不同,采集成本、实现难度也不同。
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)串联。此时:
- L3/L4 指标即使全部正常,应用层也可能大量报错(例如服务端返回 400/500)。
- 出问题时,绝大多数问题定位需要 L7 的语义信息(“是哪个接口挂了”“是哪个下游返回了错误码”)。
- 调用链追踪(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:在主机侧抓包,开销较高。
这些方案的共性局限:
- 拿不到容器 / Pod 上下文。NetFlow 只知道 IP,对 Kubernetes 来说,Pod IP 是朝生暮死的。
- 看不透 L7,或要靠深度包检测(DPI,Deep Packet Inspection)硬件盒子,价格昂贵。
- 对加密流量无能为力。
基于 eBPF 的方案则具备:
- 在内核中直接采集,开销可控。
- 通过挂载到
sched_process_exec、cgroup相关钩子,可以在事件源头就带上容器元数据。 - 通过 uprobe 挂到 OpenSSL/Go crypto 等库,可以在加密前/解密后取明文。
- 可以做到无须在物理设备上架设旁路,采集、过滤、聚合都在主机侧完成。
这是本文所有工具的共同技术底座。
二、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:
- OpenSSL:
SSL_read/SSL_write,入口拿到缓冲区指针,返回时缓冲区中是明文。 - BoringSSL:类似 OpenSSL。
- Go 标准库
crypto/tls:Go 将 TLS 实现自带,因此需要对 Go 二进制里的crypto/tls.(*Conn).Read、crypto/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 Hubble 架构
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
CLI(
hubble):命令行工具,连接 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 uiPrometheus 侧,给 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: 30sGrafana 侧,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: 2Gihelm repo add deepflow https://deepflowio.github.io/deepflow
helm install deepflow -n deepflow --create-namespace \
deepflow/deepflow -f deepflow-values.yaml6.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 语义。
常见解密路径有三种:
- 旁路 + 私钥:传统 DPI
方案。要求部署方提供服务端私钥,设备中间解密。问题:
- 对前向保密(PFS,Perfect Forward Secrecy)套件不适用,因为密钥是会话级的;
- 企业合规上很多场景不允许拿私钥出设备;
- 无法解密客户端互相访问的互联网方向流量。
- uprobe 在 TLS 库:在
SSL_read/SSL_write(以及 Gocrypto/tls、Node/Pythonssl等)函数入口/返回点采集明文缓冲区。这是 Pixie、DeepFlow、Hubble L7 HTTPS 的主流做法。关键点:- 不需要私钥,与 TLS 1.3 和 PFS 套件兼容;
- 必须在应用进程内挂探针,这意味着要能访问到进程的
/proc/<pid>/root/<libpath>; - 对静态链接的 Go 二进制尤其棘手,需要从 DWARF/pclntab 找符号偏移。
- 内核态 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 标识。对协议解析器而言,这带来两个挑战:
- 一条 TCP 连接上会交织出现多个请求响应的二进制帧(HEADERS、DATA、WINDOW_UPDATE 等),解析器必须按 Stream ID 重组。
- 请求头使用 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、:status、grpc-status、grpc-message; - 计算响应大小时注意 5 字节的 gRPC 帧头(1 字节压缩标志 + 4 字节 length)。
8.5 协议识别工程
对于”一个 socket 上跑的是什么协议”这个问题,常见识别策略:
- 基于端口的猜测:80 是 HTTP、6379 是 Redis。容器化环境下端口约定不可靠,只能作为候选。
- 基于首包指纹:HTTP 以
GET、POST等方法开头;MySQL 以长度前缀 + 握手包;Redis 以*<number>\r\n;Kafka 以 ApiKey。 - 失败回退:尝试多个解析器,若都失败则标为
unknown,避免误报。 - 状态机携带协议标签:识别成功后在 socket -> protocol 的 Map 中记录,后续跳过重复识别。
解析器本身要求:
- 增量解析:TCP
是流式协议,一个请求可能跨多次读取;解析器必须能
feed(partial_bytes)。 - 失步恢复:采集可能丢包(ring buffer 溢出),解析器要能在下一个消息边界恢复。
- 零拷贝:热路径上尽量避免
memcpy,使用索引与视图。
九、服务拓扑自动发现
9.1 拓扑的价值
“这个系统里哪些服务在互相调用”,对新接手系统、对故障影响面分析、对安全基线审计,都是最先需要回答的问题。传统做法:
- 看代码仓库的依赖配置;
- 看部署配置里的 Service 定义;
- 靠架构师画图并维护。
这些都难以跟上变化速度。基于网络流量自动发现服务拓扑,是网络可观测工具的天然能力。
9.2 聚合粒度
从原始流到服务拓扑图,需要多级聚合:
- 包级 → 流级:将相同五元组(源 IP、源端口、目的 IP、目的端口、协议)的数据包聚合成一条流。
- 流级 → 实例级:将 IP 映射为 Kubernetes Pod / 虚拟机实例。
- 实例级 → 服务级:将 Pod 按 Workload、Service 聚合。
- 服务级 → 应用级 / 域级:按业务线、命名空间、团队聚合。
每一级聚合都会失去细节,但对应不同的使用者: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_DATA、BPF_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:
- 集群规模评估:节点数、单节点 PPS、连接数、QPS。
- 内核版本:目标 5.10+(CO-RE、ringbuf 更友好),至少 4.19。
- 部署架构:agent DaemonSet、中心聚合、数据源下游(Prometheus/ClickHouse)。
- 资源画像:每节点 agent CPU/内存 request/limit;中心服务 CPU/内存/磁盘。
- 数据保留:原始流日志 N 小时、指标 N 天、聚合 N 月。
- 采样策略:错误全采、成功按比例、连接级一致性。
- 元数据接入:Kubernetes API、云 API、CMDB(Configuration Management Database)。
- 协议覆盖:列出业务使用的协议,确认工具覆盖情况(HTTP/gRPC/MySQL/Redis 等)。
- TLS 覆盖:列出主要 TLS 实现(OpenSSL/Go/Java/Node),逐一验证 uprobe 能采到。
- Service Mesh 兼容:如有 Istio,验证 sidecar 聚合、避免重复计费。
- 告警与仪表盘:错误率、丢包率、重传率、agent 健康、buffer 丢事件率。
- 与 APM 联动:TraceID 注入与传递、跨数据源 Join 方案。
- 安全事件流:Tetragon/Falco 事件 → SIEM 链路是否畅通。
- 升级回滚:eBPF 程序升级的金丝雀策略、agent 灰度。
- 故障演练:人为注入丢包、重传、5xx、DNS 超时等场景,验证工具能发现。
14.3 常见反模式
- “装了 Hubble 就以为有 APM”:L7 NPM 与 APM 视角不同,不能互相替代。
- “抓全量原始包到中央分析”:带宽与存储成本爆炸,99% 是无用数据。
- “一次性打开所有 L7 协议解析”:CPU 会被吃掉。务必按需启用。
- “用 eBPF 抓所有系统调用做安全审计”:事件量过大,应当用 TracingPolicy 收敛,只采关心的调用。
十五、参考资料
- Cilium 官方文档,https://docs.cilium.io/。
- Hubble 项目 GitHub,https://github.com/cilium/hubble。
- Tetragon 官方文档,https://tetragon.io/。
- Pixie 官方文档,https://docs.px.dev/。
- Pixie 源码,https://github.com/pixie-io/pixie。
- DeepFlow 开源文档,https://deepflow.io/docs/zh/。
- DeepFlow 源码,https://github.com/deepflowio/deepflow。
- Brendan Gregg,《BPF Performance Tools》,Addison-Wesley,2019。
- Linux 内核文档:BPF and XDP Reference Guide,https://docs.cilium.io/en/stable/bpf/。
- Liz Rice,《Learning eBPF》,O’Reilly,2023。
- CNCF TAG Observability,《Observability Whitepaper》,https://github.com/cncf/tag-observability。
- IETF RFC 7540,HTTP/2 协议规范。
- IETF RFC 8446,TLS 1.3 协议规范。
- Google,《gRPC Protocol》,https://grpc.io/docs/。
- 云杉网络博客,《DeepFlow 架构解析》系列。
- Isovalent 博客,《Hubble: Network, Service & Security Observability for Kubernetes》。
- New Relic 博客,《Introducing Pixie: Instant Kubernetes Observability》。
- 中国移动研究院,《云原生网络可观测性白皮书》,2024。
- CNCF Landscape,Observability & Analysis / Network 分类。
- Linux kernel
bpf子系统源码:kernel/bpf/、net/core/filter.c。
上一篇:eBPF 可观测性全景:bcc、bpftrace、libbpf 的工程路径
下一篇:Continuous Profiling:Parca、Pyroscope、Grafana Beyla
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【可观测性工程】eBPF 可观测性全景:bcc、bpftrace、libbpf 的工程路径
eBPF 如何实现零侵入、内核级、低开销的可观测性:从 kprobe/uprobe/tracepoint/fentry 钩子机制,到 bcc 工具集、bpftrace 脚本语言、libbpf+CO-RE 可移植编程,再到 Pixie、DeepFlow、Grafana Beyla 等商业化工具,结合内核版本兼容性与生产部署实战。
【可观测性工程】持续性能分析(Profiling):pprof、Pyroscope、Parca、async-profiler、JFR
从 CPU/heap/goroutine/lock/off-CPU 等 Profiling 种类出发,比较采样与插桩两类 profiler 的工作原理,深入 Go pprof、Java async-profiler/JFR、Python py-spy、Pyroscope、Parca eBPF Profiling,以及 OpenTelemetry Profiles 的最新进展,给出国内字节美团的真实落地经验与工程坑点。
持续性能分析(Continuous Profiling):Parca、Pyroscope、Grafana Beyla
深入剖析持续性能分析(Continuous Profiling)的原理、架构与落地实践,覆盖 Parca、Pyroscope、Grafana Beyla 三大主流方案,包含 eBPF 采样、符号解析、火焰图、差异分析以及字节跳动、美团的生产案例与工程坑点。
可观测性工程
从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。