Istio 架构深度解析:原理与流量管理

Istio 是目前最成熟的 Service Mesh 实现之一。它以透明代理的方式接管微服务间的所有通信,为应用提供流量管理、可观测性和安全策略,而无需修改业务代码。本文从整体架构出发,逐层分析各组件的工作原理,并重点讲解 Istio 是如何完成流量切分与路由的。

一、为什么需要 Service Mesh

在微服务架构中,服务间通信带来了一系列横切关注点(cross-cutting concerns):

  • 重试与超时:每个服务都要自行处理网络抖动
  • 负载均衡:客户端需要感知后端实例列表
  • 熔断:防止级联故障扩散
  • 可观测性:分布式追踪、指标、日志散落各处
  • 安全:mTLS、服务间授权需要统一策略

传统做法是把这些能力做进 SDK(如 Netflix OSS),但这带来了语言绑定和版本升级难题。Service Mesh 的思路是把这些能力下沉到基础设施层——用 Sidecar 代理接管所有流量,让业务代码只关注业务逻辑。


二、Istio 整体架构

Istio 1.5 之后完成了控制平面的整合,核心组件从此前的 Pilot / Mixer / Citadel / Galley 四件套收敛为单一进程 istiod

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
┌─────────────────────────────────────────────────────────┐
│ Control Plane │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ istiod │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ Pilot │ │ Citadel │ │ Galley │ │ │
│ │ │(xDS API) │ │ (CA) │ │(Config Val.) │ │ │
│ │ └──────────┘ └──────────┘ └──────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│ xDS (gRPC long-polling)

┌─────────────────────────────────────────────────────────┐
│ Data Plane │
│ │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ Pod A │ │ Pod B │ │
│ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ App Container│ │ │ │ App Container│ │ │
│ │ └──────┬───────┘ │ │ └──────┬───────┘ │ │
│ │ │ localhost│ │ │ localhost │ │
│ │ ┌──────▼───────┐ │ │ ┌──────▼───────┐ │ │
│ │ │ Envoy Proxy │◄─┼────┼──► Envoy Proxy │ │ │
│ │ │ (Sidecar) │ │ │ │ (Sidecar) │ │ │
│ │ └──────────────┘ │ │ └──────────────┘ │ │
│ └────────────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────┘

2.1 控制平面:istiod

istiod 是控制平面的大脑,负责三件事:

子模块 职责
Pilot 服务发现、配置下发(xDS API)
Citadel 证书颁发与轮转(mTLS)
Galley 配置校验与转换

Pilot 是流量管理的核心。它监听 Kubernetes API Server 上的 Service、Endpoint 以及 Istio 自定义资源(VirtualService、DestinationRule 等),将其转换为 Envoy 能理解的 xDS 配置,通过 gRPC 长连接推送给每个 Sidecar。

2.2 数据平面:Envoy Sidecar

每个工作负载 Pod 中都注入了一个 Envoy 代理容器。Envoy 是一个高性能的 L4/L7 代理,原生支持 xDS 协议,是数据平面的执行者。

Sidecar 的注入由 MutatingAdmissionWebhook 完成:Pod 创建请求到达 API Server 时,istiod 的 Webhook 自动向 Pod spec 中注入 istio-proxy 容器和 istio-init 初始化容器。


三、流量劫持:iptables 是怎么工作的

Sidecar 注入后,Pod 内的流量如何被 Envoy 接管?答案是 iptables 规则,由 istio-init 初始化容器在 Pod 启动时写入。

3.1 istio-init 初始化容器

istio-initNET_ADMIN 权限运行,调用 iptables 在 Pod 的网络命名空间内写入规则:

1
2
3
4
5
6
7
8
9
# 出站流量重定向到 Envoy 的 15001 端口
iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-port 15001

# 入站流量重定向到 Envoy 的 15006 端口
iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-port 15006

# Envoy 进程自身发出的流量不做重定向(避免死循环)
# Envoy 以 UID 1337 运行
iptables -t nat -A OUTPUT -m owner --uid-owner 1337 -j RETURN

3.2 完整的出站流量路径

以 Service A 调用 Service B(http://service-b:8080/api)为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
App A (发出 TCP 连接到 service-b:8080)

│ iptables OUTPUT REDIRECT

Envoy (监听 0.0.0.0:15001,Outbound 方向)

│ 1. 读取原始目标地址(SO_ORIGINAL_DST)
│ 2. 匹配 Listener → 匹配 Route → 选 Cluster
│ 3. 从 Cluster EDS 选取 Endpoint

Envoy (建立 TCP 连接到 Pod B 的实际 IP:Port)

│ iptables PREROUTING REDIRECT(进入 Pod B)

Pod B 的 Envoy (监听 0.0.0.0:15006,Inbound 方向)

│ 解析 HTTP/gRPC 请求,应用入站策略

App B (127.0.0.1:8080)

整个过程对应用完全透明——App A 以为自己直接连到了 service-b,实际上中间经过了两个 Envoy 的处理。


四、xDS 协议:控制平面如何下发配置

xDS(x Discovery Service)是 Envoy 的配置下发协议族,Pilot 通过它把路由、集群、端点等配置推送给所有 Sidecar。

4.1 xDS 的五个核心 API

API 全称 作用
LDS Listener Discovery Service 定义 Envoy 监听哪些端口、用哪个过滤器链
RDS Route Discovery Service HTTP/gRPC 路由规则(路径匹配、Header 匹配等)
CDS Cluster Discovery Service 定义后端服务集群(对应 Kubernetes Service)
EDS Endpoint Discovery Service 集群的实际 Endpoint 列表(Pod IP:Port)
SDS Secret Discovery Service 证书和私钥(用于 mTLS)

4.2 配置下发流程

1
2
3
4
5
6
7
8
9
10
11
Kubernetes API Server
│ Watch Service/Endpoint/VirtualService/DestinationRule

istiod (Pilot)
│ 转换为 xDS 对象
│ gRPC 双向流(ADS - Aggregated Discovery Service)

Envoy Sidecar
│ 动态更新 Listener / Route / Cluster / Endpoint

数据平面立即生效(无需重启)

Pilot 使用 ADS(聚合发现服务)将所有 xDS 合并到单一 gRPC 流,保证配置更新的顺序性,避免 Cluster 还未创建时 Route 就引用它导致的 404。


五、流量管理核心资源

Istio 通过四个 CRD 实现精细化流量控制。

5.1 VirtualService

VirtualService 定义”流量如何路由”,相当于 Envoy 的 Route 配置。

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
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews # 目标服务
http:
- match:
- headers:
end-user:
exact: jason # Header 匹配
route:
- destination:
host: reviews
subset: v2 # 路由到 v2
- route: # 默认路由
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v3
weight: 10

上面的配置实现了两件事:

  1. Header end-user: jason 的请求路由到 v2(灰度用户)
  2. 其余请求按 90/10 分流到 v1 和 v3(金丝雀发布)

5.2 DestinationRule

DestinationRule 定义”到达目标后怎么处理”,包括负载均衡策略、连接池、熔断,以及 subset(版本)的定义。

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
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 100
http2MaxRequests: 1000
outlierDetection: # 熔断配置
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
trafficPolicy:
loadBalancer:
simple: LEAST_CONN # v3 使用最少连接策略

DestinationRule 中的 subsets 通过 Pod label 选择器来区分同一服务的不同版本。Pilot 会把每个 subset 对应的 Pod IP 列表单独维护为一个 EDS cluster。

5.3 Gateway

Gateway 控制进出 Mesh 的流量(南北向流量),通常与 Ingress/Egress Gateway 配合使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: bookinfo-cert
hosts:
- "bookinfo.example.com"

5.4 ServiceEntry

ServiceEntry 将外部服务(集群外)注册到 Istio 的服务注册表,使 Sidecar 可以像处理内部服务一样处理外部服务的流量策略。

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc
spec:
hosts:
- api.external.com
ports:
- number: 443
name: https
protocol: HTTPS
resolution: DNS
location: MESH_EXTERNAL

六、流量切分的完整链路

以金丝雀发布为例,把 10% 流量切到新版本:

第一步:部署新版本,保留旧版本

1
2
# reviews-v1 Deployment(保持不变)
# reviews-v3 Deployment(新版本,replica=1)

关键点:两个 Deployment 共用同一个 Kubernetes Serviceselector: app=reviews),Kubernetes 会把流量均分到所有 Pod。

但如果不用 Istio,流量比例完全由 Pod 数量决定——3 个 v1 Pod + 1 个 v3 Pod = 75%/25%,无法精确控制。

第二步:用 DestinationRule 定义 subset

1
2
3
4
5
subsets:
- name: v1
labels: { version: v1 }
- name: v3
labels: { version: v3 }

Pilot 把两个 subset 各自映射为独立的 EDS Cluster:

  • outbound|9080|v1|reviews.default.svc.cluster.local → v1 Pod IPs
  • outbound|9080|v3|reviews.default.svc.cluster.local → v3 Pod IPs

第三步:用 VirtualService 精确切流

1
2
3
4
5
6
7
8
9
10
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v3
weight: 10

Pilot 将此规则转换为 Envoy 的 WeightedCluster 路由配置,下发给所有发起调用的 Sidecar。

第四步:Envoy 执行权重路由

Envoy 在处理每个出站 HTTP 请求时:

  1. 匹配 Listener(目标地址 reviews:9080
  2. 进入 Route 配置,找到 reviews 对应的虚拟主机
  3. 执行权重随机:生成 [0,100) 随机数,< 90 选 v1 cluster,≥ 90 选 v3 cluster
  4. 从选中 cluster 的 EDS 列表中按负载均衡策略(默认 Round Robin)选取一个 Endpoint
  5. 建立连接并转发请求

这样无论 v1/v3 各有多少 Pod,流量比例始终精确维持在 90/10。


七、mTLS:Sidecar 间的安全通信

Istio 的 mTLS 由 Citadel(istiod 内部)负责:

  1. 证书颁发:istiod 作为 CA,为每个服务账户签发 SPIFFE 格式的 X.509 证书
  2. 证书注入:通过 SDS 将证书和私钥推送给 Sidecar,无需挂载 Secret
  3. 自动 TLS:Sidecar 之间默认开启 mTLS(PERMISSIVE 模式下兼容明文,STRICT 模式下强制加密)
1
2
3
4
5
6
7
Pod A Envoy                              Pod B Envoy
│ │
│──── TLS ClientHello ──────────────────►│
│◄─── TLS ServerHello + Certificate ─────│
│──── Certificate (Pod A cert) ──────────►│
│ 双向验证完成 │
│──── 加密的 HTTP/2 请求 ────────────────►│

证书的 SAN(Subject Alternative Name)格式为:

1
spiffe://cluster.local/ns/default/sa/bookinfo-reviews

八、可观测性:Telemetry 数据的生成

Envoy Sidecar 在处理每个请求时自动生成三类数据:

8.1 Metrics

Envoy 暴露 Prometheus 格式的指标,包括:

  • istio_requests_total:请求总数(带 source/destination/response_code 标签)
  • istio_request_duration_milliseconds:延迟分布
  • istio_request_bytes / istio_response_bytes:流量大小

8.2 分布式追踪

Envoy 自动在请求头中注入/传播 Trace Context(B3 或 W3C TraceContext 格式),上报给 Jaeger/Zipkin/Tempo。应用只需透传这些 Header,无需集成追踪 SDK。

8.3 访问日志

每个 Sidecar 可配置结构化访问日志,记录请求的完整元数据(源服务、目标服务、响应码、延迟、Trace ID 等)。


九、关键设计决策总结

问题 Istio 的解法
如何透明接管流量 iptables REDIRECT + Envoy Sidecar
如何动态下发配置 xDS gRPC 长连接(ADS)
如何精确切流量 WeightedCluster + subset EDS 隔离
如何实现 mTLS Citadel CA + SDS 证书推送
如何采集指标 Envoy 内建 stats,无需代码改动
如何支持外部服务 ServiceEntry 注册到 Mesh

Istio 的核心价值在于把分布式系统的通信复杂性从应用层移到了基础设施层。代价是引入了额外的延迟(通常 1-5ms per hop)和运维复杂度。在大规模微服务场景下,这个 trade-off 通常是值得的。


参考资料