流量治理
Istio的流量路由规则使运维人员可以轻松控制服务之间的流量和API调用
- Istio简化了诸如断路器,超时和重试之类的服务级别属性的配置,并使其易于设置重要任务(A/B测试,canary部署和基于百分比的流量拆分的分段部署)
- 它还提供了开箱即用的故障恢复功能,有助于使应用程序更强大,以防止相关服务或网络的故障
- 使用Istio进行流量管理从本质上是将流量与底层基础架构的伸缩机制相解耦,从而让运维工程师能够通过Pilot指定它们希望流量自身需要遵循那些规则,而非仅仅只能定义由那些特定的pod/vm接收流量,并在这些pod/vm之间以受限于数量比例的方式分配流量;
- Pilot和Envoy proxy负责实现流量规则中定义的流量传输机制
- 例如,可以通过pilot指定到希望特定服务的5%流量到canary版本,而与canary部署的大小无关,或者根据请求的内容将流量发送到特定版本
- Istio的所有路由规则和控制策略都基于kubernetes CRD实现,这包括网络功能相关的VirtualService、DestinationRule、Gateway、ServiceEntry和EnvoyFilter等;
Istio流量治理的关键配置
Istio通过Ingress Gateway为网格引入外部流量;
- Gateway中运行的主程序为Envoy,它同样从控制平面接收配置,并负责完成相关的流量传输;
- 换言之,Gateway资源对象用于将外部访问映射到内部服务,它自身值负责通信子网的相关功能,例如套接字,而七层路由功能则由VirtualService实现;
stio基于ServiceEntry资源对象将外部服务注册到网格内,从而将外部服务以类同内部服务一样的方式进行访问治理;
- 对于外部服务,网格内Sidecar方式运行的Envoy即能执行治理;
- 若需要将外出流量收束于特定几个节点时则需要使用专用的Egress Gateway完成,并基于此Egress Gateway执行相应的流量治理;
VirtualService和DestinationRules
VirtualService和DestinationRules是Istio流量路由功能的核心组件
VirtualService用于将分类流量并将其路由到指定的目的地(Destination),而Destination Rules则用于配置那个指定Destination如何处理流量
VirtualService
用于在Istio及其底层平台(例如kubernetes)的基础上配置如何将请求路由到网格的各Service之上。通常由一组路由规则(routing rules)组成,这些路由规则按顺序进行评估,从而使Istio能够将那些对VirtualService的每个给定请求匹配到网格内特定的目标之上,事实上,其定义的是分发给网格内个Envoy的VirtualService和Route的相关配置
Destination Rules
定义流量在目标内部的各端点之间的分发机制,例如将各端点进行分组,分组内端点间的流量均衡机制,异常探测等;事实上,其定义的是分发给网络内各Envoy的Cluste的相关配置
-VirtualService定义虚拟主机及相关的路由规则,包括路由至哪个目标(集群或子集)
- DestinationRule定义集群或子集内部的流量分发机制
VirtualService和DestinationRule
配置Istio流量治理
流量治理基础
集群外部的入站流量会经由Ingress Gateway到达集群内部
- 需要经由Gateway定义Ingress Gateway上的“虚拟主机”
- 包括目标流量访问的“host”,以及虚拟主机监听的端口等
集群内部的流量仅会在Sidecar之间流动
- VirtualService为Sidecar Envoy定义Listener(主要定义流量路由机制等)
- DestinationRule为Sidecar Envoy定义Cluster(包括发现端点等)
网格流量治理和服务发现
网格内服务发送和接收的所有流量(Data Plan流量——都要经由Envoy代理进行
* 绑定到服务的所有流量都会通过Sidecar Envoy自动进行重新路由
Istio借助于服务注册中心完成服务发现
* Istio自身并不进行服务发现功能,它需要借助于服务注册中心发现所有的Service及相应的各Endpoint
* Istio还假设服务的新实例会自动注册到服务注册表,并且会自动删除不健康的实例
* kubernetes、Mesos等平台能够为基于容器的应用程序提供服务发现功能,另外也存在大量针对基于##VM的应用程序的解决方案
kubernetes系统上,Istio会将网格中的每个Service的端口创建为Listener,而其匹配到的Endpoint将组合成为一个Cluster
- 这些Endpoint和Cluster将配置在网格内的每个sidecar Envoy之上
- 对于某个特定Sidecar Envoy来说,仅其自身所属的Service生成的Listener为Inbound Listener,而所有Service生成Listener都将配置为其上的Outbound Listener
- Inbound Listener:接收其所属Service的部分或全部流量
- Outbound Listener:代理本地应用访问集群内的其它服务
- 进出应用的所有流量都将被Sidecar Envoy拦截并基于重定向的方式进行处理
Istio网格中的默认配置
- 应用程序自身监听的端口相关的入站访问流量,将被网络名称空间中的iptables规则实施拦截后,并统一转发给Envoy Sidecar的15006/TCP端口,该端口也是Envoy上的Listener之一
- 应用程序作为客户端发送的出站访问流量,将被网络名称空间中的iptables规则实施拦截后,并统一转发给Envoy Sidecar的15001/TCP端口,该端口也是Envoy上的Listener之一
- 对于网格应用所属名称空间中的每一个Service对象
- 其用于提供服务的每个端口,都将作为一个Egress Listener配置在网格中的Envoy实例之上,从而确保每个应用可访问到该Service;
- 生成默认路由,将发往该Service生成的Listeners的流量,将被路由至同一Service生成Cluster之上;
- 获取命令
istioctl proxy-config <clusters|listeners|routes|endpoints|bootstrap|log|secret> <pod-name[.namespace]>
Istio 虚拟服务 (Vistrual Service)
虚拟服务(Vistrual Service)是 Istio 重要的资源对象之一,作用是将流量路由到网格中的服务。支持基于权重、http header条件等优先级的路由,比Kuberentes service对于流量的管控更加的丰富,颗粒度更加精细。
有了 Kubernetes Service,为什么还需要 Istio Vistrual Service
简单来说,基于 Kubernetes Service,只可以实现简单的流量负载均衡,如果想实现基于HTTP Header,负载百分比等等复杂的流量控制就无从下手了,Istio Vistrual Service在原本 Kubernetes Service 的功能之上,提供了更加丰富的路由控制。
概念及示例
VirtualService
描述了一个或多个用户可寻址目标到网格内实际工作负载之间的映射 。 虚拟服务让您配置如何在服务网格内将请求路由到服务,这基于 Istio 和平台提供的基本的连通性和服务发现能力。每个虚拟服务包含一组路由规则,Istio 按顺序评估它们,Istio 将每个给定的请求匹配到虚拟服务指定的实际目标地址。您的网格可以有多个虚拟服务,也可以没有,取决于您的使用场景。
虚拟服务在增强 Istio 流量管理的灵活性和有效性方面,发挥着至关重要的作用,通过对客户端请求的目标地址与真实响应请求的目标工作负载进行解耦来实现。虚拟服务同时提供了丰富的方式,为发送至这些工作负载的流量指定不同的路由规则。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
gateways:
- bookinfo-gateway
- mesh
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v3
gateways字段
通过将 VirtualService
绑定到同一 Host 的 Gateway
配置(如前一节所述 ),可向网格外部暴露这些 Host。
gateways:
- bookinfo-gateway
- mesh
网格内部通信存在一个默认的mesh
保留字, mesh
用来指代网格中的所有 Sidecar。当这一字段被省略时,就会使用缺省值(mesh
),也就是针对网格中的所有 Sidecar 生效。如果提供了 gateways
字段,这一规则就只会应用到声明的 Gateway
之中。要让规则同时对 Gateway
和网格内服务生效,需要显式的将 mesh
加入 gateways
列表。
Hosts字段
VirtualService
中 hosts
字段列举虚拟服务的目标主机 ——即用户指定的目标或是路由规则设定的目标。这是客户端向服务发送请求时使用的一个或多个地址 。
hosts:
- bookinfo.com
虚拟服务目的地可以是 IP 地址、DNS 名称,或者依赖于平台的一个简称(例如 Kubernetes 服务的短名称),隐式或显式地指向一个完全限定域名(FQDN)。您也可以使用通配符(“*”)前缀,让您创建一组匹配所有服务的路由规则。虚拟服务的 hosts
字段实际上不必是 Istio 服务注册的一部分,它只是虚拟的目标地址。这让您可以为没有路由到网格内部的虚拟主机建模。
路由规则
在 http
字段包含了虚拟服务的路由规则,用来描述匹配条件和路由行为,它们把 HTTP/1.1、HTTP2 和 gRPC 等流量发送到 hosts 字段指定的目标(您也可以用 tcp
和 tls
片段流量设置路由规则)。一个路由规则包含了指定的请求要流向哪个目标地址,具有 0 或多个匹配条件,取决于您的使用场景。
匹配条件
示例中的第一个路由规则有一个条件,因此以 match
字段开始。在本例中,您希望此路由应用于来自 ”jason“ 用户的所有请求,所以使用 headers
、end-user
和 exact
字段选择适当的请求。
- match:
- headers:
end-user:
exact: jason
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- match:
- headers:
end-user:
exact: jason
uri:
prefix: "/ratings/v2/"
ignoreUriCase: true
route:
- destination:
host: ratings.prod.svc.cluster.local
Destination
route 部分的 destination
字段指定了符合此条件的流量的实际目标地址。与虚拟服务的 hosts
不同,destination 的 host 必须是存在于 Istio 服务注册中心的实际目标地址,否则 Envoy 不知道该将请求发送到哪里。可以是一个有代理的服务网格,或者是一个通过服务入口被添加进来的非网格服务。本示例运行在 Kubernetes 环境中,host 名为一个 Kubernetes 中运行着Service
的名称:
route:
- destination:
host: reviews
subset: v2
请注意,在该示例和本页其它示例中,为了简单,我们使用 Kubernetes Service
的短名称设置 destination 的 host。在评估此规则时,Istio 会添加一个基于虚拟服务命名空间的域后缀,这个虚拟服务包含要获取主机的完全限定名的路由规则。在我们的示例中使用短名称也意味着您可以复制并在任何喜欢的命名空间中尝试它们。
只有在目标主机和虚拟服务位于相同的 Kubernetes 命名空间时才可以使用这样的短名称 , 建议您在生产环境中指定完全限定的主机名。
destination 片段还指定了 Kubernetes 服务的子集,将符合此规则条件的请求转入其中。在本例中子集名称是 v2。您可以在DestinationRule章节中看到如何定义服务子集。
Subset字段
subset
不属于 Istio 创建的 CRD,但是它是一条重要的配置信息,有必要单独说明下。subset
是服务端点的集合,可以用于 A/B 测试或者分版本路由等场景。另外在 subset
中可以覆盖服务级别的即 VirtualService
中的定义的流量策略。
以下是subset
的配置信息。对于 Kubernetes 中的服务,一个 subset
相当于使用 label 的匹配条件选出来的 Service
Field | Type | Description | Required |
---|---|---|---|
name | string | 服务名和 subset 名称可以用于路由规则中的流量拆分 |
Yes |
labels | map | 使用标签对服务注册表中的服务端点进行筛选 | No |
trafficPolicy | TrafficPolicy | 应用到这一 subset 的流量策略。缺省情况下 subset 会继承 DestinationRule 级别的策略,这一字段的定义则会覆盖缺省的继承策略 |
No |
路由规则优先级
路由规则按从上到下的顺序选择,虚拟服务中定义的第一条规则有最高优先级。本示例中,不满足第一个路由规则的流量均流向一个默认的目标,该目标在第二条规则中指定。因此,第二条规则没有 match 条件,直接将流量导向 v3 子集。 我们建议提供一个默认的“无条件”或基于权重的规则作为每一个虚拟服务的最后一条规则,从而确保流经虚拟服务的流量至少能够匹配一条路由规则。
VirtualService配置
Field | Type | Description | Required |
---|---|---|---|
hosts | string[] | 流量的目标主机。可以是带有通配符前缀的 DNS 名称,也可以是 IP 地址。根据所在平台情况,还可能使用短名称来代替 FQDN。这种场景下,短名称到 FQDN 的具体转换过程是要靠下层平台完成的。一个主机名只能在一个 VirtualService 中定义。同一个 VirtualService 中可以用于控制多个 HTTP 和 TCP 端口的流量属性。Kubernetes 用户注意:当使用服务的短名称时(例如使用 reviews ,而不是 reviews.default.svc.cluster.local ),Istio 会根据规则所在的命名空间来处理这一名称,而非服务所在的命名空间。假设 “default” 命名空间的一条规则中包含了一个 reviews 的 host 引用,就会被视为 reviews.default.svc.cluster.local ,而不会考虑 reviews 服务所在的命名空间。为了避免可能的错误配置,建议使用 FQDN 来进行服务引用。 hosts 字段对 HTTP 和 TCP 服务都是有效的。网格中的服务也就是在服务注册表中注册的服务,必须使用他们的注册名进行引用;只有 Gateway 定义的服务才可以使用 IP 地址。 |
Yes |
gateways | string[] |
Gateway 名称列表,Sidecar 会据此使用路由。VirtualService 对象可以用于网格中的 Sidecar,也可以用于一个或多个 Gateway 。这里公开的选择条件可以在协议相关的路由过滤条件中进行覆盖。保留字 mesh 用来指代网格中的所有 Sidecar。当这一字段被省略时,就会使用缺省值(mesh ),也就是针对网格中的所有 Sidecar 生效。如果提供了 gateways 字段,这一规则就只会应用到声明的 Gateway 之中。要让规则同时对 Gateway 和网格内服务生效,需要显式的将 mesh 加入 gateways 列表。 |
No |
http | HTTPRoute[] | HTTP 流量规则的有序列表。这个列表对名称前缀为 http- 、http2- 、grpc- 的服务端口,或者协议为 HTTP 、HTTP2 、GRPC 以及终结的 TLS,另外还有使用 HTTP 、HTTP2 以及 GRPC 协议的 ServiceEntry 都是有效的。进入流量会使用匹配到的第一条规则。 |
No |
tls | TLSRoute[] | 一个有序列表,对应的是透传 TLS 和 HTTPS 流量。路由过程通常利用 ClientHello 消息中的 SNI 来完成。TLS 路由通常应用在 https- 、tls- 前缀的平台服务端口,或者经 Gateway 透传的 HTTPS、TLS 协议端口,以及使用 HTTPS 或者 TLS 协议的 ServiceEntry 端口上。注意:没有关联 VirtualService 的 https- 或者 tls- 端口流量会被视为透传 TCP 流量。
|
No |
tcp | TCPRoute[] | 一个针对透传 TCP 流量的有序路由列表。TCP 路由对所有 HTTP 和 TLS 之外的端口生效。进入流量会使用匹配到的第一条规则。 | No |
exportTo | string[] | 当前vritual service要导出的 namespace 列表。 应用于 vritual service 的解析发生在 namespace 层次结构的上下文中。 vritual service 的导出允许将其包含在其他 namespace 中的服务的解析层次结构中。 此功能为服务所有者和网格管理员提供了一种机制,用于控制跨 namespace 边界的 vritual service 的可见性 |
如果未指定任何 namespace,则默认情况下将 vritual service rule 导出到所有 namespace
值.
被保留,用于定义导出到 vritual service 被声明所在的相同 namespace 。类似的值*
保留,用于定义导出到所有 namespaces
NOTE:在当前版本中,exportTo值被限制为.
或*
(即, 当前namespace或所有namespace) | |
HTTPRoute配置
Field | Type | Description | Required |
---|---|---|---|
name | string | 为route分配给路由的名称 | No |
match | HTTPMatchRequest[] | 匹配要激活的规则要满足的条件。单个匹配块内的所有条件都具有AND语义,而匹配块列表具有OR语义。如果任何一个匹配块成功,则匹配该规则。 | No |
route | HTTPRouteDestination[] | http规则可以重定向或转发(默认)流量 | No |
redirect | HTTPRedirect | http规则可以重定向或转发(默认)流量. 如果在规则中指定了流量通过选项,则将忽略路由/重定向。重定向原语可用于将HTTP 301重定向发送到其他URI或Authority。 | No |
rewrite | HTTPRewrite | 重写 HTTP URIs and Authority header. 重写不能与重定向原语一起使用 | No |
timeout | Duration | Timeout for HTTP requests. | No |
retries | HTTPRetry | Retry policy for HTTP requests. | No |
fault | HTTPFaultInjection | 故障注入策略,适用于客户端的HTTP通信。请注意,如果在客户端启用了故障注入策略,则不会启用超时或重试。 | No |
mirror | Destination | 除了将请求转发到预期目标之外,还可以将HTTP流量镜像到另一个目标。 | No |
mirrorPercent | UInt32Value |
mirror 字段是设置流量的百分比。如果不存在该字段,则将镜像所有流量(100%)。最大值为100。 |
No |
corsPolicy | CorsPolicy | 有关跨源资源共享的更多详细信息,请参考 CORS | No |
headers | Headers | Header 规则 | No |
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
http:
- match:
- uri:
prefix: /reviews
route:
- destination:
host: reviews
- match:
- uri:
prefix: /ratings
route:
- destination:
host: ratings
...
TCPRoute配置
Field | Type | Description | Required |
---|---|---|---|
match | L4MatchAttributes[] | 匹配要激活的规则要满足的条件。单个匹配块内的所有条件都具有AND语义,而匹配块列表具有OR语义。如果任何一个匹配块成功,则匹配该规则。 | No |
route | RouteDestination[] | 连接应转发到的目的地 | No |
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo-Mongo
spec:
hosts:
- mongo.prod.svc.cluster.local
tcp:
- match:
- port: 27017
route:
- destination:
host: mongo.backup.svc.cluster.local
port:
number: 5555
TLSRoute配置
Type | Type | Description | Required |
---|---|---|---|
match | TLSMatchAttributes[] | 匹配要激活的规则要满足的条件。单个匹配块内的所有条件都具有AND语义,而匹配块列表具有OR语义。如果任何一个匹配块成功,则匹配该规则。 | Yes |
route | RouteDestination[] | 连接应转发到的目的地 | No |
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo-sni
spec:
hosts:
- "*.bookinfo.com"
gateways:
- mygateway
tls:
- match:
- port: 443
sniHosts:
- login.bookinfo.com
route:
- destination:
host: login.prod.svc.cluster.local
- match:
- port: 443
sniHosts:
- reviews.bookinfo.com
route:
- destination:
host: reviews.prod.svc.cluster.local
具体细节的参数明细可查阅:https://preliminary.istio.io/zh/docs/reference/config/networking/virtual-service/#VirtualService
Istio DestinationRule 目标规则
概念及示例
与VirtualService
一样,DestinationRule
也是 Istio 流量路由功能的关键部分。您可以将虚拟服务视为将流量如何路由到给定目标地址,然后使用目标规则来配置该目标的流量。在评估虚拟服务路由规则之后,目标规则将应用于流量的“真实”目标地址。
特别是,您可以使用目标规则来指定命名的服务子集,例如按版本为所有给定服务的实例分组。然后可以在虚拟服务的路由规则中使用这些服务子集来控制到服务不同实例的流量。
目标规则还允许您在调用整个目的地服务或特定服务子集时定制 Envoy 的流量策略,比如您喜欢的负载均衡模型、TLS 安全模式或熔断器设置。在目标规则参考中可以看到目标规则选项的完整列表。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-destination-rule
spec:
host: my-svc
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: v3
labels:
version: v3
每个子集都是基于一个或多个 labels
定义的,在 Kubernetes 中它是附加到像 Pod 这种对象上的键/值对。这些标签应用于 Kubernetes 服务的 Deployment 并作为 metadata
来识别不同的版本。
除了定义子集之外,目标规则对于所有子集都有默认的流量策略,而对于该子集,则有特定于子集的策略覆盖它。定义在 subsets
上的默认策略,为 v1
和 v3
子集设置了一个简单的随机负载均衡器。在 v2
策略中,轮询负载均衡器被指定在相应的子集字段上。
host字段
使用 Kubernetes Service
的短名称。含义同VirtualService 中destination 的 host字段一致。服务 一定要存在于对应的服务注册中心中,否则会被忽略。
loadBalancer字段
默认情况下,Istio 使用轮询的负载均衡策略,实例池中的每个实例依次获取请求。Istio 同时支持如下的负载均衡模型,可以在 DestinationRule
中为流向某个特定服务或服务子集的流量指定这些模型。
- 随机:请求以随机的方式转到池中的实例。
- 权重:请求根据指定的百分比转到实例。
- 最少请求:请求被转到最少被访问的实例。
subsets字段
subsets
是服务端点的集合,可以用于 A/B 测试或者分版本路由等场景。可以将一个服务的流量切分成N份供客户端分场景使用。name
字段定义后主要供 VirtualService
里destination 使用。 每个子集都是在host
对应服务的基础上基于一个或多个 labels
定义的,在 Kubernetes 中它是附加到像 Pod 这种对象上的键/值对。这些标签应用于 Kubernetes 服务的 Deployment 并作为 metadata
来识别不同的版本。
DestinationRule配置
Field | Type | Description | Required |
---|---|---|---|
host | string | 表示规则的适用对象,取值是在服务注册中心注册的服务名,可以是网格内的服务,也可以是以 ServiceEnrty 方式注册的网格外的服务。如果这个服务名在服务注册中心不存在,则这个规则无效。host 如果取短域名,则会根据规则所在的命名空间进行解析。 | Yes |
trafficPolicy | TrafficPolicy | 流量策略,包括负载均衡、连接池策略、异常点检查等 | No |
subsets | Subset[] | 是定义的一个服务的子集,经常用来定义一个服务版本,结合 VirtualService 使用 | No |
exportTo | string[] | 当前destination rule要导出的 namespace 列表。 应用于 service 的 destination rule 的解析发生在 namespace 层次结构的上下文中。 destination rule 的导出允许将其包含在其他 namespace 中的服务的解析层次结构中。 此功能为服务所有者和网格管理员提供了一种机制,用于控制跨 namespace 边界的 destination rule 的可见性 |
如果未指定任何 namespace,则默认情况下将 destination rule 导出到所有 namespace
值.
被保留,用于定义导出到 destination rule 被声明所在的相同 namespace 。类似的值*
保留,用于定义导出到所有 namespaces
NOTE:在当前版本中,exportTo值被限制为.
或*
(即, 当前namespace或所有namespace) | No |
subsets配置
Field | Type | Description | Required |
---|---|---|---|
name | string | 服务名和 subset 名称可以用于路由规则中的流量拆分 |
Yes |
labels | map | 使用标签对服务注册表中的服务端点进行筛选 | No |
trafficPolicy | TrafficPolicy | 应用到这一 subset 的流量策略。缺省情况下 subset 会继承 DestinationRule 级别的策略,这一字段的定义则会覆盖缺省的继承策略 |
No |
具体细节的参数明细可查阅:https://preliminary.istio.io/zh/docs/reference/config/networking/destination-rule/#DestinationRule