Istio非侵入的流量治理
Istio流量治理原理
istio流量治理主要有以下流程
控制面:
- 管理员通过命令行或者api创建流量规则
- Pilot将流量规则转换为Envoy的标准格式
- Pilot将规则下发给Envoy
数据面:
- Envoy拦截Pod上本地容器Inbound和Outbound的流量
- 在流量经过Envoy时,执行对应的流量规则,进行流量治理
负载均衡
主要用户服务间访问。通过它可以在多个服务实例找到一个合适的后端把请求转发过去。
Pilot维护服务发现数据,下发给Envoy,Envoy根据负载均衡策略选择一个实例转发请求。
服务熔断
istio的熔断控制无需侵入代码,有别与hystrix。
常见的熔断器状态流转
序号 | 初始状态 | 条件 | 迁移状态 |
---|---|---|---|
1 | 熔断关闭 | 请求成功 | 熔断关闭 |
2 | 熔断关闭 | 请求失败,调用失败次数自增,不超过阀值 | 熔断关闭 |
3 | 熔断关闭 | 请求失败,调用失败次数自增,超过阀值 | 熔断开启 |
4 | 熔断开启 | 熔断器维护计时器,计时未到 | 熔断开启 |
5 | 熔断开启 | 熔断器维护计时器,计时到了 | 熔断半开启 |
6 | 熔断半开启 | 访问成功 | 熔断关闭 |
7 | 熔断半开启 | 访问失败 | 熔断开启 |
故障注入
有些故障是不会经常触发的,以前模拟故障通常需要修改代码来模拟。而Istio也提供了这个能力。
灰度发布
- 蓝绿发布
类似热发布。先部署新版本,等新版可用后,全流量切换过去。 - AB测试
部署对等的两个版本A和B,分流一部分去a,一部分去b,然后根据运营收集数据,根据反馈选择使用哪个版本。 - 金丝雀发布/灰度发布
你叫像AB测试发布,先让小部分用户尝试新版本。观察一段时间后决定使用哪个版本。
常见的灰度发布技术
- 基于负载均衡的会的发布
- k8s 基于不同版本pod数量来控制流量比例
Istio灰度发布支持七层方向代理,所以可以支持非常丰富的控制策略,根据内容,请求的header作为特征等等。
服务访问入口
- k8s服务的访问入口
- Loadbalancer 类型的Service 根据端口直接转发给指定的服务
- Ingress访问入口 根据七层协议转发
- Istio服务访问入口
通过Gateway访问网格内的服务,Gateway和其它网格内的Sidecar一样,也是个Envoy。从控制面接收配置,并执行配置的规则。Gateway一般发布为Loadbalancer类型的service。
外部的接入服务治理
Istio通过在Pilot中创建ServiceEntry,配置后端数据库服务访问信息,Istio就会维护这个服务记录,可以对该服务进行配置规则治理。
访问网格外的服务,除了可以通过网格内的sidecar进行治理,也可以通过顶一个一个Egress Gateway,讲所有出口流量转发到Egress Gateway上治理。
Istio路由规则配置: VirtualService
属于Istio流量治理核心配置
路由规则配置示例
Istio配置都是通过k8s的CRD方式表达的。
https://istio.io/docs/reference/config/networking/virtual-service/
1 | apiVersion: networking.istio.io/v1alpha3 |
路由规则定义
VirtualService定义了目标服务的一组流量规则,表现形式是一个虚拟服务,讲满足条件的流量转发到对应的后端服务,这个可以后端可以是一个服务,也可以是DestinationRule中定义的服务的子集。
VirtualService是在Istio V1alpha3的API中心如的新路由定义。
VirtualService一些术语
- Service 服务
- Service Version (AKA subnets) 服务版本
- Source 发起调用的服务
- Host 调用目标时使用的地址
hosts
是必选的一个重要字段。用于匹配访问地址。可以是一个DNS名称或者IP,DNS名称可以使用通配符前缀,也可以写短域名。如果不用全限定的FQDN域名,则运行平台会把短域名解析成FQDN。
推荐写全限定的FQDN,格式
2. gateways
表示应用这些流量规则的Gateway。VirtualService描述的规则可以用作Sidecar和入口处的Gateway。
如果只是网格内访问,Gateway可以省略,如果是网格外访问,就需要用到Gateway字段。如果内外都要,则还需增加保留字mesh
3. http
是与HTTPRoute
类型的路由集合,处理http流量,是istio最丰富的流量规则
4. tls
是一个TLSRoute类型的集合,用于处理非终结的TLS和HTTPS流量
5. tcp
是一个TCLRoute类型的集合,用于处理TCP流量,应用于所有非HTTP和TLS流量。没有对https和tls定义对应的TLSRoute,则也会当做TCP流量处理。
VirtualService的路由规则使用上是一个有序的数组,在匹配到第一个满足的规则时就跳出,不会检查后面的规则。
6. exportTo
是Istio1.1新增的字段。控制VirtualService跨命名空间的可见性。控制它是否能被其它命名空间下的sidecar和Gateway发现。默认全局可见。.
表示当前命名空间可见 *
表示所有命名空间可见。
HTTP路由 (HTTPRoute)
用于处理HTTP流量
对应的协议为 HTTP
、HTTP2
、GRPC
- 服务端口名为 http-、http2-、grpc-
- Gateway端口协议满足对应的协议,或者Gateway是终结TLS,就是外部是https,内部还是http
- ServiceEntry满足对应协议
HTTPRoute规则解析
满足HTTPMatchRequest条件的流量都睡被路由到HTTPRouteDestination。
执行重定向(HTTPRedirect)、重写(HTTPRewrite)、重试(HTTPRetry)、故障注入(HTTPFaultInjection)、跨站(CorsPolicy)策略等。
还可以做一些写操作修改请求本身。
HTTP匹配规则(HTTPMatchRequest)
HTTPRoute最重要的字段是match,是HTTPMatchRequest类型的数组。
一个URI完整的格式为 URI
=scheme
://Authority
/path
?query
Authority
=userinfo
@host
:port
HTTPMatchRequest支持将uri、scheme、method、authority、port作为条件来匹配。
uri、scheme、method、authority都是StringMatch类型,在匹配时都支持exact、prefix、regex三种漠视的匹配。分别为精确匹配、前缀匹配、正则匹配
headers: headers是一个map类型,但是他的key是字符串类型,value也是StringMatch类型。
port: 请求的服务端口号。微服务中推荐只开放一个端口,这种情况可以忽略不写。
sourceLabels: map类型的键值对。请求来源的负载匹配标签。可以通过这个来区别不同的服务组。
1
2
3
4
5http:
- match:
- sourceLabels:
app: frontend
version: v2gateways: 表示应用规则的Gateway,与VirtualService的Gateways定义一样,只是一个更细的match。
HTTPMatchRequest中,元素之间关系一般是“或”逻辑,属性之间关系一般是“或”逻辑
HTTP路由目标(HTTPRouteDestination)
HTTPRoute上的Route字段是一个HTTPRouteDestination类型的数组,表示满足条件的流量目标。可以定义多个Route,通过权重(weight)来实现灰度发布。
HTTPRouteDestination主要有三个字段: destination(请求目标)、weight(权重)、headers(http头操作)
destination和weight是必选字段
- destination
destination有三个属性描述: host、subset、port
host: 必选字段,表示在istio中注册的服务名。建议写全限定FQDN。如. .svc.cluster.local
subset: 子集。通常用来区别不同的版本。比如同个服务,不同的subset来实现灰度发布。
port: 端口,一个端口通常可以缺省不写 - weight
表示流量的分配比例。一个route下多个destination的weight总和要求是100
如果只有一个可以不写,默认是100 - headers
HTTPRoute比TCPRoute多出一个headers字段。
headers有request和response两个字段。
- request 表示在发送给目标地址时修改request header
- response 表示在接收目标的response时修改response header
字段对应的类型都是HeaderOperation类型,可以使用set、add、remove字段来定义对Header的操作。
HTTP重定向(HTTPRedirect)
可以通过它发送一个301重定向给服务调用方。
HTTPRedirect有两个字段:
- uri 表示替换URL中path的部分
- authority 表示替换URL中authority的部分
HTTP重写(HTTPRewrite)
配置和上面的HTTPRedirect配置类似。不同的是,HTTPRedirect只能替换全部path。HTTPRewrite可以只替换HTTPMatchRequest匹配到的部分。比如前缀匹配,只会重写前缀部分。
HTTP重试(HTTPRetry)
定义请求失败时候的重试策略。包括重试次数、超时、重试条件等
- attempts 必选字段,定义重试的次数
- perTryTimeout 每次重试超时的时间,单位可以是ms、s、m、h 毫秒到小时
- retryOn 重试条件,可以是多个条件。取值包括以下几种
- 5xx 5xx类异常
- gateway-error 类似5xx,但是只作用502,503,504网关类应代码
- connect-failure 连接上游服务失败时
- retriable-4xx 上游返回可重试的4xx应答码时重试
- refused-stream 上游返回REFUSED_STREAM
- cancelled 在gRPC中header状态是cancelled时
- deadline-exceeded 在gRPC中状态码是deadline-exceeded时
- internal 在gRPC中状态码是internal时
- resource-exhausted 在gRPC中状态码是resource-exhausted时重试 资源用尽
- unavailable 在gRPC中状态码是unavailable时
HTTP流量镜像(Mirror)
指在给目标地址转发流量的同时给另一个目标地址也镜像一份。
数据代理只需关注原来的转发就可以,不用等待镜像地址返回
HTTP故障注入(HTTPFaultInjection)
HTTPFaultInjection有两个字段 Delay和Abort
- Delay 延迟故障注入
- fixedDelay 必选,表示延迟时间,要求大于1毫秒,单位可以是ms、s、m、h 毫秒到小时
- percentage 故障百分比,如1.5表示1.5%的请求产生延迟故障
- 请求中止故障
- httpStatus 必选 中止的状态码
- percentage 故障百分比。
例子:
模拟1.5%的请求出现500的故障
1 | route: |
HTTP跨资源共享(CorsPolicy)
可以对满足条件的请求配置跨资源共享(CORS)
字段如下:
字段 | 作用 | 对应的header |
---|---|---|
allowOrigin | 允许的来源列表 | Access-Control-Allow-Origin |
allowMethods | 允许的方法列表 | Access-Control-Allow-Methods |
allowHeaders | 允许的头部列表 | Access-Control-Allow-Headers |
exposeHeaders | 浏览器允许访问的header白名单 | Access-Control-Expose-Headers |
maxAge | 请求缓存时间 | Access-Control-Max-Age |
allowCredentials | 允许服务调用方使用凭据发起请求 | Access-Control-Allow-Credentials |
TLS路由(TLSRoute)
处理非终结的TLS和HTTPS流量。使用SNI(server name indecation) 客户端在和TLS握手阶段建立的连接使用的服务hostname做路由选择。
使用场景
- 服务端口协议是HTTPS和TLS,就是端口名包含 https-、tls-
- Gateway的端口是非终结的HTTPS和TLS
- ServiceEntry的端口是HTTPS和TLS
TLSRoute配置示例
1 | apiVersion: networking.istio.io/v1alpha3 |
TLSRoute规则解析
满足匹配规则的转发到对应后端
匹配条件是 TLSMatchAttributes
路由规则是 RouteDestination
TLS匹配规则(TLSMatchAttributes)
TLSRoute中match字段是TLSMatchAttributes类型是一个数组
https://istio.io/docs/reference/config/networking/virtual-service/#TLSMatchAttributes
四层路由目标(RouteDestination)
TLSRoute通过RouteDestination来面熟转啊的目的地址,是一个四层路由转发地址。包含两个必选属性destination和weight
TCP路由(TCPRoute)
所有不满足HTTP和TLS条件的流量都会应用TCPRoute
https://istio.io/docs/reference/config/networking/virtual-service/#TCPRoute
TCPRoute配置示例
1 | apiVersion: networking.istio.io/v1alpha3 |
Istio目标规则配置:DestinationRule
VirtualService中目标对象Destination中表示service子集的subset字段就是通过DestinationRule定义的。
DestinationRule配置示例
1 | apiVersion: networking.istio.io/v1alpha3 |
DestinationRule规则定义
DestinationRule经常和VirtualService结合使用。VirtualService用到的子集subset在DestinationRule都有对应的定义。
属性 | 描述 |
---|---|
host | 必选字段,表示规则的使用对象。如果取短域名则会根据规则所在的命名空间进行解析。建议FQDN |
trafficPolicy | 规则内容定义。包括负载均衡、连接池策略、异常点检查等 |
subset | 定义服务的子集,通常用来区别不同版本。 |
exportTo | Istio1.1后添加的重要字段。表示跨命名空间可见性。默认全局可见。只支持“.”和“*”两种配置 |
流量策略 TrafficPolicy
流量策略包含四个重要的配置
属性 | 描述 |
---|---|
loadBalancer | LoadBalancerSettings类型,描述服务的负载均衡算法。 |
connectionPool | ConnectionPoolSettings 类型,描述连接池配置。 |
outlierDetection | OutlierDetection ,描述服务的异常点检查。 |
tls | TLSSettings 类型,描述服务的TLS连接设置。 |
负载均衡设置 LoadBalancerSettings
字段 | 描述 |
---|---|
simple | 负载均衡算法 |
consistentHash | 一致性哈希,一种高级负载均衡策略 只对HTTP有效 |
simple字段
字段值 | 描述 |
---|---|
ROUND_ROBIN | 负载均衡算法 |
LEAST_CONN | 最少连接算法 |
RANDOM | 随机算法 |
PASSTHROUGH | 直接转发 |
consistentHash字段
字段值 | 描述 |
---|---|
httpHeaderName | 计算Header的哈希 |
httpCookie | 计算cookie的哈希 |
useSourceIp | 基于源IP计算哈希 |
minimumRingSize | 哈希环上的虚拟节点最小值,节点越多越精细。如果实例少于虚拟节点数,这每个后端都会有一个虚拟节点。 |
连接池设置 ConnectionPoolSettings
可以通过连接池管理,配置阀值来防止一个服务失败级联影响到整个应用。
连接池管理在协议上分为TCP流量和HTTP流量治理。
TCP连接池配置 TCPSettings
字段 | 描述 |
---|---|
maxConnections | 表示上游服务所有实例建立的最大连接数,默认为1024.对于HTTP只适用1.1,HTTP对每个主机使用单连接 |
connectionTimeout | TCP连接超时,可以改善服务相应过慢导致整个链路变慢的情况。 |
tcpKeepalive | istio新增的配置。定时发送keepalive探测报,长度为0. |
tcpKeepablve 三个字段
- probes 表示有多少次探测无响应就断定连接断开 linux缺省数值是9
- time 表示发送探测前空闲了多长时间 linux中缺省是2小时
- interval 探测间隔 Linux中缺省是75秒
HTTP连接池配置 HTTPSettings
对于七层协议,可以通过对应的连接池进行更细致的配置。
因书的描述的默认值和官网给的相差过大,直接使用官网的数据
异常实例检测设置 OutlierDetection
Istio的熔断机制。定期考察服务实例的工作情况,如果连续出现访问异常,就标记并进行隔离。
字段 | 描述 |
---|---|
consecutiveErrors | 实例被驱逐前的连续错误次数,默认是5.HTTP返回5xx被认为异常,TCP超时和连接出错被认为异常 |
interval | 驱逐的时间间隔,默认10s,要求大于1ms,可以是ms、s、m、h |
baseEjectionTime | 最小驱逐时间,默认30s。可选单位如上 |
maxEjectionPercent | 均衡池中可以被驱逐的故障实例最大比例。默认是10%. 避免驱逐太多服务能力下降。 |
minHealthPercent | 最小健康比例。默认50%.健康比例大于这个值时,异常检查打开。反之关闭,所有实例接收请求。 |
https://istio.io/docs/reference/config/networking/destination-rule/#OutlierDetection
端口流量策略设置 PortTrafficPolicy
将前面四种策略应用到端口上。
和TrafficPolicy没有很大差别
https://istio.io/docs/reference/config/networking/destination-rule/#TrafficPolicy-PortTrafficPolicy
服务子集 subset
通常用来定义版本。VirtualService可以给版本配置流量规则。将流量导入到subset的后端实例上。
subset三个重要属性
字段 | 描述 |
---|---|
name | 必选字段,VirtualService用的就是这名字 |
labels | subnet的标签,通常识别服务版本的Version标签 |
trafficPolicy | 应用到这个subset的流量策略 |
maxEjectionPercent | 均衡池中可以被驱逐的故障实例 |
DestinationRule的典型应用
主要有以下几种
定义subset
使用DestinationRule定义subset来为某个服务定义多个服务版本。可以配合VirtualService流量策略实现各种发布场景,比如蓝绿、灰度、金丝雀之类的。
定义服务版本v1,v2
1 | apiVersion: networking.istio.io/v1alpha3 |
配置VirtualService将75%流量导入v1,25%流量导入v2
1 | apiVersion: networking.istio.io/v1alpha3 |
服务熔断示例
一般使用异常检查点(OutlierDetection)和连接池管理(ConnectionPoolSettings)两种手段来实现服务熔断机制。
1 | apiVersion: networking.istio.io/v1alpha3 |
表示最大连接80个,最大请求数为1000个,单个连接最大请求次数为10次。如果服务实例5分钟内连续7次出现故障,则会被隔离15分钟。最大故障隔离比例为30%.
负载均衡配置示例
1 | apiVersion: networking.istio.io/v1alpha3 |
实现bookinfo-ratings v3流量采取轮询的负载均衡策略,v4采取随机负载均衡策略。
TLS认证配置
mode: ISTIO_MUTUAL
istio便可以自动进行密钥证书的管理
1 | apiVersion: networking.istio.io/v1alpha3 |
更多TLS配置示例 https://istio.io/docs/reference/config/networking/destination-rule/#TLSSettings
Istio服务网关配置 Gateway
Gateway在网格边缘接收外部访问,讲流量转发到网格内的服务。
Gateway配置示例
Gateway配置
1 | apiVersion: networking.istio.io/v1alpha3 |
在VirtualService中的gateways字段来指定应用哪些gateway规则。
1 | apiVersion: networking.istio.io/v1alpha3 |
Gateway规则定义
Gateway配置一般配合VirtualService规则使用。
Gateway定义了服务从外面怎么访问。
VirtualService定义了匹配到的内部服务怎么流转。
不同v1alpha1的k8s,在Ingress中描述服务入口和后端服务的路由。Istio解耦了,Gateway只描述外部服务的访问。
Gateway定义了两个关键的字段
字段 | 描述 |
---|---|
selector | 必选,表示Gateway负载,作为入口处的Envoy运行的pod标签。通过这个找到对应的Envoy。 |
server | 必选,表示开放的服务列表。数组类型。 |
后端服务server
server定义了真正的服务访问入口
字段 | 描述 |
---|---|
port | 必选字段,描述服务在哪个服务对外开放,是对外监听的端口。 |
hosts | 必选字段,数组类型。FQDN域名,支持左侧通配符。支持使用命名空间过滤条件。 |
绑定到一个Gateway的VirtualService必须匹配这里的hosts条件。
除了hosts匹配到,还要VirtualService的exportTo字段包含Gateway所在的命名空间,才能被关联到。
TLS选项 TLSOptions
字段 | 描述 |
---|---|
httpsRedirect | 启用时,负载均衡器会给所有http连接发送一个301重定向到https |
mode | TLSmode |
更多字段看官网: https://istio.io/docs/reference/config/networking/gateway/#Server-TLSOptions
Gateway的典型应用
- 发布网格内的HTTP服务为外部HTTP访问
- 将网格内的HTTPS服务发布为HTTPS服务外部访问
- 将网格内的HTTP服务发布为HTTPS服务外部访问
- 将网格内的HTTP服务发布为双向HTTPS外部访问
- 将网格内的HTTP服务发布为HTTPS外部访问和HTTPS内部访问
Istio外部服务配置 ServiceEntry
将外部服务加入网格中,像网格内的服务一样管理。
ServiceEntry配置示例
1 | apiVersion: networking.istio.io/v1alpha3 |
ServiceEntry定义以及用法
完整: https://istio.io/docs/reference/config/networking/service-entry/#ServiceEntry
字段 | 描述 |
---|---|
hosts | 可以是一个DNS域名,还可以使用前缀模糊匹配。 |
addresses | 服务关联的IP地址,支持CIDR这种前缀表达式,http流量该字段被忽略 |
posts | 表示与外部服务关联的端口。必选。 |
location | 表示服务是在内部还是外部。MESH_EXTERNAL和MESH_INTERNAL |
resolution | 服务发现模式,NONE、STATIC、DNS |
subjectAltNames | 服务负载的SAN列表 |
endpoints | 与网格服务关联的网络地址,可以是IP也可以是主机名 |
ServiceEntry典型应用
1 | apiVersion: networking.istio.io/v1alpha3 |
1 | apiVersion: networking.istio.io/v1alpha3 |
Istio代理规则配置 Sidecar
定义一个全局的默认Sidecar配置在 root命名空间,叫istio-config
该空间下的所有workload允许Egress流量,istio-system命名空间下的所有workloadworkload也可以。
1 | apiVersion: networking.istio.io/v1alpha3 |
1 | apiVersion: networking.istio.io/v1alpha3 |
Envoy Filter
新增加的 提供了对Envoy更信息的控制. 用来更新配置Envoy中的filter
有L4/L7的filter
https://istio.io/docs/reference/config/networking/envoy-filter/