第29章 Service Mesh 数据面:Envoy Sidecar 全链路
学习目标
- 把前面所有要素串成一条线:sidecar 劫持 + Envoy + mTLS + xDS + L7 = Mesh 数据面
- 走通一次服务间调用穿过两个 Envoy 的完整链路
- 理解控制面如何用 xDS 把 VirtualService/DestinationRule 下发成数据面配置
- 厘清 Service Mesh 与 API 网关的分工与融合
前置知识
- 第15章 Envoy/xDS、第26章 sidecar 劫持、第05章 mTLS、第10章 L7
- apiGateway · 服务网格(控制面/Istio 治理视角,与本章互补)
原理
Mesh 数据面 = 你已学的一切的组合
Service Mesh 听起来高深,但从本书视角看,它的数据面就是把前面的代理技术组合起来:
Service Mesh 数据面 = 每 Pod 一个 Envoy(第15章)
+ 透明流量劫持(第26章 iptables / 第11章)
+ 自动 mTLS(第05章)
+ xDS 动态配置(第15章)
+ L7 路由/重试/熔断(第10章)
一句话:Mesh 数据面 = 被控制面编排的、每 Pod 一个的 L7 反向代理网格。它治理的是东西流量(服务间,第27章 的对照)。
一次服务间调用的完整链路
服务 A 调用服务 B,请求穿过两个 Envoy,全程业务无感:
┌─ A Pod ─────────┐ ┌─ B Pod ─────────┐
│ A-app │ │ B-app │
│ │①出站 │ │ ⑥入站│ │
│ ▼ iptables │ │ iptables▲ │
│ A-Envoy:15001 │ │ B-Envoy:15006 │
└───┬──────────────┘ └──────────────▲──┘
│②选路由(RDS) ③负载均衡选B实例(EDS) ⑤mTLS解密+鉴权│
│④mTLS加密(SDS证书) │
└──────────────── 加密隧道 ──────────────────────────────┘
① A-app 发出请求 → 被 iptables 劫持到 A-Envoy:15001(出站,第26章)
② A-Envoy 按路由规则(VirtualService→RDS)决定去哪个服务
③ 按负载均衡从 B 的实例列表(EDS)选一个,应用熔断/重试/超时
④ 用 SDS 下发的证书与 B 建 mTLS(第05章)
⑤ B-Envoy:15006 收到,mTLS 解密 + 鉴权(AuthorizationPolicy)
⑥ 转发给 B-app。回程对称。全程 A-app/B-app 无感
每一跳的能力都是前面学过的:路由(第10章)、负载均衡(第09章)、mTLS(第05章)、Envoy filter(第15章)。
控制面如何驱动数据面(xDS 落地)
数据面 Envoy 本身不"懂"业务规则,全靠控制面(Istiod)翻译 + 下发:
你写的高层 CRD 控制面 Istiod 翻译 下发给数据面 Envoy(xDS,第15章)
────────────── ───────────────── ────────────────────────────
VirtualService ──▶ 路由规则 ──▶ RDS(Route)
DestinationRule ──▶ 负载均衡/熔断/子集 ──▶ CDS(Cluster)
Service/Endpoints ──▶ 实例列表 ──▶ EDS(Endpoint)
PeerAuthentication──▶ mTLS 策略 + 证书 ──▶ SDS(Secret)+ Listener
Gateway ──▶ 入口监听器 ──▶ LDS(Listener)
这就是 第24章 的"数据面 vs 控制面"分工的终极体现:Envoy(C++) 跑数据,Istiod(Go) 算配置。你改一个 VirtualService,Istiod 算出新路由,xDS 秒级推给所有相关 Envoy,无 reload、无重启。
Mesh 提供的能力总表
| 维度 | Mesh 数据面能力 | 来自本书 |
|---|---|---|
| 安全 | 自动 mTLS、零信任、AuthorizationPolicy | 第05章 |
| 流量管理 | 灰度/金丝雀、流量镜像、故障注入、超时重试熔断 | 第10章、第15章 |
| 可观测 | 黄金指标、分布式追踪、访问日志(每请求) | 第10章 |
| 弹性 | 负载均衡、连接池、异常剔除 | 第09章 |
代价与演进
- 代价:每 Pod 一个 sidecar 的资源/延迟开销、整体复杂度、调试难度(第26章)
- 演进:Ambient Mesh(ztunnel + waypoint)去 sidecar 化、eBPF 加速数据面(第11章、第12章)
Mesh 与 API 网关:分工与融合
| API 网关(apiGateway 手册) | Service Mesh | |
|---|---|---|
| 流量 | 南北(外→内,第27章) | 东西(服务间) |
| 形态 | 集中式入口 | 分布式 sidecar |
| 关注 | 认证、限流、API 管理 | 服务间 mTLS、路由、可观测 |
两者正在融合:Gateway API(第27章)成为统一入口标准,Istio 既做 mesh 又做 ingress gateway。详细的治理视角(Istio 组件、灰度、熔断)见 apiGateway · 服务网格,本书聚焦"数据面=代理"这一面。
️ 实现 / 命令
实验一:观察请求穿过两个 Envoy
# 看 A 的 sidecar 访问日志,能看到出站记录
kubectl logs <a-pod> -c istio-proxy | tail
# [out] "GET /api HTTP/1.1" 200 ... → b-svc.default.svc.cluster.local
# 看 B 的 sidecar,能看到对应的入站记录 → 一次调用两条日志,证明穿过了两个 Envoy
kubectl logs <b-pod> -c istio-proxy | tail
实验二:VirtualService 灰度(控制面→数据面)
# 90% 流量到 v1,10% 到 v2(金丝雀,第10章按权重)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata: { name: b-route }
spec:
hosts: [b-svc]
http:
- route:
- { destination: { host: b-svc, subset: v1 }, weight: 90 }
- { destination: { host: b-svc, subset: v2 }, weight: 10 }
kubectl apply -f b-route.yaml
# 确认它被翻译成了数据面的路由配置(RDS)
istioctl proxy-config routes <a-pod> --name 80 -o json | grep -A3 weight
# 多次调用,约 1/10 命中 v2 —— 控制面规则秒级生效到数据面,无 reload
实验三:验证自动 mTLS
kubectl apply -f - <<'EOF'
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata: { name: default, namespace: default }
spec: { mtls: { mode: STRICT } }
EOF
# 抓 Pod 间流量:明文消失,全是 TLS(第05章)
istioctl proxy-config secret <a-pod> # 看 SDS 下发的证书
istioctl authn tls-check <a-pod> b-svc.default.svc.cluster.local
实验四:可观测(数据面自带指标)
# Envoy 暴露的黄金指标(无需改业务代码)
kubectl exec <a-pod> -c istio-proxy -- curl -s localhost:15000/stats | grep "upstream_rq_"
# upstream_rq_200 / upstream_rq_5xx / upstream_rq_time —— 请求数、错误、延迟全在数据面
排错
| 现象 | 根因 | 解决 |
|---|---|---|
调用一直 503 UH | 无健康 upstream / mTLS 不匹配 | 查 proxy-config endpoints、mTLS 模式(第15章) |
| 灰度规则不生效 | sidecar 没注入 / VS 没选中 | 确认注入(第26章)、istioctl proxy-config routes |
| mTLS 报错 | 一边 STRICT 一边明文 | 统一 PeerAuthentication |
| 配置改了不生效 | xDS 没同步 | istioctl proxy-status 看是否 SYNCED |
| 延迟变高 | 每跳两个 Envoy 开销 | 评估 Ambient/资源调优 |
| 调试无从下手 | 链路太长 | istioctl proxy-config、访问日志、Kiali |
本章小结
- Mesh 数据面 = 每 Pod 一个 Envoy + 透明劫持 + 自动 mTLS + xDS + L7——全是本书前面学过的技术组合。
- 一次服务调用穿过两个 Envoy:出站选路由/负载均衡/加密 → 入站解密/鉴权 → 业务无感。
- 控制面把 VirtualService/DestinationRule/PeerAuthentication 翻译成 RDS/CDS/SDS 下发数据面(数据面 vs 控制面分工)。
- Mesh 治东西流量、网关治南北,正经 Gateway API 融合。
容器与 K8s 篇至此收官——你已把代理原理一路落到 Docker、Istio 劫持、Ingress、Egress、Mesh 数据面。最后一篇 第七篇·进阶 收尾全书:可编程代理、性能调优、排错决策树、代理安全。