转自本人博客: https://uublog.com/article/20191212/principles-of-istio-service-governance/
istio流量治理主要有以下流程
控制面:
数据面:
主要用户服务间访问。通过它可以在多个服务实例找到一个合适的后端把请求转发过去。
Pilot维护服务发现数据,下发给Envoy,Envoy根据负载均衡策略选择一个实例转发请求。
istio的熔断控制无需侵入代码,有别与hystrix。
常见的熔断器状态流转
序号 | 初始状态 | 条件 | 迁移状态 |
---|---|---|---|
1 | 熔断关闭 | 请求成功 | 熔断关闭 |
2 | 熔断关闭 | 请求失败,调用失败次数自增,不超过阀值 | 熔断关闭 |
3 | 熔断关闭 | 请求失败,调用失败次数自增,超过阀值 | 熔断开启 |
4 | 熔断开启 | 熔断器维护计时器,计时未到 | 熔断开启 |
5 | 熔断开启 | 熔断器维护计时器,计时到了 | 熔断半开启 |
6 | 熔断半开启 | 访问成功 | 熔断关闭 |
7 | 熔断半开启 | 访问失败 | 熔断开启 |
有些故障是不会经常触发的,以前模拟故障通常需要修改代码来模拟。而Istio也提供了这个能力。
你叫像AB测试发布,先让小部分用户尝试新版本。观察一段时间后决定使用哪个版本。
常见的灰度发布技术
Istio灰度发布支持七层方向代理,所以可以支持非常丰富的控制策略,根据内容,请求的header作为特征等等。
通过Gateway访问网格内的服务,Gateway和其它网格内的Sidecar一样,也是个Envoy。从控制面接收配置,并执行配置的规则。Gateway一般发布为Loadbalancer类型的service。
Istio通过在Pilot中创建ServiceEntry,配置后端数据库服务访问信息,Istio就会维护这个服务记录,可以对该服务进行配置规则治理。
访问网格外的服务,除了可以通过网格内的sidecar进行治理,也可以通过顶一个一个Egress Gateway,讲所有出口流量转发到Egress Gateway上治理。
属于Istio流量治理核心配置
Istio配置都是通过k8s的CRD方式表达的。
https://istio.io/docs/reference/config/networking/virtual-service/
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
rewrite:
uri: "/newcatalog"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
- name: "reviews-v1-route"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
VirtualService定义了目标服务的一组流量规则,表现形式是一个虚拟服务,讲满足条件的流量转发到对应的后端服务,这个可以后端可以是一个服务,也可以是DestinationRule中定义的服务的子集。
VirtualService是在Istio V1alpha3的API中心如的新路由定义。
VirtualService一些术语
hosts
是必选的一个重要字段。用于匹配访问地址。可以是一个DNS名称或者IP,DNS名称可以使用通配符前缀,也可以写短域名。如果不用全限定的FQDN域名,则运行平台会把短域名解析成FQDN。gateways
表示应用这些流量规则的Gateway。VirtualService描述的规则可以用作Sidecar和入口处的Gateway。mesh
http
是与HTTPRoute
类型的路由集合,处理http流量,是istio最丰富的流量规则tls
是一个TLSRoute类型的集合,用于处理非终结的TLS和HTTPS流量tcp
是一个TCLRoute类型的集合,用于处理TCP流量,应用于所有非HTTP和TLS流量。没有对https和tls定义对应的TLSRoute,则也会当做TCP流量处理。exportTo
是Istio1.1新增的字段。控制VirtualService跨命名空间的可见性。控制它是否能被其它命名空间下的sidecar和Gateway发现。默认全局可见。.
表示当前命名空间可见 *
表示所有命名空间可见。用于处理HTTP流量
对应的协议为 HTTP
、HTTP2
、GRPC
满足HTTPMatchRequest条件的流量都睡被路由到HTTPRouteDestination。
执行重定向(HTTPRedirect)、重写(HTTPRewrite)、重试(HTTPRetry)、故障注入(HTTPFaultInjection)、跨站(CorsPolicy)策略等。
还可以做一些写操作修改请求本身。
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类型的键值对。请求来源的负载匹配标签。可以通过这个来区别不同的服务组。
http:
- match:
- sourceLabels:
app: frontend
version: v2
HTTPMatchRequest中,元素之间关系一般是“或”逻辑,属性之间关系一般是“或”逻辑
HTTPRoute上的Route字段是一个HTTPRouteDestination类型的数组,表示满足条件的流量目标。可以定义多个Route,通过权重(weight)来实现灰度发布。
HTTPRouteDestination主要有三个字段: destination(请求目标)、weight(权重)、headers(http头操作)
destination和weight是必选字段
HTTPRoute比TCPRoute多出一个headers字段。
headers有request和response两个字段。
字段对应的类型都是HeaderOperation类型,可以使用set、add、remove字段来定义对Header的操作。
可以通过它发送一个301重定向给服务调用方。
HTTPRedirect有两个字段:
配置和上面的HTTPRedirect配置类似。不同的是,HTTPRedirect只能替换全部path。HTTPRewrite可以只替换HTTPMatchRequest匹配到的部分。比如前缀匹配,只会重写前缀部分。
#### HTTP重试(HTTPRetry)
定义请求失败时候的重试策略。包括重试次数、超时、重试条件等
指在给目标地址转发流量的同时给另一个目标地址也镜像一份。
数据代理只需关注原来的转发就可以,不用等待镜像地址返回
HTTPFaultInjection有两个字段 Delay和Abort
例子:
模拟1.5%的请求出现500的故障
route:
- destination:
host: forecast
subnet: v1
fault:
abort:
percentage:
value: 1.5
httpStatus: 500
可以对满足条件的请求配置跨资源共享(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和HTTPS流量。使用SNI(server name indecation) 客户端在和TLS握手阶段建立的连接使用的服务hostname做路由选择。
使用场景
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.loca
满足匹配规则的转发到对应后端
匹配条件是 TLSMatchAttributes
路由规则是 RouteDestination
TLSRoute中match字段是TLSMatchAttributes类型是一个数组
https://istio.io/docs/reference/config/networking/virtual-service/#TLSMatchAttributes
TLSRoute通过RouteDestination来面熟转啊的目的地址,是一个四层路由转发地址。包含两个必选属性destination和weight
所有不满足HTTP和TLS条件的流量都会应用TCPRoute
https://istio.io/docs/reference/config/networking/virtual-service/#TCPRoute
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
VirtualService中目标对象Destination中表示service子集的subset字段就是通过DestinationRule定义的。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bookinfo-ratings
spec:
host: ratings.prod.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
subsets:
- name: testversionv3
labels:
version: v3
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: testversionv4
labels:
version: v4
trafficPolicy:
loadBalancer:
simple: RANDOM
DestinationRule经常和VirtualService结合使用。VirtualService用到的子集subset在DestinationRule都有对应的定义。
属性 | 描述 |
---|---|
host | 必选字段,表示规则的使用对象。如果取短域名则会根据规则所在的命名空间进行解析。建议FQDN |
trafficPolicy | 规则内容定义。包括负载均衡、连接池策略、异常点检查等 |
subset | 定义服务的子集,通常用来区别不同版本。 |
exportTo | Istio1.1后添加的重要字段。表示跨命名空间可见性。默认全局可见。只支持“.”和“*”两种配置 |
流量策略包含四个重要的配置
属性 | 描述 |
---|---|
loadBalancer | LoadBalancerSettings类型,描述服务的负载均衡算法。 |
connectionPool | ConnectionPoolSettings 类型,描述连接池配置。 |
outlierDetection | OutlierDetection ,描述服务的异常点检查。 |
tls | TLSSettings 类型,描述服务的TLS连接设置。 |
字段 | 描述 |
---|---|
simple | 负载均衡算法 |
consistentHash | 一致性哈希,一种高级负载均衡策略 只对HTTP有效 |
字段值 | 描述 |
---|---|
ROUND_ROBIN | 负载均衡算法 |
LEAST_CONN | 最少连接算法 |
RANDOM | 随机算法 |
PASSTHROUGH | 直接转发 |
字段值 | 描述 |
---|---|
httpHeaderName | 计算Header的哈希 |
httpCookie | 计算cookie的哈希 |
useSourceIp | 基于源IP计算哈希 |
minimumRingSize | 哈希环上的虚拟节点最小值,节点越多越精细。如果实例少于虚拟节点数,这每个后端都会有一个虚拟节点。 |
可以通过连接池管理,配置阀值来防止一个服务失败级联影响到整个应用。
连接池管理在协议上分为TCP流量和HTTP流量治理。
字段 | 描述 |
---|---|
maxConnections | 表示上游服务所有实例建立的最大连接数,默认为1024.对于HTTP只适用1.1,HTTP对每个主机使用单连接 |
connectionTimeout | TCP连接超时,可以改善服务相应过慢导致整个链路变慢的情况。 |
tcpKeepalive | istio新增的配置。定时发送keepalive探测报,长度为0. |
tcpKeepablve 三个字段
对于七层协议,可以通过对应的连接池进行更细致的配置。
因书的描述的默认值和官网给的相差过大,直接使用官网的数据
https://istio.io/docs/reference/config/networking/destination-rule/#ConnectionPoolSettings-HTTPSettings
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
将前面四种策略应用到端口上。
和TrafficPolicy没有很大差别
https://istio.io/docs/reference/config/networking/destination-rule/#TrafficPolicy-PortTrafficPolicy
通常用来定义版本。VirtualService可以给版本配置流量规则。将流量导入到subset的后端实例上。
subset三个重要属性
字段 | 描述 |
---|---|
name | 必选字段,VirtualService用的就是这名字 |
labels | subnet的标签,通常识别服务版本的Version标签 |
trafficPolicy | 应用到这个subset的流量策略 |
maxEjectionPercent | 均衡池中可以被驱逐的故障实例 |
主要有以下几种
使用DestinationRule定义subset来为某个服务定义多个服务版本。可以配合VirtualService流量策略实现各种发布场景,比如蓝绿、灰度、金丝雀之类的。
定义服务版本v1,v2
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-destination
spec:
host: reviews.prod.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
配置VirtualService将75%流量导入v1,25%流量导入v2
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
weight: 25
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
weight: 75
一般使用异常检查点(OutlierDetection)和连接池管理(ConnectionPoolSettings)两种手段来实现服务熔断机制。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-cb-policy
spec:
host: reviews.prod.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 80
http:
http2MaxRequests: 1000
maxRequestsPerConnection: 10
outlierDetection:
consecutiveErrors: 7
interval: 5m
baseEjectionTime: 15m
maxEjectionPercent: 30
表示最大连接80个,最大请求数为1000个,单个连接最大请求次数为10次。如果服务实例5分钟内连续7次出现故障,则会被隔离15分钟。最大故障隔离比例为30%.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bookinfo-ratings
spec:
host: ratings.prod.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
subsets:
- name: v3
labels:
version: v3
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
- name: v4
labels:
version: v4
trafficPolicy:
loadBalancer:
simple: RANDOM
实现bookinfo-ratings v3流量采取轮询的负载均衡策略,v4采取随机负载均衡策略。
mode: ISTIO_MUTUAL
istio便可以自动进行密钥证书的管理
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings-istio-mtls
spec:
host: ratings.prod.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
更多TLS配置示例 https://istio.io/docs/reference/config/networking/destination-rule/#TLSSettings
Gateway在网格边缘接收外部访问,讲流量转发到网格内的服务。
Gateway配置
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway
namespace: some-config-namespace
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- uk.bookinfo.com
- eu.bookinfo.com
tls:
httpsRedirect: true # sends 301 redirect for http requests
- port:
number: 443
name: https-443
protocol: HTTPS
hosts:
- uk.bookinfo.com
- eu.bookinfo.com
tls:
mode: SIMPLE # enables HTTPS on this port
serverCertificate: /etc/certs/servercert.pem
privateKey: /etc/certs/privatekey.pem
- port:
number: 9443
name: https-9443
protocol: HTTPS
hosts:
- "bookinfo-namespace/*.bookinfo.com"
tls:
mode: SIMPLE # enables HTTPS on this port
credentialName: bookinfo-secret # fetches certs from Kubernetes secret
- port:
number: 9080
name: http-wildcard
protocol: HTTP
hosts:
- "*"
- port:
number: 2379 # to expose internal service via external port 2379
name: mongo
protocol: MONGO
hosts:
- "*"
在VirtualService中的gateways字段来指定应用哪些gateway规则。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo-rule
namespace: bookinfo-namespace
spec:
hosts:
- reviews.prod.svc.cluster.local
- uk.bookinfo.com
- eu.bookinfo.com
gateways:
- some-config-namespace/my-gateway
- mesh # applies to all the sidecars in the mesh
http:
- match:
- headers:
cookie:
exact: "user=dev-123"
route:
- destination:
port:
number: 7777
host: reviews.qa.svc.cluster.local
- match:
- uri:
prefix: /reviews/
route:
- destination:
port:
number: 9080 # can be omitted if it's the only port for reviews
host: reviews.prod.svc.cluster.local
weight: 80
- destination:
host: reviews.qa.svc.cluster.local
weight: 20
Gateway配置一般配合VirtualService规则使用。
Gateway定义了服务从外面怎么访问。
VirtualService定义了匹配到的内部服务怎么流转。
不同v1alpha1的k8s,在Ingress中描述服务入口和后端服务的路由。Istio解耦了,Gateway只描述外部服务的访问。
Gateway定义了两个关键的字段
字段 | 描述 |
---|---|
selector | 必选,表示Gateway负载,作为入口处的Envoy运行的pod标签。通过这个找到对应的Envoy。 |
server | 必选,表示开放的服务列表。数组类型。 |
server定义了真正的服务访问入口
字段 | 描述 |
---|---|
port | 必选字段,描述服务在哪个服务对外开放,是对外监听的端口。 |
hosts | 必选字段,数组类型。FQDN域名,支持左侧通配符。支持使用命名空间过滤条件。 |
绑定到一个Gateway的VirtualService必须匹配这里的hosts条件。
除了hosts匹配到,还要VirtualService的exportTo字段包含Gateway所在的命名空间,才能被关联到。
字段 | 描述 |
---|---|
httpsRedirect | 启用时,负载均衡器会给所有http连接发送一个301重定向到https |
mode | TLSmode |
更多字段看官网: https://istio.io/docs/reference/config/networking/gateway/#Server-TLSOptions
将外部服务加入网格中,像网格内的服务一样管理。
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: external-svc-https
spec:
hosts:
- api.dropboxapi.com
- www.googleapis.com
- api.facebook.com
location: MESH_EXTERNAL
ports:
- number: 443
name: https
protocol: TLS
resolution: DNS
完整: 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也可以是主机名 |
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: tls-routing
spec:
hosts:
- wikipedia.org
- "*.wikipedia.org"
tls:
- match:
- sniHosts:
- wikipedia.org
- "*.wikipedia.org"
route:
- destination:
host: internal-egress-firewall.ns1.svc.cluster.local
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: external-svc-httpbin
namespace : egress
spec:
hosts:
- httpbin.com
exportTo:
- "."
location: MESH_EXTERNAL
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
定义一个全局的默认Sidecar配置在 root命名空间,叫istio-config
该空间下的所有workload允许Egress流量,istio-system命名空间下的所有workloadworkload也可以。
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
name: default
namespace: istio-config
spec:
egress:
- hosts:
- "./*"
- "istio-system/*"
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
name: default
namespace: prod-us1
spec:
ingress:
- port:
number: 9080
protocol: HTTP
name: somename
defaultEndpoint: unix:///var/run/someuds.sock
egress:
- port:
number: 9080
protocol: HTTP
name: egresshttp
hosts:
- "prod-us1/*"
- hosts:
- "istio-system/*"
新增加的 提供了对Envoy更信息的控制. 用来更新配置Envoy中的filter
有L4/L7的filter
https://istio.io/docs/reference/config/networking/envoy-filter/