297 lines
9.1 KiB
Markdown
297 lines
9.1 KiB
Markdown
|
|
---
|
|||
|
|
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 最常挂钩的地方
|