手把手教你用 eBPF 排查 K8s 网络问题

前言:为什么需要 eBPF?

生产环境告警响起——数据库连接数瞬间飙高,可 kubectl get pods 一片绿色。过去我们靠 tcpdump + iptables -L 盲排,既费时又破坏线上流量。

eBPF(Extended Berkeley Packet Filter)技术让我们第一次能在不停业务的前提下,精准追踪每一条跨 Pod 流量,实现内核级可观测。本文基于 Cilium 1.17 和最新内核实践,提供可直接落地的排查方法论。


一、环境准备:生产级前置检查

1.1 内核版本要求

eBPF 功能对内核版本敏感,生产环境建议:

# 检查内核版本(推荐 ≥ 5.10,最低 ≥ 4.19.57)
uname -r

# 检查 BPF 特性支持
bpftool feature probe | grep -E "program_type|map_type"

# 关键检查项:BTF 支持(CO-RE 必需)
ls /sys/kernel/btf/vmlinux

生产提示:标准化内核版本 across 所有节点,避免 CO-RE(Compile Once - Run Everywhere)兼容性问题 。

1.2 快速部署排查工具

# 安装 kubectl-trace(无需在节点预装组件)
kubectl krew install trace

# 安装 bpftool(节点级调试)
yum install -y bpftool || apt-get install -y bpftool

# Cilium 集群确认 eBPF 模式
cilium status | grep "KubeProxyReplacement"
# 预期输出:KubeProxyReplacement: Strict

二、网络问题排查

场景 1:Pod 无法访问 ClusterIP,但 PodIP 正常

现象curl <service-ip>:port 超时,直接访问后端 Pod IP 正常。

排查流程

# Step 1: 确认 Cilium 代理模式
kubectl -n kube-system exec ds/cilium -- cilium status | grep "KubeProxyReplacement"

# Step 2: 检查 eBPF 程序加载状态
kubectl -n kube-system exec ds/cilium -- bpftool prog show | grep cilium

# Step 3: 查看 Service 映射表(替代 iptables -t nat -L)
kubectl -n kube-system exec ds/cilium -- cilium service list
# 预期看到:ClusterIP -> Backend Pod IPs 的映射

# Step 4: 追踪数据包路径
kubectl trace run <node-name> -e 'kprobe:tcp_v4_connect { printf("PID %d connecting to %s\n", pid, ntop(AF_INET, arg2)); }'

根因定位:若 cilium service list 无对应条目,确认 kubeProxyReplacement=strict 已生效且 Service CIDR 正确写入 CT LB Map 。


场景 2:NetworkPolicy 误拦截导致连接超时

现象:应用间通信随机超时,无明确错误日志。

排查流程

# 启用 Hubble 实时观测(Cilium 内置)
hubble observe --verdict DROPPED -f

# 典型输出:
# default/client-xxx:35044 (ID:4605) <> default/server-xxx:80 (ID:22656) Policy denied DROPPED (TCP Flags: SYN)
# default/client-xxx:35044 (ID:4605) <> default/server-xxx:80 (ID:22656) policy-verdict:none INGRESS DENIED (TCP Flags: SYN)

# 查看具体策略命中
kubectl -n kube-system exec ds/cilium -- cilium endpoint list | grep <pod-id>

修复建议:使用 CiliumNetworkPolicy 替代原生 NetworkPolicy,支持基于 Identity 的细粒度控制,避免标签选择器交叉导致的"假阳性"拦截 。


场景 3:跨节点 Pod 丢包(VXLAN/Direct Routing 模式)

现象:同节点 Pod 通信正常,跨节点丢包。

排查流程

# 检查隧道映射(VXLAN 模式)
kubectl -n kube-system exec ds/cilium -- cilium bpf tunnel list

# 检查路由和邻居表(Direct Routing 模式)
kubectl -n kube-system exec ds/cilium -- cilium bpf neigh list

# 使用 bpftrace 追踪跨节点流量
kubectl trace run <node-name> -e 'tracepoint:skb:kfree_skb { printf("Drop reason: %s\n", args->location); }'

# 检查底层网络
ip route show table all | grep <remote-node-cidr>
arp -n | grep <remote-node-ip>

生产经验:若采用 Direct-Routing,检查 ToR(Top-of-Rack)交换机的 ARP Proxy / ECMP 配置;必要时切换为 VXLAN 模式确保稳定性 。


场景 4:DNS 解析间歇性失败

现象:应用日志显示 NXDOMAIN 或超时,CoreDNS Pod 状态正常。

排查流程

# 使用 eBPF 追踪 DNS 查询路径
kubectl trace run <node-name> -e 'kprobe:udp_sendmsg /comm == "coredns"/ { printf("DNS query from %d\n", pid); }'

# 检查 Cilium DNS 策略(若启用 L7 策略)
kubectl -n kube-system exec ds/cilium -- cilium policy get | grep -A5 "dns"

# 查看 Hubble DNS 指标
hubble observe --protocol DNS --namespace kube-system

根因:常见为 Cilium L7 DNS 策略的 FQDN 缓存过期或通配符规则配置不当,导致合法查询被拦截。


场景 5:高并发场景下连接追踪表溢出

现象:大流量压测时新建连接失败,conntrack -L 显示表满。

排查流程

# 检查 conntrack 状态(传统 iptables 模式)
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max

# Cilium eBPF 模式下检查 CT Map
kubectl -n kube-system exec ds/cilium -- cilium bpf ct list global | wc -l
kubectl -n kube-system exec ds/cilium -- cilium bpf metrics list | grep conntrack

# 动态调整 Map 大小(生产环境)
helm upgrade cilium cilium/cilium -n kube-system \
  --set bpf.ctTcpMax=524288 \
  --set bpf.ctAnyMax=262144 \
  --set bpf.mapDynamicSizeRatio=0.0025

性能对比:eBPF Map 相比传统 conntrack,查询复杂度为 O(1),且支持动态扩容,在高并发场景下 CPU 开销降低 40%-60% 。


三、生产环境最佳实践

3.1 可观测性体系建设

# Cilium Hubble 指标配置(Prometheus 集成)
apiVersion: v1
kind: ConfigMap
metadata:
  name: cilium-config
  namespace: kube-system
data:
  enable-hubble: "true"
  hubble-metrics-server: ":9965"
  hubble-metrics: |
    dns:query;ignoreAAAA
    drop:sourceContext=identity;destinationContext=identity
    tcp:sourceContext=identity;destinationContext=identity
    flow:sourceContext=identity;destinationContext=identity
    icmp:sourceContext=identity;destinationContext=identity
    http:sourceContext=identity;destinationContext=identity

3.2 安全加固要点

  1. 权限控制:限制 CAP_BPFCAP_SYS_ADMIN 能力,仅允许预编译签名的 eBPF 程序加载
  2. 资源隔离:使用 cgroup 控制 eBPF 程序的资源消耗,避免"吵闹邻居"影响
  3. 审计日志:建立 eBPF 程序加载、Map 访问的完整审计链路

3.3 性能调优清单

优化项配置建议效果
XDP 加速loadBalancer.acceleration=native降低延迟 30%
CPU 绑定resources.limits.cpu=2000m避免调度抖动
Ring Buffer使用 per-CPU Map减少并发竞争
动态采样高负载时降低追踪频率控制 overhead < 1%

四、工具链速查表

工具适用场景命令示例
kubectl-trace集群级动态追踪kubectl trace run node-1 -e 'kprobe:tcp_drop'
bpftrace快速原型开发bpftrace -e 'kprobe:ip_vs_* { @[probe] = count(); }'
bpftool程序/Map inspectionbpftool prog show / bpftool map dump id <id>
cilium-cliCilium 专属诊断cilium connectivity test / cilium sysdump
Hubble CLI流量可视化hubble observe --verdict DROPPED --follow
BCC tools深度系统分析tcplife / tcpdrop / execsnoop

五、总结

eBPF 技术正在重塑 Kubernetes 网络运维范式:

  1. 从黑盒到白盒:Hubble 提供 L3-L7 全链路秒级追踪,定位网络抖动不再靠抓包
  2. 从被动到主动:基于 Identity 的 NetworkPolicy 实现零信任东西向隔离
  3. 从低效到高性能:eBPF 替代 iptables,Service 数量 >1000 时性能优势显著

给 SRE 的临别赠言:生产环境不是儿戏,升级内核、拥抱 eBPF 需要做好运维门槛提升的准备。但当你的集群规模爆炸式增长时,eBPF 可能是救命的稻草。


本文基于 Cilium 1.17.5、Kernel 5.15+ 生产环境实践整理,建议定期关注内核版本与 eBPF 特性兼容性更新。

更多推荐