istio在namespace中开启自动注入后,我们不再需要关心sidecar的生命周期与生效时间。进行流量治理的时候我们只需要与istio交互即可
在(一)中我们已经了解了Istio是通过k8的service进行服务发现的,所以即使我们的服务没有对外服务的能力,如果需要被istio接管的话也需要配置service(istio接近所有的流量治理方式都需要基于service操作
)
istio对k8的service依赖很深,所以在使用时也存在一些硬性要求
在istio的0.8版本以前为了满足这一需求,istio是不允许一个pod关联到多个服务的
)控制层
(1)管理员通过命令行或API创建流量规则
(2)Pilot组件(上一节中介绍过,Pilot组件类似一个master服务的功能会下发路由规则给每一个Sidecar,除了下发以外Pilot还有一个类似于解释器的功能,将用户配置的规则翻译成每个sidecar能识别的格式
)将流量规则转换为Envoy可以识别的标准格式;
(3)Polot组件将规则下发给Envoy
数据层
(1)Envoy拦截对应pod的IO流量
(2)Envoy在拦截到流量时根据收到的规则将流量治理
Istio的流量治理主要通过VirtualService(路由规则
)、DestinationRule(目标规则
)、Gateway(服务网关
)、ServiceEntry(外部服务
)来实现,其中我们最多使用的就是VS和DR
virtualService是istio最主要最复杂的核心配置,主要负责配置服务的调用规则,分发规则等等,在详细介绍vs功能之前,可以先查看以下的简化配置内容
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
vs配置中的关键配置项
hosts:表示流量发送的目标(可以理解为拦截目标,也可以理解为配置的路由规则归属哪一个Sidecar
),在k8s中hosts需要配置为服务的service域名,同namesapce下可以配置 短域名(因为可以跨namespace配置路由规则,所以这里是不便于管理的,如果重新开发istio配置管理dashboard可以考虑为域名分配增加权限
)
http: 是一个类似httpRoute的路由集合,用于处理http的流量,是istio最丰富的的流量规则
tls:是一个tlsRoute类型的路由集合,用于处理非终结的tls和https流量
tcp:是一个tcpRoute类型的路由集合,用于处理tcp流量,应用于所有非http和tls端口的流量
exportTo:是istio在1.1版本后的新增特性,用于控制VS跨namespace的可见性。可以控制在一个命名空间下定义的vs是否可以被其他命名空间的Sidecar和Gateway使用。不填写代表全局可见,".“代表仅当前namespace可见,”* "代表所有namespace可见。
在正常使用时,http协议的路由应用场景最多,主要介绍一下http路由的使用场景和使用方法
如上图,httproute可以通过请求中的内容为条件,对请求进行重定向、重写、重试、故障注入、流量复制等操作
我们把这些步骤拆分一下,主要分为匹配规则,重定向,重写,重试,故障注入,流量复制这几个方面来详述。
简述:匹配规则是分发流量的重要条件,关键字段是match字段,在match字段下就是对请求路由的匹配方式。
uri、scheme、method、authority:这4个字段都是StringMatch类型,请求规则中都支持exact(完全匹配),prefix(前缀匹配)、regex(正则匹配)三种匹配方式
headers:匹配请求中的header,是一个map类型,所以匹配时以k-v的形式比对,对每一个header的值都可以使用exact,prefix、regex三种匹配方式。
例:
- match:
- headers:
end-user:
exact: jason
uri:
prefix: "/testPipeline"
以上规则中包含了1和2的使用方式,代表匹配请求头中的end-user的值为jason且uri以/testPipeline开头的请求。
http:
- match:
- sourceLabels:
app: cicdfront
version: v1.0.10
route:
- destination:
host: cicdapi
subset: v1.0.10
- route:
- destination:
host: cicdapi
subset: v1.0.9
当请求服务来源为cicdfront且其pod版本为v1.0.10时会将流量转发到cicdapi的v1.0.10上,其他的请求会发送到cicdapi的v1.0.9版本上
简述:路由目标代表请求流量发送到的目标服务,关键字段是route,在match(匹配规则)下时常代表匹配规则后的发送请求的目标服务。
当请求完成匹配规则后,我们需要对匹配到的请求进行转发,我们还是以开始的配置举例(稍微改动一下)。
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
weight: 30
- destination:
host: reviews
subset: v3
weight: 70
- route:
- destination:
host: reviews
subset: v1
通过上节的匹配规则我们可以理解match中的匹配规则为请求头中的end-user的值为jason。当匹配这一条件时route路由生效,将请求的30%发送到reviews服务的v2版本上,另外70%发送到reviews服务的v3版本上。对未能匹配的请求路由到v1版本上。
这一转发需要搭配istio的另一个重要配置DR(DestinationRule)使用,DR种通过标签定义不同的pod服务。通过subset子集来完成请求的调用,这里按reviews服务的v1 v2两个pod理解就好。
简述:istio可以人工注入一些不可见的重定向规则,自定义的重定向规则在redirect关键字下。
理解了istio的vs工作模式那么我们接下来继续看istio的重定向功能,比较常见的使用场景:网站系统的网站地址发生了变化(并非服务器变化,只是访问地址的请求后缀变化
),要求使用之前的访问地址也能够进入网站,不影响旧用户的操作。这种情况下就很适合使用istio的重定向功能
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: cicdapi
spec:
hosts:
- cicdapi
http:
- match:
- uri:
prefix: /pipeline
redirect:
uri: /cicd/pipeline
authority: newcicd
以上的请求对cicdapi服务的/pipeline请求都会被重定向到newcicd服务的/cicd/pipeline上
简述:istio可以在请求发送给目标服务之前对请求信息进行改写,这个改写过程是对客户端及服务端都不可见的。重写与重定向很像。
关键字:rewrite
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: cicdapi
spec:
hosts:
- cicdapi
http:
- match:
- uri:
prefix: /pipeline
rewrite:
uri: /cicd/pipeline
简述:很多时候http请求发生异常,重试都是解决异常的最直接,最简单的办法,尤其是环境比较复杂的情况下,可以提高总体的服务质量,但是这个重试逻辑如果放在客户端进行调度就过于不规范,不便于管理。istio可以支持这种重试的自动调度。
关键字:retry
这里可能不包括部分返回码,如404,405
)apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: cicdapi
spec:
hosts:
- cicdapi
http:
- route:
- destination:
host: cicdapi
retries:
attempts: 5
perTryTimeout: 3s
retryOn: 5xx,connect-failure
简述:流量复制是指在流量需要发送到某个服务时,将这个请求流量复制一份到一个指定的服务上,如下图。可以将生产系统的流量复制到一个需要更新的新版本服务上,这样完全不会对生产系统产生影响,这里只复制了一份流量,数据面代理只需要住原来的流量就可以了。
关键字:mirror
例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: portal-web
spec:
hosts:
- portal-web
http:
- route:
- destination:
host: portal-web
subset: v1.0.15
mirror:
host: portal-web
subset: v1.0.16
简述:除了转发重试这些常用的http请求操作,istio还支持故障注入。主要用于测试时主动模拟一些异常场景,比如跨服务请求超时,访问中发生错误等情况。
在istio中故障注入主要分为两种
……
- route:
- destination:
host: portal-web
subset: v1.0.15
- fault:
delay:
percentage:
value: 1.5
fixedDelay: 10s
表示对portal-web服务的请求的百分之1.5会被注入10s的延迟
……
- route:
- destination:
host: portal-web
subset: v1.0.15
- fault:
delay:
percentage:
value: 1.5
httpStatus: 500
对portal-web服务的请求的百分之1.5会被模拟返回500的异常。
其实当了解了vs的大部分功能之后,我们可以看到vs的作用其实与k8s的service的作用基本是一致的,只是vs是用来修饰service的服务,可以调整、组合、拼接service,将多个service拼装成一个大的,富有规则的service。
在我们刚刚查看VirtualService时候经常能看到这样一段配置
- route:
- destination:
host: portal-web
subset: v1.0.15
之前说这段配置指的是将流量发送给portal-web的v1.0.15的版本,这样说是为了方便理解。实际上这种说法是不严谨的,这段配置真实代表的含义是将请求转发给portal-web服务的destinationRule的v1.0.15的子集。
DestinationRule配置样例:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: cicdpai
spec:
host: cicdapi
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
destinationRule经常与virtualService一起使用(dr是配合vs一起使用的,但是vs并不要求一定需要使用dr,如果不使用dr,vs会直接使用service来负载调用对应的pod
),virtualService用来修饰满足什么条件后被哪个后端处理。而destinationRule描述的是这个请求到达某个后端后该怎么去处理。
简述:vs设置服务的访问规则,具体请求服务时的规则由dr来决定。
关键属性:
(1)host:必选字段,表示规则的使用对象,对应的也是k8s中的service。域名解析方式与之前的host配置一致。
(2)trafficPolicy:规则的内容定义,包括负载均衡,连接池策略,异常点检查等内容。
(3)exportTo:Istio 1.1版本后新增的特性,用于控制DestinationRule跨命名空间的可见性,这样就能控制在一个命名空间下定义的资源对象是否可以被其他命名空间下的Sidecar执行。如果不做赋值代表全命名空间都可见。支持“.”
代表当前命名空间可见。"*"
代表全命名空间可见。
(4)subsets:代表一个服务的子集,一般代表一个服务的版本,与vs结合使用。每个子集都是通过label来匹配对应的pod,在istio的使用要求中建议用户为每个pod分配app、version两个标签。所以subset一般以version来划分,但这并不是硬性限制。
简述:当subset中可以匹配到多个pod时可以通过istio自身的负载均衡策略将请求分配。
简述:通过连接池管理可以配置阈值来放置一个服务的失败影响到整个应用。istio的连接池可以配置tcp流量、http流量治理
简述:异常点检查就是定期考察被访问的服务实例的工作情况,如果连续出现访问异常,则将服务实例标记为异常并进行隔离,在一段时间内不为其分配流量,过一段时间被移除的实例会被解除移除,尝试请求,如果访问失败会进行更长实际胺的隔离,这也是istio的熔断功能。
参数配置:
连续
错误次数,默认为5,对于http服务返回502,503,504的返回码会认为服务异常。例:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: cicdapi
namespace: paas
spec:
host: cicdapi
trafficPolicy:
connectionPool:
tcp:
maxConnections: 80
connectTimeout: 25ms
http:
http2MaxRequest: 800
maxRequestsPerConnection: 10
outlierDetection:
consecutiveErrors: 5
interval: 4m
baseEjectionTime: 10m
maxEjectionPercent: 30
检查4分钟内cicdapi服务的异常情况,连续出现5次连接异常的服务实例会被隔离10分钟,被隔离的服务数量不能超过30%。达到十分钟后实例会重新接受请求,如果依然不能正常工作会被隔离20分钟
简述:当我们熟悉以上的连接池配置后,实际端口配置也没有什么特殊的地方,实际上就是为了某些端口配置一些特殊规则,比如最大连接数等
例:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: cicdapi
namespace: paas
spec:
host: cicdapi
trafficPolicy:
connectionPool:
tcp:
maxConnections: 80
portLevelSettings:
- port:
number: 8081
connectionPool:
tcp:
maxConnections: 100
cicd服务的最大连接数为80,但8081端口单独配置了最大连接数为100
简述:subset主要作用就是通过label标签配置真实的后端服务。virtualService中通过制定subset的name来引用对应的服务。
name:必选字段,subset的名字,通过virtualService引用subset的时候就是通过name来引用的
labels:服务标签,通过标签来引用真实的后端服务,最常用的标签为version标签
trafficPolicy:应用到这个subset的流量策略
例:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: cicdapi
namespace: paas
spec:
host: cicdapi
subset:
- name: v2
labels:
version: v2
trafficPolicy:
connectionPool:
tcp:
maxConnections: 80
dr的作用主要就是配置目标服务的匹配方式和负载均衡、熔断的服务治理方式。
之前的配置不论是vs还是dr的配置都是针对服务间的访问做的样例,没有针对过外部请求访问容器服务的样例。这种请求都需要通过istio的服务网关来配置。
样例:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: cicdfront-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "cicdfront.com"
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: cicd-front
spec:
hosts:
- frontend
- cicdfront.com
gateways:
- cicdfront-gateway
- mesh
http:
- route:
- destination:
host: cicd-front
port:
number: 8080
Gateway一般需要与virtualService结合使用,Gateway定义了服务从外面怎么访问,virtualService定义了匹配到内部服务怎么流转。
关键配置:
selector:必选字段,表示Gateway负载,为入口处的Envoy运行的pod标签
server:必选字段,表示开放的服务列表
简述:server定义了服务的访问入口
例:
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "cicdfront.com"
简述:将网格外的服务加入网络中,像网格内的服务一样管理,实际上就是将不归属istio自动注入的服务加入到istio的服务发现。
配置示例
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: cicdfront-entry
spec:
hosts:
- www.cicddb.com
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
location: MESH_EXTERNAL
重要参数:
但在使用中会发现这几种问题
hosts
,在k8s集群中 ,这个hosts是我们服务的长短域名,也就是service的名称。所以在很大程度来讲,istio都是基于service在工作。但是istio没有图形界面提供功能配置,不论是vs,dr,gw都是需要通过yaml配置的。这种配置就不能限制用户的一些误操作,比如对一个服务配置误配置了两个vs,那么哪个会是有效的vs?对一个服务配置了两个dr,那么哪个会是有效的dr?前面提过istio在1.1版本之后新增了exportTo属性,代表当前配置能否支持跨namespace,默认都是允许跨namespace生效的,这样会不会出现误引用的情况?所以在使用时还是建议封装istio的yaml拼装功能,通过页面进行控制,防止误配置yaml。
istio会进行服务间的流量治理,实现方式是通过iptables进行流量拦截,这样使用时为了让入口服务也能被istio治理就必须使用istio的入口网关Gateway。这样平台使用时就不能直接为用户提供route的方式访问平台。需要使用gateway进行包装才行。但并不是所有服务都需要进行包装,只有需要在集群外直接访问的服务需要进行这个包装。(大部分都是前台服务才需要进行这个步骤:浏览器 --> cicd-front --> cicd-api,这种情况下就需要为cicdfront生成入口网关,用户需要通过入口网关访问cicdfront才能治理这部分流量
)
集群内不能直接访问集群外的url