Files
2026-05-24 11:42:38 +08:00

297 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [计算机网络, eBPF, XDP, kprobe, Tracepoint, ServiceMesh, Istio, Envoy]
create time: 2026-05-18 05:30
---
# eBPF 与 Service Mesh
## 概述
eBPF 让 Linux 内核变得可编程而不需要编译内核模块;Service Mesh(Istio/Linkerd)让微服务间的流量治理从代码中剥离到基础设施层。这两者代表了可观测性和流量治理的两个重要方向。
## eBPF(extended Berkeley Packet Filter)
### 什么是 eBPF?
eBPF 允许在**内核态安全地运行沙箱程序**,无需修改内核源码或加载内核模块。它最初是一个 packet filter 增强版,现在已扩展到 tracing、monitoring、security 等多个领域。
```
传统方案: eBPF 方案:
───────── ─────────
编译内核模块 (.ko) ↔ 编写 eBPF C 程序
手动符号导出 ↔ kprobe/kfunc/tracepoint 直接挂钩
系统重启加载 ↔ insmod bpf 即时生效
无类型安全检查 ↔ 内核验证器严格检查 (verifier)
崩溃影响全局 ↔ 沙箱隔离,失败不崩内核
无法卸载或调试 ↔ 可卸载,bpftool 可调试
```
### eBPF 的核心架构
```mermaid
flowchart TD
subgraph "用户态 (User Space)"
Prog["eBPF 程序<br/>(C/BPF 汇编)"]
Map["bpf_map<br/>KV 存储<br/>hash/array/perf_event/..."]
Tool["bpftool<br/>BCC tools<br/>bpftrace"]
end
subgraph "内核态 (Kernel Space)"
Verifier["Verifier<br/>严格安全检查"]
JIT["JIT Compiler<br/>C → x86/arm/riscv 机器码"]
subgraph "Attachment Points"
KP["kprobe / kretprobe<br/>hook 任意内核函数入口/出口"]
TP["tracepoint<br/>内核预定义探测点"]
TC["Traffic Control<br/>qdisc classifier"]
XDP["XDP (eXpress Data Path)<br/>网卡驱动级别最快路径"]
end
Map -->|"写入"| PerfEvent["perf event → 用户态采集"]
end
Tool -->|"加载"| Prog
Prog -->|"提交"| Verifier
Verifier -->|"验证通过"| JIT
JIT -->|"注册到"| KP
JIT -->|"注册到"| TP
JIT -->|"注册到"| TC
JIT -->|"注册到"| XDP
```
### eBPF 在网络中的典型应用层级
```mermaid
flowchart LR
NIC["Network Interface Card"] -.->|XDP 微秒级处理| XDP["XDP<br/>最快路径: 网卡驱动级别"]
TC["Traffic Control<br/>tc filter/qdisc"] -.->|中等路径| Stack["Linux Network Stack"]
Stack -.->|kprobe hook| Kprobe["kprobe/kretprobe<br/>TCP/IP 栈钩子"]
XDP -->|"drop/mirror/redirect"| NIC
TC -->|"police/packet/cgroup"| Stack
Kprobe -->|"tcp_connect/tcp_rcv_skb..."| App["可观测性工具"]
style XDP fill:#FF6B6B,color:#fff
style TC fill:#FFD700,color:#000
style Kprobe fill:#98FB98,color:#000
```
| 挂载点 | 性能 | 用途 | 典型工具 |
|--------|------|------|---------|
| **XDP** | 微秒级,最快 | DDoS 过滤、L4 LB、镜像 | AF_XDP, cilium-hubble |
| **tc (Traffic Control)** | 纳秒~微秒级 | qdisc 调度、带宽限制、重定向 | tc-bpf, polycube |
| **kprobe/kretprobe** | 低开销 | 追踪任意内核函数 | bcc tcpconnect, bpftrace |
| **tracepoint** | 极低开销 | 内核预定义事件 | perf trace |
| **CGroup** | 进程级 | 网络隔离、限速 | cgroup-bpf |
| **LSM** | 安全级别 | 强制访问控制 | libbpf-security |
### 常用 eBPF 工具实战
```bash
# === BCC Tools (Python-based eBPF 工具集) ===
# 追踪所有新建 TCP 连接
sudo ./tcpconnect
PID COMM IP SADDR DADDR DPORT
1234 curl 4 192.168.1.10 93.184.216.34 443
# 查看 TCP 连接存活时间
sudo ./tcplife
PID COMM FD LADDR:LADDR → RADDR:RADDR state msec
1234 chrome 42 192.168.1.10:54321→ 93.184.216.34:443 ESTAB 12345
# 查看 TCP 状态分布
sudo ./tcpstates
Tracing TCP states... Output every 1 seconds.
TIME_WAIT 42
ESTABLISHED 128
CLOSE_WAIT 0
# === bpftrace (一行脚本) ===
# 实时打印每个 TCP 包的大小
sudo bpftrace -e 'kprobe:tcp_sendmsg { @bytes[tid] = arg0; }'
# 统计每秒 DNS 查询数
sudo bpftrace -e 'tracepoint:dns:dns_query { @count++; } interval:s:1 { print(@count); clear(@count); }'
# === Cilium Hubble (Kubernetes 可观测性) ===
# 服务间流量可视化
hubble observe --namespace=default
FLOW 08:23:45.123 DefaultPod → api-server (TCP NEW) DPT=8080
FLOW 08:23:45.125 api-server → DefaultPod (TCP FIN)
# 按命名空间聚合
hubble observe --aggregate 5s
```
### eBPF 监控网络问题的经典场景
```bash
# 场景 1: 哪个进程的 TCP 连接最多?
sudo bpftrace -e '
kprobe:sock_alloc
/@pids[comm]/++
'
# 场景 2: 慢连接诊断——每个 TCP 连接耗时多久?
sudo bpftrace -e '
kprobe:tcp_v4_connect /arg0/ {
@start[tid] = nsecs;
}
kretprobe:tcp_v4_connect /arg0 >= 0/ {
$delta = (nsecs - @start[tid]) / 1000;
@latency_us = hist($delta);
delete(@start[tid]);
}'
# 场景 3: SYN Flood 检测
sudo bpftrace -e '
kprobe:tcp_v4_do_rcvd
@syn_count["SYN_RECV"]++;
interval:1s {
print(@syn_count);
clear(@syn_count);
}'
```
## Service Mesh (Istio / Linkerd)
### Sidecar 模式原理
```mermaid
flowchart LR
Pod["Pod / VM"] -->|"app container"| App["my-service v1"]
Pod -->|"proxy container"| Proxy["envoy sidecar"]
Proxy -->|"xDS API"| CP["Istiod<br/>Pilot(路由) + Citadel(mTLS)"]
CP -->|"推送配置"| Proxy
subgraph "Sidecar 自动接管:"
MTLS["mTLS 双向认证"]
Retry["重试/熔断/超时"]
Tracing["分布式链路追踪 (Jaeger)"]
Metrics["指标收集 (Prometheus)"]
Canary["金丝雀/蓝绿发布"]
Dashboard["流量仪表盘"]
end
Proxy -.-> MTLS
Proxy -.-> Retry
Proxy -.-> Tracing
Proxy -.-> Metrics
Proxy -.-> Canary
Proxy -.-> Dashboard
style Proxy fill:#DDA0DD,color:#000
style CP fill:#FFD700,color:#000
```
### Istio Traffic Management 核心资源
```yaml
# VirtualService: 路由规则
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-service
spec:
hosts: ["my-service.default.svc.cluster.local"]
http:
- match:
- headers:
x-canary: {exact: "true"}
route:
- destination: {host: my-service, subset: v2} # canary 版
weight: 100
- route:
- destination: {host: my-service, subset: v1}
weight: 90 # 正式版 90%
- destination: {host: my-service, subset: v2}
weight: 10 # 金丝雀 10%
timeout: 5s # 超时控制
retries: # 重试策略
attempts: 3
perTryTimeout: 2s
retryOn: "5xx,reset,connect-failure,gateway-error"
# DestinationRule: 定义 subset (版本分组)
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-service
spec:
host: my-service.default.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL # 自动 mTLS
connectionPool:
tcp:
maxConnections: 100 # 连接池上限
http:
h2UpgradePolicy: DEFAULT # 升级到 HTTP/2
http1MaxPendingRequests: 100
http2MaxRequests: 1000
subsets:
- name: v1 # 打标签为 v1
labels: {app-version: v1}
- name: v2 # 打标签为 v2
labels: {app-version: v2}
# Gateway: 入站流量入口
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: my-gateway
spec:
selector: {istio: ingressgateway}
servers:
- port: {number: 443, name: https, protocol: HTTPS}
tls: {mode: SIMPLE, credentialName: my-cert}
hosts: ["api.example.com"]
```
### Istio 工作原理
```
开发者视角:
──────────────
我的代码完全不知道 Service Mesh 的存在!
不需要引入任何 SDK、注解或配置。
流量全部被 envoy sidecar 拦截和转发。
运维视角:
──────────────
Istiod (control plane) 统一管理所有 envoy proxy
↓ 通过 xDS API (CDS/EDS/LDS/RDS)
推送路由规则、监听配置、集群发现给每个 sidecar
↓
sidecar 热更新配置,无需重启应用
```
```bash
# 确认 sidecar 注入成功
kubectl get pods -n default
NAME READY STATUS
my-service-abc123-xk9qp 2/2 Running ← 2/2 = app + envoy sidecar
# 检查 envoy 配置
kubectl exec -it my-service-abc123-xk9qp -c envoy -- \
envoy --admin-address-port localhost:15000 stats
# istioctl 诊断
istioctl analyze # 分析配置正确性
istioctl proxy-status # sidecar 同步状态
istioctl proxy-config routes my-service-pod # 查看某 pod 的路由表
```
## 关联笔记
- [[hhs/NETWORK/QUIC协议深度解析]] — QUIC 也是用户态实现的协议
- [[hhs/NETWORK/WireGuardVPN原理与实践]] — WireGuard 同样在内核态运行
- [[hhs/NETWORK/01-SocketAPI与backlog详解]] — Socket API 是 eBPF kprobe 最常挂钩的地方