欢迎光临

eBPF可观测性深度实战:从内核探针到Cilium Tetragon,构建零侵入式云原生监控体系

在云原生时代,系统复杂度呈指数级增长。一个微服务请求可能穿越负载均衡、API网关、服务网格、数据库代理等多层组件,传统的基于Agent的监控方案不仅资源开销大,而且难以捕获内核层面的真实行为。eBPF(Extended Berkeley Packet Filter)技术的崛起,让我们能够以近乎零开销的方式在Linux内核中运行沙箱程序,实现网络监控、安全审计、性能分析等能力,而无需修改内核源码或加载内核模块。

本文将从eBPF的基础原理出发,逐步深入到BCC工具链使用、内核探针编写、Cilium网络可观测性、Tetragon安全监控等实战场景,帮助你在生产环境中构建一套完整的零侵入式可观测性体系。

eBPF内核可观测性架构示意图

一、eBPF技术原理与架构解析

eBPF的核心思想是在内核中运行用户定义的沙箱程序,但不像内核模块那样拥有完整的内核权限。eBPF程序通过JIT编译器转换为本地机器码执行,同时经过验证器(Verifier)的安全检查,确保不会导致内核崩溃或陷入死循环。

1.1 eBPF程序的生命周期

一个eBPF程序从编写到执行,需要经过以下关键阶段:

  • 编写:使用C语言(或部分高级语言)编写eBPF程序,通过Clang编译为BPF字节码(ELF格式)
  • 验证:内核验证器检查字节码的安全性——确保无无限循环、无越界内存访问、无未初始化的寄存器使用
  • JIT编译:验证通过后,JIT编译器将字节码转换为宿主机原生机器码,执行效率接近内核原生代码
  • 挂载:将编译后的程序附加到内核hook点(kprobes、tracepoints、XDP、TC等)
  • 数据交换:通过BPF Maps在内核态和用户态之间传递数据

1.2 核心Hook点类型

Hook类型 触发时机 典型用途
kprobes 内核函数入口/出口 函数级性能分析、参数捕获
tracepoints 内核预定义追踪点 系统调用追踪、调度事件
XDP 网卡收包最早阶段 高性能包过滤、DDoS防护
TC 流量控制层 网络策略、流量整形
uprobes 用户态函数入口/出口 应用函数级追踪
perf_events 性能计数器事件 CPU profiling、缓存分析

二、开发环境搭建与BCC工具链实战

BCC(BPF Compiler Collection)是最流行的eBPF开发框架之一,它提供了Python绑定,让你可以用Python编写用户态控制逻辑,用C编写内核态eBPF程序。以下是完整的搭建流程:

2.1 安装BCC工具链


1
2
3
4
5
6
7
8
9
10
11
12
# Ubuntu 22.04+ / 24.04
sudo apt-get update
sudo apt-get install -y bpftrace bpfcc-tools python3-bpfcc \
  linux-headers-$(uname -r) clang llvm libelf-dev

# 验证安装
bpftool version
bpftrace --version

# CentOS / RHEL 9
sudo dnf install -y bcc-tools bcc-devel llvm-toolset
export PATH=$PATH:/usr/share/bcc/tools

2.2 用BCC编写第一个eBPF程序

下面的程序追踪所有进程的

1
execve

系统调用,记录每个进程执行的命令行参数:


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
#!/usr/bin/env python3
from bcc import BPF
from datetime import datetime

# eBPF C程序
bpf_text = '''
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>

BPF_HASH(exec_calls, u32, u64);

TRACEPOINT_PROBE(syscalls, sys_enter_execve) {
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    u64 zero = 0, *count;
   
    count = exec_calls.lookup_or_try_init(&pid, &zero);
    if (count) {
        (*count)++;
    }
   
    char comm[TASK_COMM_LEN];
    bpf_get_current_comm(&comm, sizeof(comm));
   
    bpf_trace_printk("execve by %s (pid=%d)\n", comm, pid);
    return 0;
}
'''

b = BPF(text=bpf_text)
print("Tracing execve syscalls... Ctrl-C to quit.")

while True:
    try:
        (task, pid, cpu, flags, ts, msg) = b.trace_fields()
        print("%-8s %-6s %-16s" % (
            datetime.now().strftime("%H:%M:%S"),
            pid, task))
    except ValueError:
        continue

运行后,每当任何进程执行

1
execve

系统调用时,你都会看到实时输出。这对于排查”谁在启动什么进程”这类问题非常有效——尤其是在Kubernetes集群中排查异常进程时。

eBPF程序追踪输出演示

三、用bpftrace进行高级性能分析

bpftrace是另一个强大的eBPF前端工具,它使用一种类似AWK的DSL语言,适合快速编写一次性探针脚本。在生产排障中,bpftrace往往是你的第一选择。

3.1 一行命令追踪系统调用延迟


1
2
3
4
5
6
7
8
9
10
11
12
13
# 追踪所有进程的 read() 系统调用耗时分布(直方图)
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_read { @start[tid] = nsecs; }
  tracepoint:syscalls:sys_exit_read /@start[tid]/ {
    @us = hist((nsecs - @start[tid]) / 1000);
    delete(@start[tid]);
  }'

# 追踪特定进程的文件打开操作
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat
  /comm == "nginx"/ { printf("%s opened file\n", comm); }'

# 统计每个CPU核心上的进程调度次数
sudo bpftrace -e 'tracepoint:sched:sched_switch { @[cpu] = count(); }'

3.2 追踪TCP连接建立延迟

下面的脚本追踪TCP三次握手的完成时间,帮助你发现网络延迟问题:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
kprobe:tcp_v4_connect {
    @connect_start[tid] = nsecs;
}

kretprobe:tcp_v4_connect /@connect_start[tid]/ {
    $latency = (nsecs - @connect_start[tid]) / 1000000;
   
    if ($latency > 100) {
        printf("SLOW CONNECT: pid=%d latency=%dms\n", pid, $latency);
    }
   
    @tcp_connect_latency_ms = hist($latency);
    delete(@connect_start[tid]);
}

这个脚本不仅能展示连接延迟的分布直方图,还会在延迟超过100ms时打印警告。在微服务架构中,这类信息对于定位跨服务调用的网络瓶颈至关重要。

四、Cilium:基于eBPF的云原生网络可观测性

Cilium是目前最成熟的eBPF网络方案,它完全用eBPF替换了kube-proxy的iptables规则,同时提供了强大的网络可观测性能力。Cilium的Hubble组件可以实时可视化服务间的流量拓扑。

4.1 在Kubernetes集群中安装Cilium


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 安装 cilium CLI
CILIUM_CLI_VERSION=$(curl -s https://api.github.com/repos/cilium/cilium-cli/releases/latest | grep tag_name | cut -d '"' -f 4)
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz{,.sha256sum}
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin

# 安装 Cilium(替换默认 CNI)
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.16.0 \
  --namespace kube-system \
  --set kubeProxyReplacement=true \
  --set hubble.enabled=true \
  --set hubble.metrics.enabled="{dns,drop,tcp,udp,icmp,http,flows}" \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

# 验证安装
cilium status --wait
cilium connectivity test

4.2 使用Hubble观测服务流量


1
2
3
4
5
6
7
8
9
10
11
12
# 实时查看所有HTTP流量
hubble observe --type traffic --protocol http

# 查看特定命名空间的流量
hubble observe --namespace default --verdict DROPPED

# 查看DNS查询
hubble observe --type traffic --protocol dns --follow

# 导出流量指标到Prometheus
kubectl port-forward -n kube-system svc/hubble-metrics 9965:9965 &
curl -s http://localhost:9965/metrics | grep hubble

Hubble的可观测性数据完全来自eBPF程序在内核中采集的网络事件,不需要Sidecar代理,不需要修改应用代码,开销极低。在百节点集群中,Cilium的网络可观测性组件额外CPU消耗不超过2%。

Cilium Hubble服务流量拓扑可视化

五、Tetragon:eBPF驱动的运行时安全监控

Tetragon是Cilium团队推出的安全可观测性与运行时执行框架。与传统的基于日志的SIEM方案不同,Tetragon直接在内核层面监控安全事件,能够实现毫秒级的实时告警和阻断。

5.1 安装Tetragon


1
2
3
4
5
6
7
8
9
helm repo add cilium https://helm.cilium.io/
helm install tetragon cilium/tetragon --version 1.2.0 \
  --namespace kube-system

# 安装 tetragon CLI
tetragon version

# 查看实时安全事件
kubectl logs -n kube-system ds/tetragon -l k8s-app=tetragon -f

5.2 编写TracingPolicy检测异常行为

以下策略检测容器内执行Shell的行为——这在正常应用中几乎不会发生,通常是攻击者利用RCE漏洞后的第一步:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: detect-shell-exec-in-container
spec:
  kprobes:
  - name: execve_monitor
    syscall: true
    args:
    - index: 0
      type: "string"
    selectors:
    - matchBinaries:
      - operator: "In"
        values:
        - "/bin/sh"
        - "/bin/bash"
        - "/bin/zsh"
      matchActions:
      - action: Sigkill
      - action: Post

这个策略不仅会记录事件,还会通过

1
Sigkill

动作直接终止违规进程。这种”检测即阻断”的能力是传统安全方案难以实现的——因为传统方案需要在事件日志流转到SIEM平台后才能分析告警,通常有数秒到数分钟的延迟。

5.3 检测敏感文件访问


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: detect-sensitive-file-access
spec:
  kprobes:
  - name: open_sensitive_files
    syscall: true
    args:
    - index: 0
      type: "string"
    selectors:
    - matchArgs:
      - index: 0
        operator: "Prefix"
        values:
        - "/etc/shadow"
        - "/etc/passwd"
        - "/root/.ssh/"
        - "/var/run/docker.sock"
        - "/proc/1/root"
      matchActions:
      - action: Post
        rateLimit: "1s"

该策略监控对

1
/etc/shadow

、SSH密钥目录、Docker socket等敏感路径的访问,并在每秒最多上报一次(通过

1
rateLimit

避免告警风暴)。在容器逃逸攻击场景中,攻击者通常会尝试访问宿主机的这些敏感路径。

六、生产环境部署最佳实践

6.1 性能调优要点

eBPF程序虽然开销低,但在高流量场景下仍需注意性能优化:

  • 使用Per-CPU Maps:避免多CPU竞争,
    1
    BPF_PERCPU_HASH

    比普通

    1
    BPF_HASH

    在高并发下性能高10倍以上

  • 限制Map大小:根据实际需求设置Map的最大条目数,避免内存浪费
  • 使用ringbuf替代perf buffer
    1
    BPF_RINGBUF

    是Linux 5.8+引入的高性能环形缓冲区,支持无锁写入和大数据传输

  • 合理设置采样率:对于高频事件(如每个网络包),使用采样逻辑避免数据洪流

6.2 与现有可观测性栈集成


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Cilium metrics 提供给 Prometheus 抓取
scrape_configs:
  - job_name: 'cilium'
    kubernetes_sd_configs:
    - role: pod
    relabel_configs:
    - source_labels: [__meta_kubernetes_pod_label_k8s_app]
      regex: cilium
      action: keep
    - source_labels: [__meta_kubernetes_pod_container_port_number]
      regex: '9962'
      action: keep

  - job_name: 'hubble'
    kubernetes_sd_configs:
    - role: pod
    relabel_configs:
    - source_labels: [__meta_kubernetes_pod_label_k8s_app]
      regex: hubble-relay
      action: keep

对于Tetragon的安全事件,可以通过其gRPC API将事件流导出到ELK或Loki进行长期存储和关联分析:


1
2
3
4
5
6
7
8
9
10
11
# 使用 tetra CLI 导出事件为JSON
tetra observe --output json |   jq 'select(.type == "alert")'   > /var/log/tetragon-alerts.jsonl

# 配置 Filebeat 采集
filebeat.inputs:
  - type: log
    paths:
      - /var/log/tetragon-alerts.jsonl
    json.keys_under_root: true
output.elasticsearch:
  hosts: ["elasticsearch:9200"]

6.3 内核版本兼容性矩阵

功能特性 最低内核版本 推荐版本
基础kprobes/tracepoints 4.4 5.4+
BTF(BPF Type Format) 5.2 5.10+
ringbuf 5.8 5.15+
XDP native driver mode 4.8 5.10+
Cilium full kube-proxy replacement 5.4 5.10+
Tetragon Sigkill enforcement 5.3 5.15+
bpf_iter(迭代器) 5.8 5.15+

七、eBPF可观测性方案与传统方案对比

为了更清晰地理解eBPF的优势,下表对比了eBPF方案与传统可观测性方案在关键维度上的差异:

维度 传统Agent方案 Sidecar方案 eBPF方案
资源开销 高(每节点100-500MB) 很高(每Pod额外内存) 极低(每节点小于50MB)
侵入性 需安装Agent进程 需修改Pod spec 零侵入(内核层运行)
数据粒度 应用层指标 应用层指标+部分网络 内核级全栈可见
延迟感知 秒级 毫秒级 微秒级
安全检测 基于日志分析 不适用 实时内核级阻断
部署复杂度 高(需改部署) 低(DaemonSet)

eBPF与传统监控方案性能对比

总结

eBPF正在重新定义云原生可观测性的边界。从内核函数级追踪到网络流量可视化,从性能分析到安全阻断,eBPF提供了一套统一的、零侵入的解决方案。在2026年,主流的云厂商(AWS、Google Cloud、Azure)都已经在其托管Kubernetes服务中支持或默认启用eBPF网络方案。

对于运维工程师和SRE来说,掌握eBPF工具链(BCC、bpftrace、Cilium、Tetragon)已经成为必备技能。建议从以下路径入手实践:

  1. 先用bpftrace在本地机器上运行几个一行命令,感受eBPF的即时反馈能力
  2. 在测试Kubernetes集群中部署Cilium,体验Hubble的流量可视化
  3. 编写自定义TracingPolicy,用Tetragon实现安全审计规则
  4. 将Cilium和Tetragon的指标接入现有Prometheus/Grafana监控栈
  5. 在生产环境中逐步替换传统Agent方案,观察资源开销和可观测性数据质量的变化

eBPF不是银弹,但它确实是目前在内核层面实现可观测性最优雅、最高效的方案。随着内核版本的迭代和工具链的成熟,eBPF将在更多场景中替代传统方案,成为云原生基础设施的标准组件。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » eBPF可观测性深度实战:从内核探针到Cilium Tetragon,构建零侵入式云原生监控体系
分享到: 更多 (0)