在 Kubernetes 集群中,网络问题一直是最难排查的故障类型之一。当一个服务调用另一个服务超时,你可能会问:是网络策略拦截了流量?是 DNS 解析出了问题?还是目标 Pod 根本没有收到请求?传统的排查方式需要登录节点抓包、查看 iptables 规则、逐跳验证连通性,耗时且容易遗漏关键信息。
eBPF(Extended Berkeley Packet Filter)的出现彻底改变了这一局面。它允许我们在内核态插入轻量级的安全沙箱程序,在不修改应用代码、不注入 Sidecar 的前提下,实现对网络流量的全量观测。而 Cilium Hubble 则是基于 eBPF 构建的网络可观测性平台,能够以零侵入的方式为 Kubernetes 集群提供应用层、网络层、安全层的全链路流量可视化。本文将带你从 eBPF 原理出发,深入理解 Cilium Hubble 的架构设计,并完成一套生产级的部署与实战配置。

一、为什么传统网络监控在 K8s 中力不从心
在深入 eBPF 之前,我们需要先理解传统网络监控方案在 Kubernetes 环境下遇到的三大核心痛点。
1.1 Sidecar 模式的性能开销
以 Istio 为代表的 Service Mesh 方案通过在每个 Pod 中注入 Envoy Sidecar 代理来拦截和观测流量。这种方式虽然功能强大,但带来了显著的性能损耗:
- 每个请求额外增加两次代理跳转(客户端到Sidecar再到服务端),延迟增加 2-5ms
- Sidecar 占用额外的 CPU 和内存资源,在大规模集群中资源开销可达 15%-20%
- Sidecar 的生命周期管理增加了运维复杂度,升级 Envoy 版本需要滚动重启所有 Pod
1.2 tcpdump 与 iptables 的局限性
传统运维依赖 tcpdump 在节点上抓包分析,但这种方式存在根本性缺陷:
- 只能看到网络层的数据包,无法关联到 Kubernetes 资源(Pod、Service、Namespace)
- 需要在每个节点上手动执行,无法集中查看全集群的流量拓扑
- iptables 规则链在 K8s 中可能长达数百条,人工排查几乎不可能
- 抓包本身会消耗大量磁盘 I/O,不适合长期运行
1.3 DNS 黑洞问题
Kubernetes 中的 DNS 解析问题是最常见的网络故障之一,但传统工具对 DNS 可观测性几乎没有支持。当一个服务间歇性地无法解析另一个服务的域名时,你很难判断是 CoreDNS 负载过高、UDP 包被丢弃,还是网络策略阻断了 DNS 请求。

二、eBPF 技术原理:从内核观测到零侵入监控
eBPF 是 Linux 内核中的一个革命性技术,它允许在不修改内核源码、不加载内核模块的前提下,以安全的方式在内核态运行沙箱程序。理解 eBPF 的工作原理,是正确使用 Cilium Hubble 的基础。
2.1 eBPF 程序的挂载点
eBPF 程序可以挂载到内核的多个钩子点上,对于网络可观测性最关键的有:
| 挂载点类型 | 用途 | 在 K8s 中的观测价值 |
|---|---|---|
| tc(Traffic Control) | 网络设备的流量控制 | 捕获进出 Pod 的所有网络包 |
| XDP(eXpress Data Path) | 网卡驱动层的极速包处理 | DDoS 防护、高性能负载均衡 |
| cgroup/connect | 跟踪连接建立 | 记录 TCP 连接的五元组信息 |
| sock_ops | Socket 操作回调 | 监控 TCP 状态变化(重传、RST 等) |
| kprobe/kretprobe | 内核函数入口与返回 | 跟踪 DNS 解析过程 |
2.2 eBPF Map:数据共享的桥梁
eBPF 程序本身是无状态的,它通过 eBPF Map 与用户态程序共享数据。Cilium 使用了多种 Map 类型来构建可观测性数据管道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 // Cilium 中用于跟踪连接的关键 Map 结构
struct connection_key {
__u32 src_ip;
__u32 dst_ip;
__u16 src_port;
__u16 dst_port;
__u8 protocol;
};
struct connection_value {
__u64 bytes_sent;
__u64 bytes_received;
__u64 packets_sent;
__u64 packets_received;
__u64 last_seen;
__u32 flags;
};
这些 Map 在内核态由 eBPF 程序写入,在用户态由 Cilium Agent 读取并转换为 Hubble 的流事件。由于 eBPF Map 是内存映射的,数据读取几乎零开销,不会对网络数据路径产生任何影响。
2.3 安全性保障
eBPF 程序在加载到内核前必须经过验证器(Verifier)的严格检查:
- 确保程序必定会终止(不允许无限循环)
- 确保所有内存访问都在边界内
- 确保程序不会访问未授权的内核内存
- 限制程序的栈空间大小(最大 512 字节)
这些保障使得 eBPF 程序即使在生产环境中运行也是安全的,不会导致内核崩溃。

三、Cilium Hubble 架构深度解析
Cilium Hubble 的架构设计围绕着零侵入和全链路两个核心目标。理解其架构,才能正确部署和调优。
3.1 核心组件
Hubble 由三个核心组件构成,形成数据的采集、聚合、展示管道:
- Cilium Agent:每个节点上运行一个,加载 eBPF 程序并收集网络事件。它是数据的生产者,将 eBPF Map 中的原始数据转换为结构化的流事件。
- Hubble Agent:内嵌在 Cilium Agent 进程中,将本节点的流事件通过 gRPC 流式接口暴露出去。每个节点的 Hubble Agent 只关心本节点的流量。
- Hubble Relay:集群级聚合器,连接所有节点的 Hubble Agent,将分布式的事件流合并为全局视角。Hubble UI 和 CLI 都通过 Relay 获取数据。
3.2 数据流路径
当一个 Pod 发出 HTTP 请求时,Hubble 的数据采集路径如下:
- eBPF tc 程序在网络设备上捕获数据包,提取五元组信息写入 Map
- cgroup/connect 钩子记录连接建立事件
- sock_ops 回调跟踪 TCP 状态变化(SYN、ACK、FIN、RST)
- Cilium Agent 从 Map 中轮询事件,关联 Kubernetes 元数据(Pod 名、Service 名、Namespace)
- Hubble Agent 将事件通过 gRPC 流推送给 Relay
- Hubble Relay 将事件提供给 UI、CLI 或外部消费者
整个路径的延迟通常在微秒级别,对应用性能几乎无影响。
3.3 与 Cilium 网络策略的联动
Hubble 最大的价值之一是与 Cilium 网络策略(CiliumNetworkPolicy)的深度联动。当一条网络策略拒绝了一个连接,Hubble 会在事件中标记拒绝原因和匹配的策略名称,让你不仅能看到流量断了,还能知道为什么断了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 # CiliumNetworkPolicy 示例:只允许 frontend 访问 backend 的 8080 端口
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-allow-frontend
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
当其他 Pod 尝试访问 backend 的 8080 端口时,Hubble 会记录一个 DROP 事件,并标注 policy=name:backend-allow-frontend,让你立即定位是哪条策略导致了流量被拒绝。

四、生产级部署实战
下面我们以 Helm 方式在已有 Kubernetes 集群上部署 Cilium Hubble,包含完整的配置说明和生产环境调优建议。
4.1 前置条件检查
部署前需要确认集群满足以下条件:
1
2
3
4
5
6
7
8 # 检查内核版本(需要大于等于 4.19,推荐 5.10+)
uname -r
# 检查 eBPF 特性支持
cilium-feature-check
# 如果是从 kube-proxy 迁移,需要先确认 eBPF kube-proxy 替换模式支持
kubectl get nodes -o wide
4.2 Helm 部署配置
以下是一个生产级的 values.yaml 配置,关键参数都有详细注释:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 # values-hubble.yaml
# 启用 Hubble 可观测性
hubble:
enabled: true
# Relay 配置
relay:
enabled: true
replicas: 2
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
# PDB 确保 Relay 高可用
podDisruptionBudget:
enabled: true
minAvailable: 1
# UI 配置
ui:
enabled: true
replicas: 1
service:
type: ClusterIP
# 监控配置
metrics:
enabled:
- dns
- drop
- tcp
- flow
- port-distribution
- http
# 启用服务地图指标
serviceMap:
enabled: true
# Cilium Agent 配置
cilium:
kubeProxyReplacement: strict
bpf:
autoMount:
enabled: true
mapDynamicSizeRatio: 0.0025
lbExternalClusterIP: true
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
monitor:
enabled: true
# Operator 配置
cilium-operator:
replicas: 2
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
4.3 执行部署
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 # 添加 Helm 仓库
helm repo add cilium https://helm.cilium.io/
helm repo update
# 安装 Cilium
helm install cilium cilium/cilium \
--namespace kube-system \
-f values-hubble.yaml \
--wait
# 验证 Cilium 状态
cilium status
# 验证 Hubble Relay 就绪
kubectl -n kube-system get pods -l app.kubernetes.io/name=hubble-relay
# 验证 Hubble UI 就绪
kubectl -n kube-system get pods -l app.kubernetes.io/name=hubble-ui
4.4 网络无缝切换验证
部署完成后,需要验证集群网络功能正常:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 # 验证跨节点 Pod 通信
kubectl run test-net --image=busybox --rm -it -- \
wget -qO- http://kubernetes.default.svc.cluster.local
# 验证 DNS 解析
kubectl run test-dns --image=busybox --rm -it -- \
nslookup kubernetes.default.svc.cluster.local
# 验证 NetworkPolicy 生效
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-default
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
# 检查 Hubble 是否捕获到 DROP 事件
hubble observe --type drop --last 1m

五、Hubble 实战:全链路流量分析与故障排查
部署完成后,让我们通过几个真实的排查场景来展示 Hubble 的强大能力。
5.1 CLI 工具安装与基础用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 # 安装 Hubble CLI
curl -LO https://github.com/cilium/hubble/releases/latest/download/hubble-linux-amd64.tar.gz
tar xzf hubble-linux-amd64.tar.gz
mv hubble /usr/local/bin/
# 配置端口转发访问 Relay
kubectl port-forward -n kube-system svc/hubble-relay 4245:4245 &
# 设置 Hubble CLI 连接
hubble config set relay localhost:4245
# 查看实时流量
hubble observe --follow
# 过滤特定命名空间的流量
hubble observe --namespace production --follow
# 只看 DNS 事件
hubble observe --type dns --follow
# 只看被拒绝的流量
hubble observe --type drop --follow
# 查看特定 Pod 的流量
hubble observe --to-pod production/backend-7d4f8b6c5-x2k9j --follow
5.2 场景一:服务间间歇性超时排查
假设前端服务调用后端 API 间歇性超时。使用 Hubble 可以快速定位问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 # 第一步:查看 frontend 到 backend 的所有流量
hubble observe \
--from-pod default/frontend-5c8f9d7b4d-abc12 \
--to-pod default/backend-6d7g8e9c5e-xyz34 \
--last 10m
# 第二步:过滤 TCP 层面的异常事件
hubble observe \
--from-pod default/frontend-5c8f9d7b4d-abc12 \
--type tcp --last 10m
# 第三步:查看 DNS 解析延迟
hubble observe \
--from-pod default/frontend-5c8f9d7b4d-abc12 \
--type dns \
--dns-query backend.default.svc.cluster.local \
--last 10m
# 第四步:检查是否有 NetworkPolicy 拦截
hubble observe \
--from-pod default/frontend-5c8f9d7b4d-abc12 \
--type drop \
--last 10m
通过 Hubble 的事件输出,你可以清楚看到每个请求的完整生命周期:DNS 解析耗时、TCP 握手是否成功、是否被网络策略拒绝、是否存在 TCP 重传。这是传统 tcpdump 无法提供的信息维度。
5.3 场景二:NetworkPolicy 效果验证
部署了一条新的 CiliumNetworkPolicy 后,你需要验证它是否按预期生效:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 # 查看被策略拒绝的流量及策略名称
hubble observe --type drop --last 5m \
--output jsonpb | jq ".drop.reason, .policy"
# 验证允许的流量确实通过了
hubble observe \
--from-pod default/frontend \
--to-pod default/backend \
--to-port 8080 \
--type trace \
--last 5m
# 导出流量数据用于审计
hubble observe --type drop --last 1h \
--output jsonpb > policy_drops.json
5.4 场景三:HTTP 层面的可观测性
Hubble 不仅能看到网络层,还能解析 HTTP 协议(需要启用 http 指标),提供应用层面的可观测性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 # 查看 HTTP 请求和响应
hubble observe \
--type http \
--from-pod default/frontend \
--last 5m
# 输出示例:
# Jul 27 10:30:15.534 default/frontend GET http://backend/api/users 200 3ms
# Jul 27 10:30:16.102 default/frontend GET http://backend/api/orders 503 1ms
# Jul 27 10:30:16.789 default/frontend POST http://backend/api/cart 201 5ms
# 过滤特定 HTTP 状态码
hubble observe --type http --http-status 5xx --last 5m
# 过滤特定 URL 路径
hubble observe --type http --http-path /api/users --last 5m
这种应用层的可观测性完全不需要修改应用代码或注入 Sidecar,是 eBPF 方案最大的优势。

六、与 Prometheus 和 Grafana 集成构建监控大盘
Hubble 的指标数据可以直接导出到 Prometheus,结合 Grafana 构建完整的网络监控体系。
6.1 关键指标说明
Hubble 暴露的 Prometheus 指标涵盖了网络可观测性的各个维度:
| 指标名称 | 含义 | 典型告警阈值 |
|---|---|---|
| hubble_dns_responses_total | DNS 响应计数 | 解析失败率大于5% |
| hubble_drop_total | 被丢弃的包计数 | 非预期 DROP 大于0 |
| hubble_tcp_connection_duration_seconds | TCP 连接持续时间 | P99 大于5s |
| hubble_flows_processed_total | 处理的流总数 | 骤降可能意味着采集异常 |
| hubble_http_request_duration_seconds | HTTP 请求延迟 | P99 大于2s |
6.2 Grafana Dashboard 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 # 示例:Prometheus 告警规则
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: hubble-network-alerts
namespace: monitoring
spec:
groups:
- name: hubble.network
rules:
- alert: HighDNSFailureRate
expr: |
rate(hubble_dns_responses_total{rcode!="No Error"}[5m])
/ rate(hubble_dns_responses_total[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "DNS 解析失败率过高"
- alert: UnexpectedPacketDrops
expr: rate(hubble_drop_total{reason!="policy denied"}[5m]) > 0
for: 2m
labels:
severity: critical
annotations:
summary: "检测到非策略原因的丢包"
七、性能调优与生产注意事项
7.1 eBPF Map 大小调优
在大规模集群中,默认的 eBPF Map 大小可能不够用,导致事件丢失:
1
2
3
4
5
6
7
8
9
10 # 在 values.yaml 中调整
bpf:
# Conntrack 表大小(默认 524288,大规模集群建议翻倍)
conntrack: 1048576
# NAT 表大小
ctNatAny: 524288
# LB(负载均衡)Map 大小
lbMapMax: 65536
# 邻居表大小
neighMapMax: 524288
7.2 Hubble 事件采样与保留
在高流量集群中,全量采集所有网络事件会消耗大量资源。Cilium 提供了事件采样机制:
1
2
3
4
5
6 # 在 values.yaml 中配置采样
hubble:
eventBufferCapacity: 16384
eventQueueSize: 16384
# 丢弃事件时的日志级别
dropEvents: warning
7.3 Hubble Relay 高可用
Hubble Relay 是全局流量的聚合点,其可用性直接影响可观测性。生产环境建议:
- 部署 2-3 个 Relay 副本,配置 PDB 确保至少 1 个可用
- Relay 后端使用 Kubernetes Service 做负载均衡,客户端自动重连
- 如果不需要历史回溯,可以关闭 Relay 的持久化存储,减少资源消耗
7.4 内核版本与特性兼容性
不同内核版本对 eBPF 特性的支持程度不同。以下是关键特性与内核版本的对应关系:
| 特性 | 最低内核版本 | 推荐内核版本 |
|---|---|---|
| 基础网络可观测性 | 4.19 | 5.4+ |
| 替换 kube-proxy | 5.10 | 5.15+ |
| 带宽管理(EDT) | 5.1 | 5.15+ |
| 主机路由优化 | 5.10 | 5.15+ |
| WireGuard 加密 | 5.6 | 5.15+ |
| 大数据包分段跟踪 | 5.15 | 6.1+ |
如果集群运行在云厂商的托管 K8s 上,建议选择较新的节点镜像版本。GKE 的 COS containerd 镜像默认内核版本为 5.15+,EKS 的 Amazon Linux 2023 默认内核为 6.1+,AKS 的 Ubuntu 22.04 镜像默认内核为 5.15+,基本都能满足 Cilium 的完整功能需求。
八、总结与选型建议
Cilium Hubble 代表了 Kubernetes 网络可观测性的未来方向。通过 eBPF 实现的零侵入监控,在不牺牲性能的前提下提供了从网络层到应用层的全链路可视化。相比传统的 Sidecar 模式,它省去了 15%-20% 的资源开销;相比 tcpdump 等手工工具,它提供了自动化的全集群视角和 Kubernetes 语义关联。
但 Hubble 并不是银弹。如果你的团队对 eBPF 完全不熟悉,初始的学习曲线可能较陡。此外,某些高级功能(如 HTTP 层面的完整负载解析)仍需要内核 5.10+ 的支持。对于刚开始探索网络可观测性的团队,建议按以下路径渐进式采用:
- 第一阶段:部署 Cilium 作为 CNI,启用 Hubble 的基础网络指标(DNS、TCP、Drop),替代 tcpdump 进行故障排查
- 第二阶段:迁移到 CiliumNetworkPolicy,利用 Hubble 的策略验证能力确保网络安全策略正确生效
- 第三阶段:启用 HTTP 指标和服务地图,构建应用层面的可观测性
- 第四阶段:评估替换 kube-proxy,开启 eBPF 的完整网络控制平面能力
网络可观测性是云原生成熟度的重要标志。当你不再需要逐节点登录抓包,而是在一个界面中看到全集群的流量拓扑、策略执行和异常事件时,你的 K8s 运维效率将提升一个量级。eBPF 和 Cilium Hubble,正是实现这一目标的最优路径。
汤不热吧