2. 服务网格基础:Istio/Envoy 数据平面与控制平面架构、Sidecar 代理模式、流量劫持原理

服务网格(Service Mesh)是云原生微服务通信的基础设施层,它将服务间通信的复杂性从应用代码中剥离,交由专门的代理层处理。Istio 是目前最主流的服务网格实现,其底层核心代理为 Envoy。理解 Istio 的数据平面与控制平面架构、Sidecar 代理模式以及流量劫持原理,是构建安全流量拓扑基线的第一步。

2.1 控制平面与数据平面架构

Istio 采用经典的控制平面/数据平面分离架构,两者职责明确,协同工作。

核心原则: 数据平面负责处理所有业务流量,控制平面负责下发配置与策略,两者通过 xDS 协议通信,实现“数据与逻辑分离”。
平面 核心组件 主要职责 通信协议
控制平面 istiod (Pilot、Citadel、Galley) 服务发现、证书签发、配置管理、策略下发 xDS (CDS/EDS/LDS/RDS/SDS)
数据平面 Envoy Proxy (Sidecar) 流量转发、负载均衡、健康检查、TLS 终止、遥测数据采集 HTTP/1.1, HTTP/2, gRPC, TCP

控制平面(istiod) 是网格的大脑。它将用户定义的路由规则、安全策略、监控配置等转换为 Envoy 可理解的 xDS 协议配置,并通过 gRPC 流推送到每个 Sidecar 代理。

数据平面(Envoy) 是网格的肌肉。它以 Sidecar 模式部署在每个业务 Pod 中,拦截所有进出 Pod 的流量,并根据控制平面下发的配置执行路由、熔断、重试、认证等操作。

Istio 控制平面与数据平面架构图 Istio 控制平面与数据平面架构 控制平面 (Control Plane) — istiod Pilot 服务发现 & 配置下发 Citadel 证书签发 & 身份认证 Galley 配置验证 & 管理 数据平面 (Data Plane) — Envoy Sidecar Pod A (Service A) App A 业务容器 Envoy Sidecar 代理 Pod B (Service B) App B 业务容器 Envoy Sidecar 代理 xDS 协议 (gRPC) mTLS 加密流量

2.2 Sidecar 代理模式

Sidecar 模式是服务网格的核心部署形态。Istio 通过自动注入或手动注入的方式,将 Envoy 代理作为一个独立的容器添加到业务 Pod 中,与业务容器共享网络命名空间。

关键特性: Sidecar 代理对业务应用完全透明。应用无需感知代理的存在,也无需修改代码即可获得流量管理、安全、可观测性能力。

Sidecar 模式的优势:

  • 非侵入式: 业务容器只关注业务逻辑,通信能力由 Sidecar 统一提供。
  • 语言无关: 无论应用使用 Java、Go、Python 还是 Node.js,Sidecar 都使用统一的 Envoy 代理。
  • 独立升级: 代理的升级、配置变更不影响业务容器,反之亦然。
  • 安全隔离: 代理可以独立实施 TLS 终止、访问控制、限流等安全策略。
对比维度 传统 SDK 模式 Sidecar 代理模式
侵入性 高,需引入特定语言库 低,完全透明
升级成本 需重新编译部署所有服务 仅需重启 Sidecar 容器
多语言支持 每种语言需独立实现 统一代理,语言无关
资源开销 集成在进程内,开销较低 额外代理进程,增加少量延迟

2.3 流量劫持原理

流量劫持是 Sidecar 代理能够拦截所有进出 Pod 流量的关键技术。Istio 利用 iptables 规则,在 Pod 的网络命名空间内将流量重定向到 Envoy 代理的监听端口。

劫持流程:

  1. 入站劫持: 所有发往 Pod IP 的入站流量(目标端口非 15006),被 iptables 规则重定向到 Envoy 的入站端口(15006)。
  2. 出站劫持: 所有从业务容器发出的出站流量(目标端口非 15001),被 iptables 规则重定向到 Envoy 的出站端口(15001)。
  3. Envoy 处理: Envoy 根据控制平面下发的配置,对流量进行路由、策略执行、TLS 握手等操作,然后将流量转发到实际目标。
注意: 流量劫持依赖于 Pod 的 NET_ADMIN 和 NET_RAW 能力。在安全要求极高的环境中,可以通过配置 traffic.sidecar.istio.io/includeOutboundIPRanges 等注解来精细化控制劫持范围,或使用 cni 模式替代 iptables 劫持。
Sidecar 流量劫持原理图 Sidecar 流量劫持原理 (iptables 重定向) Pod 网络命名空间 业务容器 App (监听 8080) Envoy Sidecar 入站:15006 / 出站:15001 iptables 规则 (istio-init 容器注入) 入站劫持 (INBOUND) 目标非 15006 → 重定向到 15006 出站劫持 (OUTBOUND) 目标非 15001 → 重定向到 15001 外部请求 → Pod IP:8080 iptables 重定向 Envoy 处理后转发到业务容器 127.0.0.1:8080 出站请求 iptables 重定向 Envoy 处理后转发到外部目标

2.4 流量劫持的配置与验证

Istio 通过 istio-init 初始化容器在 Pod 启动时注入 iptables 规则。用户可以通过 Pod 注解或全局配置调整劫持行为。

常用劫持配置注解:

  • traffic.sidecar.istio.io/includeInboundPorts:指定需要劫持的入站端口列表,默认劫持所有端口。
  • traffic.sidecar.istio.io/excludeInboundPorts:排除不需要劫持的入站端口。
  • traffic.sidecar.istio.io/includeOutboundIPRanges:指定需要劫持的出站 IP 范围,默认劫持所有出站流量。
  • sidecar.istio.io/inject:设置为 "true" 或 "false" 控制是否注入 Sidecar。

验证劫持是否生效:

# 进入 Pod 查看 iptables 规则
kubectl exec -it <pod-name> -c istio-proxy -- iptables -t nat -L -n -v

# 预期输出应包含类似以下规则
# Chain PREROUTING (policy ACCEPT)
# ISTIO_INBOUND  tcp  --  anywhere  anywhere  tcp dpt:8080
# Chain OUTPUT (policy ACCEPT)
# ISTIO_OUTPUT   tcp  --  anywhere  anywhere
安全基线提示: 在配置 OPA 策略时,应确保 Sidecar 注入和流量劫持的配置符合安全基线。例如,禁止通过注解排除关键端口(如 22、6443)的劫持,防止绕过安全策略。同时,建议启用 STRICT 模式的 mTLS,确保所有网格内流量都经过加密和身份验证。