深入浅出 Istio 服务网格:从原理到实践
在现代云原生架构中,微服务已成为主流。然而,随着服务数量的激增,服务间的通信、安全、可观测性和流量管理变得异常复杂。Istio 作为一个强大的服务网格,应运而生,它将这类通用能力从应用程序代码中剥离出来,下沉到基础设施层,为微服务提供了统一的治理能力。
1. Istio 的原理:控制面与数据面
Istio 的服务网格在逻辑上分为数据平面和控制平面。
数据平面
数据平面由一组以 Sidecar 方式部署的智能代理组成。在 Istio 中,这个代理就是 Envoy。
- 工作模式:Istio 会将 Envoy 代理注入到每个微服务的 Pod 中。该代理会拦截 Pod 的所有入站和出站网络流量。
- 核心功能:Envoy 代理负责直接控制服务间的所有通信。它执行控制平面下发的策略,包括:
- 流量控制:路由规则、负载均衡、故障恢复(超时、重试、熔断)。
- 网络安全:服务间的双向 TLS 加密和身份认证。
- 可观测性:自动为流量生成详细的指标、日志和分布式追踪数据。
控制平面
控制平面是 Istio 的大脑,它负责管理和配置数据平面中的代理,并收集它们的遥测数据。在较新版本的 Istio 中,控制平面整合为 **istiod
** 一个核心组件。
- **
istiod
的核心作用**:- 服务发现:获取集群中的服务信息。
- 配置管理:将用户通过 Kubernetes API 定义的流量规则(如 VirtualService、DestinationRule)转换为 Envoy 能够理解的配置。
- 证书签发:为数据平面中的服务自动签发和轮转 TLS 证书,以实现安全的 mTLS 通信。
总结:控制平面(istiod
)是管理者,负责制定规则;数据平面(Envoy)是执行者,负责拦截和处理流量,并上报数据。两者分离,使得策略更新和代理管理变得非常灵活。
2. Istio 的安装部署
这边使用helm进行安装,非常方便,可以参考官方文档
https://istio.io/latest/zh/docs/setup/install/helm/
helm repo add istio https://istio-release.storage.googleapis.com/charts
helm repo update# 相关crd安装
helm install istio-base istio/base -n istio-system --set defaultRevision=default --create-namespace# istiod 安装
helm install istiod istio/istiod -n istio-system --wait
注:
安装 Istio 的入站网关,也就是istio gateway:
kubectl create namespace istio-ingress
helm install istio-ingress istio/gateway -n istio-ingress --wait
k -n istio-ingrss get svc就可以查看到创建好的gateway了,可以被后面的gateway运用
3. Istio 几个关键模块说明
要驾驭 Istio 的流量,必须理解以下几个核心的 Kubernetes 自定义资源(CRD):
组件 | 类别 | 核心职责 | 类比 |
---|---|---|---|
Envoy Proxy | 数据平面 | 流量的实际处理者(路由、安全、观测) | 智能交警,在每个路口指挥车辆 |
Istiod (Pilot) | 控制平面 | 将用户意图转换为 Envoy 配置并下发 | 交通总指挥中心,制定交规并通知所有交警 |
Istiod (Citadel) | 控制平面 | 颁发和管理服务身份证书,实现 mTLS | 公安部,负责发放身份证和驾照 |
Ingress/Egress Gateway | 数据平面 | 管理网格的入口和出口流量 | 边境检查站,管理所有进出城市的车辆 |
istioctl & Addons | 运维工具 | 安装、调试、监控和可视化网格状态 | 指挥车和监控大屏,辅助指挥中心进行管理和决策 |
- Istio Ingress网关:
一个实际运行的、由 Envoy 代理组成的 Kubernetes Deployment/Service。
Gateway
和 Ingress Gateway
的关系可以概括为:“蓝图”与“执行者” 或 “接口定义”与“具体实现” 的关系。
概念 | 是什么? | 类比 | 职责 |
---|---|---|---|
Gateway | 一个 Kubernetes API 资源(CRD),是一个声明式配置。 | 就像一份 《大楼入口设计蓝图》。 | 定义规则:“应该在哪个端口(如80)、以哪种协议(如HTTP)、为哪些域名(如app.com )接收流量。” |
Ingress Gateway | 一个实际运行的、由 Envoy 代理组成的 Kubernetes Deployment/Service。 | 就像根据蓝图建造出来的大楼入口和保安团队。 | 执行规则:“我监听80端口,根据收到的流量和配置的规则,决定将请求转发到内部哪个服务。” |
简单来说:
a)你通过编写 Gateway
YAML 文件来描述你想要的入口是什么样的。
b)Istio 控制平面(istiod
)会读取这个 Gateway
配置,并将其应用到实际的 istio-ingressgateway
Pod 上。
c)运行中的 istio-ingressgateway
Pod 就成为了这个入口配置的执行者。
gateway与istio gatway为什么要分离,不写在一起?
如果路由规则(如基于域名的路由)直接写在 istio-ingressgateway
的部署定义里,那么每次修改路由(比如新增一个网站)都需要:
- 修改部署配置。
- 滚动重启
istio-ingressgateway
Pod。 - 这会导致入口服务短暂中断,且难以管理。
分离带来的好处:
a)动态配置:你可以随时创建/修改/删除 Gateway
和 VirtualService
资源,istiod
会几乎实时地(秒级)将新配置下发给 istio-ingressgateway
Pod,无需重启代理,实现了热更新
b)关注点分离:
平台运维人员:负责部署和维护 istio-ingressgateway
这个基础设施组件(例如,确保其有足够的副本和资源)。
应用开发者/运维:只需关心应用层路由,通过创建 Gateway
和 VirtualService
资源来管理自己应用的流量入口,而无需理解底层网关的部署细节。
-
Gateway:网关,用于网格的边界入口
Gateway 描述了一个运行在网格边缘的负载均衡器,用于接收来自外部的 HTTP/TCP 流量。它不直接管理流量路由,而是配置暴露的端口、协议和证书等。你可以把它看作是一个 Kubernetes Ingress 的增强版,但功能更强大、更通用。
注意:这里的selector:是集群内查询所有满足条件的PO,如(2 istio的安装)章节里提到的安装的istio gatway.
istio: ingressgateway的值ingressgateway应该理安装好的svc命对应,
如果svc名为istio-ingressgateway,则这里的selector要配置是ingressgateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: my-gateway
spec:selector:istio: ingressgateway # 使用 Istio 默认的 ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- "*" # 匹配所有主机,生产环境中应指定域名,如 "app.example.com"
-
VirtualService (VS):虚拟服务,定义流量路由规则
VirtualService 是流量路由的核心。它定义了当流量满足特定条件时(如主机头、URI、自定义 Header),应该被发送到哪个或多个目标服务(或子集)。它实现了诸如 A/B 测试、金丝雀发布、按比例分流等高级功能。apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: my-virtualservice spec:hosts:- "myapp.com" # 关联的网关或服务gateways:- my-gateway # 绑定到上面定义的 Gateway,表示这是来自外部的流量http:- match: ... # 匹配条件(可选)route: ... # 路由规则(必选)
-
DestinationRule (DR):目标规则,定义流量策略和子集
DestinationRule 是 VirtualService 路由动作的“目的地”的补充配置。它在 VirtualService 完成路由后生效,主要定义了:apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata:name: my-destinationrule spec:host: my-svc # 对应的 Kubernetes 服务名subsets:- name: v1labels:version: v1 # 选择具有 label version=v1 的 Pod- name: v2labels:version: v2trafficPolicy: ... # 可以定义全局或子集级别的策略
- 子集:将一个服务的后端 Pod 划分为不同的版本(如 v1, v2),这是实现蓝绿、金丝雀发布的基础。
- 流量策略:如负载均衡策略(轮询、最少连接等)、连接池设置、Outlier Detection(异常点检测,即熔断)。
三者关系:Gateway
接收外部流量 -> VirtualService
根据规则将流量路由到 DestinationRule
定义的某个服务子集。
4. Bookinfo 应用的实践
Bookinfo 是 Istio 官方提供的示例应用,由四个微服务组成:productpage
, details
, reviews
(v1, v2, v3三个版本), ratings
。它是演示 Istio 功能的绝佳平台。
Bookinfo 应用可细分为四个独立的微服务:
productpage
:这个微服务会调用details
和reviews
两个微服务,用来填充页面内容。details
:这个微服务中包含了书籍的信息。reviews
:这个微服务中包含了书籍相关的评论。它还会调用ratings
微服务。ratings
:这个微服务中包含了由书籍评论组成的评级信息。
reviews
微服务有 3 个版本:
- v1 版本不会调用
ratings
服务。 - v2 版本会调用
ratings
服务,并使用 1 到 5 个黑色星形图标来显示评分信息。 - v3 版本会调用
ratings
服务,并使用 1 到 5 个红色星形图标来显示评分信息。
下图展示了这个应用的端到端架构。
部署应用:
确保已启用 Sidecar 注入,然后部署 Bookinfo。
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.27/samples/bookinfo/platform/kube/bookinfo.yaml
部署内容下面
应用 productpage
服务,并通过 Istio Ingress Gateway 访问。
场景实践:
-
按版本路由(基础)
目标:将所有流量发送到 reviews
服务的 v1 版本。
配置:创建 VirtualService 和 DestinationRule。
# DestinationRule 定义子集
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: reviews
spec:host: reviewssubsets:- name: v1labels:version: v1- name: v2labels:version: v2- name: v3labels:version: v3
# VirtualService 路由到 v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v1
此时,无论刷新多少次页面,评论区域都不会出现星级评分(v1版本特性)。
同时,将vs版本切成V2,评论区会出现黑色评分
# VirtualService 路由到 v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v2
-
基于权重的金丝雀发布
... http: - route:- destination:host: reviewssubset: v1weight: 90- destination:host: reviewssubset: v3weight: 10
刷新页面,大约有 10% 的几率会看到带黑色星级的评论界面。
- 目标:将 90% 的流量分给 v1,10% 的流量分给 v3(带星级的黑色)。
- 配置:修改上面的
reviews
VirtualService。
-
基于用户标识的 A/B 测试
目标:将来自特定用户(如 Jason)的流量全部导向 reviews:v2
(带红色星级),其他用户则访问 reviews:v1
。
配置:使用 match
字段进行条件匹配。
...
http:
- match:- headers:end-user:exact: jasonroute:- destination:host: reviewssubset: v2
- route: # 默认路由,不匹配上述条件的流量走这里- destination:host: reviewssubset: v1
登录后,以 Jason 用户(密码任意)登录,你将始终看到红色星级的评论。
-
蓝绿发布
- 目标:从 v1(绿色)瞬间切换到 v2(蓝色)。
- 实现:蓝绿发布是金丝雀发布的特例,即权重比例的瞬间切换。
- 配置:只需将权重从
v1:100 / v2:0
修改为v1:0 / v2:100
即可完成发布。如果需要回滚,则反向操作。这比金丝雀发布风险更高,但切换速度极快。
-
故障注入测试
我们创建一个新的 VirtualService,将 100% 流量路由到 reviews v2
,并注入一个 7 秒的延迟。这个延迟是注入在 ratings
服务这一环的。
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: ratings
spec:hosts:- ratingshttp:- fault:delay:percentage:value: 100 # 对100%的流量注入延迟fixedDelay: 7sroute:- destination:host: ratingssubset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v2 # 将流量切换到 reviews v2
EOF
- 刷新 productpage 页面。
- 现象:页面会加载很长时间(约 7 秒),然后才显示出来。并且,因为
reviews v2
在调用ratings
服务时遇到了 7 秒延迟,而productpage
服务有自己的超时设置(默认 3 秒 + 1 次重试),所以最终你会看到页面上的 Book Reviews 部分显示为:“Sorry, product reviews are currently unavailable for this book.”
5.原理说明
三大核心流程
我们可以将 Istio 的流量管控分为三个关键流程:
- 初始化阶段:Sidecar 注入与流量拦截 - 如何将 Envoy 插入到网络路径中。
- 配置阶段:控制平面下发规则 -
istiod
如何将配置告知 Envoy。 - 运行时阶段:数据平面执行规则 - Envoy 如何处理每一个数据包。
流程一:初始化阶段 - Sidecar 注入与流量拦截
这是实现透明拦截的基础。
1. Sidecar 注入
- 自动注入:当您为 Kubernetes 命名空间打上
istio-injection=enabled
标签后,Istio 的 准入控制器 Webhook 会拦截在该命名空间下创建的任何新 Pod 的请求。 - 修改 Pod Spec:Webhook 会动态修改 Pod 的配置清单,向其中添加两个关键容器:
istio-proxy
:这就是 Envoy 代理容器。istio-init
:这是一个初始化容器,它运行在 Pod 中任何应用容器启动之前。
2. 流量拦截(由 istio-init
完成)
这是最巧妙的一步。istio-init
容器以特权模式运行,执行一个关键命令:配置 Pod 的 iptables 规则。
- 原理:它重写了 Pod 的网络规则,使得:
- 所有流入 Pod 的流量(入站/Inbound),都被重定向到 Envoy Sidecar 监听的端口(默认 15006)。
- 所有流出 Pod 的流量(出站/Outbound),也被重定向到 Envoy Sidecar 监听的另一个端口(默认 15001)。
结果:你的应用容器(如 productpage
)认为自己直接访问了 reviews:9080
,但实际上,这个请求被 Linux 内核根据 iptables 规则,无缝地劫持到了同一个 Pod 内的 istio-proxy
容器。Envoy 完全掌控了流量。
流程二:配置阶段 - 控制平面下发规则(xDS API)
这是 istiod
作为“大脑”发挥作用的地方。
1. 用户声明意图
您(作为运维人员)通过 kubectl
应用 Istio 的自定义资源(CRD),例如:
VirtualService
:定义路由规则。DestinationRule
:定义子集和熔断策略。AuthorizationPolicy
:定义安全策略。
2. istiod
的工作
- 监听与聚合:
istiod
中的Pilot
组件持续监听 Kubernetes API Server,获取这些 CRD 的变更,以及标准的 Kubernetes Service 和 Endpoint 的变化。 - 转换与抽象:
Pilot
将这些高级的、平台无关的配置(如“将 90% 流量发给 v1”),转换为 Envoy 能够理解的、低级别的动态配置。这套配置规范就是 xDS。- LDS:监听器发现服务。Envoy 监听哪些端口和协议。
- RDS:路由发现服务。HTTP 路由规则。
- CDS:集群发现服务。Upstream 的集群定义(对应 Kubernetes Service)。
- EDS:端点发现服务。集群中健康实例的地址(对应 Kubernetes Pod IP)。
- 下发配置:
istiod
通过 gRPC 流式长连接 主动将 xDS 配置推送给网格中所有的 Envoy Sidecar。这种长连接保证了配置变更可以近乎实时地(秒级)生效。
流程三:运行时阶段 - 数据平面处理请求
这是 Envoy 作为“手脚”执行任务的阶段。我们跟踪一个请求 productpage -> reviews
的完整生命周期。
-
出站请求
productpage
应用容器发起一个 HTTP 请求到http://reviews:9080/
。- 根据
istio-init
设置的 iptables 规则,这个请求被透明劫持到127.0.0.1:15001
(Envoy 的出站监听器)。 - Envoy 接收到这个请求。
-
匹配路由
- Envoy 查看请求的 Host 头(
reviews:9080
),根据从istiod
下发的 RDS 规则,查找对应的VirtualService
。 VirtualService
告诉 Envoy:“这个请求应该被路由到reviews
服务的v2
子集”。
- Envoy 查看请求的 Host 头(
-
发现目标
- Envoy 查询 CDS/EDS,得知“
reviews
服务的v2
子集”对应哪些具体的 Pod IP 地址列表。
- Envoy 查询 CDS/EDS,得知“
-
负载均衡与弹性检查
- Envoy 根据
DestinationRule
中配置的负载均衡策略(如轮询),选择一个目标 Pod IP。 - 在发送前,检查连接池和熔断器状态。如果目标实例已被熔断,则立即返回 503 错误。
- Envoy 根据
-
安全通信
- 如果全局策略要求 mTLS,Envoy 会自动与目标
reviews
Pod 的 Envoy Sidecar 进行 TLS 握手,加密通信链路。这一切对应用透明。
- 如果全局策略要求 mTLS,Envoy 会自动与目标
-
入站请求
- 请求到达
reviews
Pod,首先被 iptables 规则劫持到127.0.0.1:15006
(Envoy 的入站监听器)。 reviews
的 Envoy Sidecar 验证 TLS 证书、应用AuthorizationPolicy
检查请求是否被授权。- 检查通过后,Envoy 将请求转发给同一 Pod 内的
reviews
应用容器(127.0.0.1:9080
)。
- 请求到达
-
可观测性
- 在整个过程中,出入站的 Envoy 都会生成详细的访问日志、指标数据(发给 Prometheus)和追踪 span(发给 Jaeger/Zipkin)。
-
返回响应
- 响应沿着原路返回。
组件 | 角色 | 关键职责 |
---|---|---|
**istio-init ** | 网格工程师 | 配置 iptables,透明地让流量“绕道”经过 Envoy。 |
**istiod (Pilot)** | 交通总指挥中心 | 监听用户配置,转换为 Envoy 能懂的语言(xDS),并实时下发给所有“路口”的 Envoy。 |
Envoy Sidecar | 每个路口的智能交警 | 接收指挥中心的指令,对经过其路口的每一辆“车”(数据包)进行指挥(路由、检查、记录)。 |
流程精髓:iptables 实现透明拦截,xDS 协议实现动态控制。应用无感知,运维人员通过高级 API 统一管理,Envoy 负责高性能执行。这种解耦架构是 Istio 强大威力的根源。
6.总结
通过本文,我们系统地了解了 Istio 服务网格的架构原理、安装方法、核心资源模型以及如何利用这些模型对真实应用(Bookinfo)进行精细化的流量治理。Istio 通过将网络复杂性抽象化,为运维和开发人员提供了强大、非侵入式的工具,极大地简化了微服务架构的落地难度,是构建现代化、高可用的云原生应用不可或缺的基础设施。