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-init 以 NET_ADMIN 权限运行,调用 iptables 在 Pod 的网络命名空间内写入规则:
1 2 3 4 5 6 7 8 9
| iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-port 15001
iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-port 15006
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 route: - destination: host: reviews subset: v2 - route: - destination: host: reviews subset: v1 weight: 90 - destination: host: reviews subset: v3 weight: 10
|
上面的配置实现了两件事:
- Header
end-user: jason 的请求路由到 v2(灰度用户)
- 其余请求按 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
|
DestinationRule 中的 subsets 通过 Pod label 选择器来区分同一服务的不同版本。Pilot 会把每个 subset 对应的 Pod IP 列表单独维护为一个 EDS cluster。
5.3 Gateway
Gateway 是 Istio 中专门管理南北向流量(进出 Mesh 的流量)的 CRD。它运行在网格边缘的专用 Envoy 进程上(istio-ingressgateway 或 istio-egressgateway Pod),而非 Sidecar,负责处理集群外部与内部服务之间的通信。
Gateway CRD 本身只定义监听规则(端口、协议、TLS),必须配合 VirtualService 才能完成路由,这是它与 Kubernetes Ingress 的核心区别之一。
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
|
六、Istio Gateway 深度解析:Ingress 与 Egress
Istio 的 Gateway 分为两类,承担截然不同的职责:
| 类型 |
方向 |
默认 Pod |
典型场景 |
| Ingress Gateway |
外部 → 集群内 |
istio-ingressgateway |
接收外部 HTTP/HTTPS 请求,TLS 终结,路由到内部服务 |
| Egress Gateway |
集群内 → 外部 |
istio-egressgateway |
集中管控出站流量,审计、策略执行、企业代理 |
6.1 Ingress Gateway:外部流量入口
架构图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 外部用户 │ HTTPS 443 ▼ ┌─────────────────────────────────────┐ │ LoadBalancer / NodePort Service │ ← Kubernetes Service(类型 LoadBalancer) └─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ istio-ingressgateway Pod │ │ (独立 Envoy 进程,非 Sidecar) │ │ │ │ Gateway CRD → 配置监听端口 + TLS │ │ VirtualService → 配置路由规则 │ └─────────────────────────────────────┘ │ 根据 Host / Path 路由 ├──────────────────► Service A (app Sidecar) └──────────────────► Service B (app Sidecar)
|
Gateway + VirtualService 协作机制
Gateway 和 VirtualService 通过 gateways 字段绑定,形成完整的入站路由链:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bookinfo-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "bookinfo.example.com" - port: number: 443 name: https protocol: HTTPS tls: mode: SIMPLE credentialName: bookinfo-cert hosts: - "bookinfo.example.com" ---
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: bookinfo spec: hosts: - "bookinfo.example.com" gateways: - bookinfo-gateway - mesh http: - match: - uri: prefix: /productpage - uri: prefix: /api/v1 route: - destination: host: productpage port: number: 9080 - match: - uri: prefix: /reviews route: - destination: host: reviews subset: v2
|
关键点:VirtualService 的 gateways 字段控制这条路由规则对谁生效:
gateways: [bookinfo-gateway]:只对从 Ingress Gateway 进来的流量生效
gateways: [mesh]:只对 Mesh 内部 Sidecar 间的流量生效
- 两者同时列出:外部和内部均生效
TLS 模式详解
Ingress Gateway 支持三种 TLS 处理模式:
| TLS 模式 |
说明 |
典型场景 |
SIMPLE |
Gateway 终结 TLS,内部用明文或 mTLS |
最常见,外部 HTTPS → 内部 HTTP |
PASSTHROUGH |
Gateway 不解密,直接透传 TCP 到后端 |
后端自己处理 TLS,Gateway 看不到明文 |
MUTUAL |
双向 TLS,要求客户端提供证书 |
B2B API,高安全要求场景 |
1 2 3 4 5 6 7 8 9 10
| servers: - port: number: 443 name: https-passthrough protocol: TLS tls: mode: PASSTHROUGH hosts: - "*.example.com"
|
Ingress Gateway 的典型使用场景
场景一:多域名路由(Host-based Routing)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| spec: hosts: - "api.example.com" - "web.example.com" ---
spec: hosts: ["api.example.com"] gateways: [shared-gateway] http: - route: - destination: host: api-service
---
spec: hosts: ["web.example.com"] gateways: [shared-gateway] http: - route: - destination: host: frontend-service
|
场景二:HTTP 跳转 HTTPS
1 2 3 4 5 6 7 8 9 10
| spec: hosts: ["bookinfo.example.com"] gateways: [bookinfo-gateway] http: - match: - port: 80 redirect: uri: / scheme: https redirectCode: 301
|
场景三:金丝雀发布(结合外部流量)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| http: - match: - headers: x-canary: exact: "true" route: - destination: host: frontend subset: v2 - route: - destination: host: frontend subset: v1 weight: 95 - destination: host: frontend subset: v2 weight: 5
|
6.2 Egress Gateway:集中管控出站流量
默认情况下,Istio 允许 Pod 直接访问集群外部服务(受 outboundTrafficPolicy 控制)。Egress Gateway 在出站路径上引入一个中间层,把所有出站流量集中到一个或多个专用 Envoy Pod,从而实现统一的审计、策略和访问控制。
架构图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Pod(App + Sidecar) │ 出站请求到 api.external.com:443 │ │ iptables 劫持 → Sidecar Envoy │ │ Sidecar 查路由表:目标匹配 ServiceEntry + VirtualService │ → 发现应通过 egressgateway 转发 ▼ ┌─────────────────────────────────────┐ │ istio-egressgateway Pod │ │ (独立 Envoy,集中出站点) │ │ │ │ 1. 接收来自各 Sidecar 的出站流量 │ │ 2. 应用出站策略(允许/拒绝/重写) │ │ 3. 实际发起到外部服务的连接 │ └─────────────────────────────────────┘ │ 实际 HTTPS 请求 ▼ 外部服务(api.external.com)
|
对比无 Egress Gateway 的直接出站:
1 2 3 4 5
| # 无 Egress Gateway Pod Sidecar → 直接连接 api.external.com ← 难以集中审计/策略
# 有 Egress Gateway Pod Sidecar → egressgateway → api.external.com ← 所有出站经过统一控制点
|
配置 Egress Gateway 的完整示例
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-api spec: hosts: - api.external.com ports: - number: 443 name: https protocol: HTTPS resolution: DNS location: MESH_EXTERNAL ---
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-system spec: selector: istio: egressgateway servers: - port: number: 443 name: tls protocol: TLS tls: mode: PASSTHROUGH hosts: - api.external.com ---
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: direct-external-via-egress spec: hosts: - api.external.com gateways: - mesh - egress-gateway tls: - match: - gateways: - mesh port: 443 sniHosts: - api.external.com route: - destination: host: istio-egressgateway.istio-system.svc.cluster.local port: number: 443 - match: - gateways: - egress-gateway port: 443 sniHosts: - api.external.com route: - destination: host: api.external.com port: number: 443
|
Egress Gateway 的典型使用场景
场景一:强制所有出站流量经过审计点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: allow-egress-only namespace: istio-system spec: selector: matchLabels: app: istio-egressgateway rules: - from: - source: principals: - "cluster.local/ns/default/sa/allowed-service-account"
|
场景二:企业网络合规(所有出站经企业代理)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: egress-tls-origination spec: host: api.external.com trafficPolicy: portLevelSettings: - port: number: 443 tls: mode: SIMPLE caCertificates: /etc/ssl/certs/corporate-ca.pem
|
场景三:限制只允许特定外部域名
1 2 3 4 5 6 7
|
apiVersion: istio.io/v1alpha1 kind: MeshConfig spec: outboundTrafficPolicy: mode: REGISTRY_ONLY
|
6.3 Ingress Gateway vs Egress Gateway 对比
| 维度 |
Ingress Gateway |
Egress Gateway |
| 流量方向 |
外部 → 集群内(南→北) |
集群内 → 外部(北→南) |
| 主要职责 |
TLS 终结、外部路由入口 |
出站集中审计、访问控制 |
| 是否必须 |
通常必须(暴露服务) |
可选(高安全要求才用) |
| 配套资源 |
Gateway + VirtualService |
ServiceEntry + Gateway + VirtualService |
| TLS 处理 |
通常终结 TLS(SIMPLE 模式) |
通常透传(PASSTHROUGH)或 TLS 发起 |
| 典型用户 |
所有 Istio 集群 |
金融、医疗等合规场景 |
6.4 Gateway vs Kubernetes Ingress
Istio Gateway 和原生 Kubernetes Ingress 都能处理入站 HTTP 流量,但设计理念不同:
| 维度 |
Kubernetes Ingress |
Istio Gateway |
| 路由规则载体 |
Ingress 资源本身 |
分离为 Gateway + VirtualService |
| 流量协议 |
HTTP/HTTPS |
HTTP/HTTPS/TCP/TLS/gRPC 等 |
| 高级路由 |
有限(依赖注解) |
原生支持 Header/Weight/Mirror |
| 与 Mesh 集成 |
无(独立于 Mesh) |
完全集成(可触发 mTLS、策略) |
| 可观测性 |
依赖控制器实现 |
与 Sidecar 同等的指标、追踪 |
| 复杂度 |
低 |
较高(需理解 Gateway/VS 分离) |
实践建议:在已经部署 Istio 的集群中,优先使用 Istio Gateway 替代 Kubernetes Ingress,这样可以充分利用流量镜像、精细路由、mTLS 端到端等特性,同时统一可观测性视角。
七、流量切分的完整链路
以金丝雀发布为例,把 10% 流量切到新版本:
第一步:部署新版本,保留旧版本
关键点:两个 Deployment 共用同一个 Kubernetes Service(selector: 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 请求时:
- 匹配 Listener(目标地址
reviews:9080)
- 进入 Route 配置,找到
reviews 对应的虚拟主机
- 执行权重随机:生成 [0,100) 随机数,< 90 选 v1 cluster,≥ 90 选 v3 cluster
- 从选中 cluster 的 EDS 列表中按负载均衡策略(默认 Round Robin)选取一个 Endpoint
- 建立连接并转发请求
这样无论 v1/v3 各有多少 Pod,流量比例始终精确维持在 90/10。
八、mTLS:Sidecar 间的安全通信
Istio 的 mTLS 由 Citadel(istiod 内部)负责:
- 证书颁发:istiod 作为 CA,为每个服务账户签发 SPIFFE 格式的 X.509 证书
- 证书注入:通过 SDS 将证书和私钥推送给 Sidecar,无需挂载 Secret
- 自动 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 在处理每个请求时自动生成三类数据:
9.1 Metrics
Envoy 暴露 Prometheus 格式的指标,包括:
istio_requests_total:请求总数(带 source/destination/response_code 标签)
istio_request_duration_milliseconds:延迟分布
istio_request_bytes / istio_response_bytes:流量大小
9.2 分布式追踪
Envoy 自动在请求头中注入/传播 Trace Context(B3 或 W3C TraceContext 格式),上报给 Jaeger/Zipkin/Tempo。应用只需透传这些 Header,无需集成追踪 SDK。
9.3 访问日志
每个 Sidecar 可配置结构化访问日志,记录请求的完整元数据(源服务、目标服务、响应码、延迟、Trace ID 等)。
十、关键设计决策总结
| 问题 |
Istio 的解法 |
| 如何透明接管流量 |
iptables REDIRECT + Envoy Sidecar |
| 如何动态下发配置 |
xDS gRPC 长连接(ADS) |
| 如何精确切流量 |
WeightedCluster + subset EDS 隔离 |
| 如何处理外部入站流量 |
Ingress Gateway + VirtualService(TLS 终结、Host/Path 路由) |
| 如何集中管控出站流量 |
Egress Gateway + ServiceEntry(审计、合规、访问白名单) |
| 如何实现 mTLS |
Citadel CA + SDS 证书推送 |
| 如何采集指标 |
Envoy 内建 stats,无需代码改动 |
| 如何支持外部服务 |
ServiceEntry 注册到 Mesh |
Istio 的核心价值在于把分布式系统的通信复杂性从应用层移到了基础设施层。代价是引入了额外的延迟(通常 1-5ms per hop)和运维复杂度。在大规模微服务场景下,这个 trade-off 通常是值得的。
参考资料