📦 Istio 1.18
🏆 Istio基础
Istio
服务网格在逻辑上分为数据平面和控制平面
数据平面由一组部署为 sidecar
的智能代理(Envoy
)组成,这些代理与 Mixer
通用策略和遥测中心协调并控制微服务之间的所有网络通信 控制平面管理并配置从代理到路由的流量。此外,控制平面配置 Mixer
以执行策略和收集遥测数据
- 控制平面采用您想要的配置及其服务视图,并动态地对代理服务器进行编程,并根据规则或环境的变化对其进行更新。
- 数据平面是服务之间的通信。如果没有服务网格,网络就无法理解发送的流量,也无法根据流量的类型或来源或目的地做出任何决策。
⭐️ Istio
是一 Sidercar
容器的方式,在每一个被治理的应用 pod
中运行这个代理服务,这个代理服务就可以通过配置Pod里面的 Iptables
来接管整个 Pod
的进出流量,这样 Istio
的控制层就可以通过调用代理容器的 API
来对代理进行配置,从而实现微服务治理
🌟 Istio组件
老架构图:
下面是最新的架构图 Pilot、Mixe、Citadel
都被集成在了 istiod
上:
Envoy:
Istio
使用 Envoy 代理的扩展版本。Envoy
是用 C++
开发的高性能代理,用于协调服务网格中所有服务的入站和出站流量。Envoy
代理是唯一与数据平面流量交互的 Istio
组件。
Envoy
代理被部署为服务的 Sidecar
,在逻辑上为服务增加了 Envoy
的许多内置特性,例如:
- 动态服务发现
- 负载均衡
TLS
终止HTTP/2
与gRPC
代理- 熔断器
- 健康检查
- 基于百分比流量分割的分阶段发布
- 故障注入
- 丰富的指标
这种 Sidecar
部署允许 Istio
可以执行策略决策,并提取丰富的遥测数据, 接着将这些数据发送到监视系统以提供有关整个网格行为的信息。
Sidecar
代理模型还允许您向现有的部署添加 Istio
功能,而不需要重新设计架构或重写代码。
由 Envoy
代理启用的一些 Istio
的功能和任务包括:
- 流量控制功能:通过丰富的
HTTP
、gRPC
、WebSocket
和TCP
流量路由规则来执行细粒度的流量控制。 - 网络弹性特性:重试设置、故障转移、熔断器和故障注入。
- 安全性和身份认证特性:执行安全性策略,并强制实行通过配置
API
定义的访问控制和速率限制。 - 基于
WebAssembly
的可插拔扩展模型,允许通过自定义策略执行和生成网格流量的遥测。
Istiod
Istiod
提供服务发现、配置和证书管理。
Istiod
将控制流量行为的高级路由规则转换为 Envoy
特定的配置, 并在运行时将其传播给 Sidecar
。它提取了特定平台的服务发现机制, 并将其综合为一种所有符合 Envoy API 的 Sidecar
都可以使用的标准格式。
Istio
可以支持发现 Kubernetes
或 VM
等多种环境。
- 您可以使用
Istio
流量管理 API 让Istiod
重新构造Envoy
的配置,以便对服务网格中的流量进行更精细的控制。 Istiod
安全通过内置的身份和凭证管理, 实现了强大的服务对服务和终端用户认证。- 可以使用
Istio
来升级服务网格中未加密的流量。 使用Istio
,运营商可以基于服务身份而不是相对不稳定的第3 层或第 4 层
网络标识符来执行策略。 - 可以使用 Istio 的鉴权功能控制谁可以访问您的服务。
Istiod
充当证书颁发机构(CA
)并生成证书,以允许在数据平面中进行安全的 mTLS
通信。
🌟 Istio流量管理概念
🏢 https://istio.io/v1.18/zh/docs/concepts/traffic-management/#gateways
1️⃣ 虚拟服务
虚拟服务让您配置如何在服务网格内将请求路由传递至需要访问的服务,它提供基本的连通性和服务发现能力,每一个虚拟服务包含一组
路由规则,使用路由规则来进行匹配
Istio
的 VirtualService
和 K8s
的 Service
,相比较它多了熔断,流量分割、重试、超时等,它不仅仅只是负载均衡,它可以精确匹配至某一条路由
虚拟服务可以为一个或多个主机名指定流量行为。在虚拟服务中使用路由规则, 告诉
Envoy
如何发送虚拟服务的流量到适当的目标。路由目标地址可以是同一服务的不同版本, 也可以是完全不同的服务
一个典型的用例是将流量发送到被指定为服务子集的服务的不同版本。 客户端将虚拟服务视为一个单一实体,将请求发送至虚拟服务主机, 然后 Envoy 根据虚拟服务规则把流量路由到不同的版本。例如, “20% 的调用转发到新版本”或“将这些用户的调用转发到版本 2”。 这允许您创建一个金丝雀发布,逐步增加发送到新版本服务的流量百分比。 流量路由完全独立于实例部署,这意味着实现新版本服务的实例可以根据流量的负载来伸缩, 完全不影响流量路由。相比之下,像 Kubernetes 这样的容器编排平台只支持基于实例缩放的流量分发, 这会让情况变得复杂。您可以在
使用 Istio 进行金丝雀部署的文章里阅读到更多用虚拟服务实现金丝雀部署的内容
通过单个虚拟服务处理多个应用程序服务。如果是在 k8s
中能使用 istio
, 可以配置一个虚拟服务处理特定命名空间中的所有服务,可以在不需要适应转换的情况下,将单体应用转换为微服务构建的复合应用系统。 路由规则可以指定为“对 monolith.com
的 URI 调用转发到 microservice A
、microservice B
” 等等
虚拟服务还支持HTTP重定向、重写机制、重试、流量镜像、故障注入、跨域的解决等问题
虚拟服务配置大全https://istio.io/v1.18/zh/docs/reference/config/networking/virtual-service/
2️⃣ 目标规则
与
虚拟服务一样, 目标规则也是 Istio
流量路由功能的关键部分。可以将虚拟服务视为将流量如何路由到给定目标地址,然后使用目标规则来配置该目标的流量。在评估虚拟服务路由规则之后,目标规则将应用于流量的“真实”目标地址。
也就是一条一条规则。你可以对某些服务进行分组,可以按照版本分组,然后可以在虚拟服务的路由规则中使用这些服务子集来控制到服务不同实例的流量。
在比如存在一个视频网站服务Service管理下面有多个
pod
起来的服务,这些服务里面有 v1\v2\v3
的版本,那么就可以使用 DestinationRule
给他们按照版本分组
目标规则还支持服务熔断、调整负载均衡策略、TLS认证等功能
目标规则配置大全: https://istio.io/v1.18/zh/docs/reference/config/networking/destination-rule/
3️⃣ 网关
网关是用来管理入站和出站流量的,可以指定进入/离开的网格流量,网关配置被用于运行在网格边缘的独立
Envoy
代理
它和
ingress
这种七层代理不同,在配置网关时,你不需要在同一个 Gateway
资源中同时配置7层(应用层)的流量路由规则,Istio
允许你将4-6层(TCP/UDP
)的负载均衡规则和7层的应用层流量路由规则分开配置。你可以在 Gateway
资源中定义监听端口、TLS
设置等4-6层的规则,然后通过绑定 Istio
的 VirtualService
资源来管理7层的流量路由。这样做的好处是,你可以更灵活地管理流量,并且可以像管理网格中其他数据平面的流量一样去管理网关流量
例如,你可以在
Gateway
资源中定义一个监听80
端口的HTTP
流量的入口,然后在一个单独的VirtualService
资源中定义如何将这些流量路由到网格内的服务。这样,Gateway
资源专注于处理底层的网络流量转发,而VirtualService
资源则负责更高级的流量路由和策略管理
网关主要用于管理进入的流量,也可以配置出口网关。出口网关让您为离开网格的流量配置一个专用的出口节点, 这可以限制哪些服务可以或应该访问外部网络,或者启用
出口流量安全控制增强网格安全性。也可以使用网关配置一个纯粹的内部代理。
详细配置大全: https://istio.io/v1.18/zh/docs/reference/config/networking/
4️⃣ 服务入口
ServiceEntry
允许将额外的条目添加到 Istio
的内部服务注册表中,以便网格中自动发现的服务可以访问/路由到这些手动指定的服务。服务条目描述服务的属性(DNS 名称、VIP、端口、协议、终端节点)。这些服务可以是网格外部的(例如,Web API),也可以是不属于平台服务注册表的网格内部服务(例如,一组与 Kubernetes
中的服务通信的 VM
)。此外,还可以使用 workloadSelector
字段动态选择服务条目的终端节点。这些终端节点可以是使用 WorkloadEntry
对象或 Kubernetes
Pod 声明的 VM
工作负载。在单个服务下同时选择 Pod
和 VM
的功能允许将服务从 VM
迁移到 Kubernetes
,而无需更改与服务关联的现有 DNS
名称
🍹 额外的知识点: Istio
是如何将边车容器注入 pod
内的呢?
https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/
istio
通过使用 Admission Controller
来将容器无感的注入到 pod
内的;Admission
是执行在 API
被提交到 kube-Api-Server
之前需要执行的"初始化"工作,比如自动给某些 Pod
加上标签等等
但是如果是要使用
Admission Controller
是有点麻烦的,它是可选择性的编译至 Api-Server
中的,如果需要使用它,就要重新编译并且重启 api-server
,这样就很麻烦
但是
K8S
还提供了另外一种机制那就是 Dynamic Admission Controller
,也被称为 Initlizer
但是在1.16之后被 admission webhooK
取代但是工作原理和 istio
注入机制依然相同,Istio
使用的是,MutatingWebhookConfiguration
的方法
https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/extend-resources/mutating-webhook-configuration-v1/
https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/
- 首先
istio
会将envoy
这个代理容器本身的资源清单存储到configmap
中 istio
将一个编写好的Initalizer
作为一个pod
部署在k8s
中,也就是operator
,它不获取需要注入的容器状态,如果这个pod已经被注入的代理,就放过这个pod,如果没有注入,则进行initalizer
操作
通常是在
metadata
上有一个initailizer.pending
的信息来判断
- 进入
initalizer
操作,它会先从Api Server
中获取这个存储envoy
配置的ConfigMap
,将它添加到一个空的pod
对象里面,然后通过TwoWayMergePatch
将两个pod
结合生成一个patch
数据、 - 通过
patch
数据向Kubernetes Client
发起Patch
请求,这样就完成了容器注入