Vistrual Service & Destination R
虚拟服务(Vistrual Service)是 Istio 重要的资源对象之一,作用是将流量路由到网格中的服务。支持基于权重、http header条件等优先级的路由,比Kuberentes service对于流量的管控更加的丰富,颗粒度更加精细。
有了 Kubernetes Service,为什么还需要 Istio Vistrual Service
简单来说,基于 Kubernetes Service,只可以实现简单的流量负载均衡,如果想实现基于HTTP Header,负载百分比等等复杂的流量控制就无从下手了,Istio Vistrual Service在原本 Kubernetes Service 的功能之上,提供了更加丰富的路由控制。
VirtualHost
-
VirtualHost
-
几个关键术语
-
Service:服务注册表上用于标识一组应用实例的独立单元,列如Kubernetes上的Service资源对象
-
Service Version:Service的一至多个版本(通常称为subset),通常表现为CD场景中,同时运行着的同一应用的不版本的实例组合,用于支撑实现A/B测试、Canary发布等,以及相应的流量分配机制;
-
Host:客户端请求报文中的“主机”,用于支撑基于虚拟主机的流量过滤;
-
-
VirtualHost的定义:一组关乎到特定“主机(客户端访问的目标地址或主机名)”的流量路由规则
-
VirtualService配置要点
- VirtualService的关键字段
-
hosts: 必选字段,用于指定流量请求的目标,可以是一个DNS名称或IP地址;
- DNS名称可以使用通配符,也可以使用短格式的Service名称;
-
gateways:指定应用流量规则的Gateway资源,在VirtualService上使用gateways字段时遵循如下规则
-
仅应用于网格内的东西流量时,应省略gateways字段;
-
仅用于引入网格外的流量,为gateways字段赋予合适的值(Gateway名称列表)即可
-
客户端源自网格外部
-
Gateway负责接入这部分流量,VirtualService负责将这部分流量完成在网格内的路由
-
-
同时用于网格内和网格外的流量时,需要将gateways字段的列表值的其中一项指定为“mesh”
- 客户端既可源自网格外部,也可以是网格内部的流量
-
-
http: 配置http协议的流量管理机制的有序列表,其配置框架称为HTTPRoute
-
tls:用于处理非终结的TLS和HTTPS流量的有序列表,其配置框架称为TLSRoute
-
tcp:管理四层的TCP流量的有序列表,其配置框架称为TCPRoute
-
VirtualService配置生效示意图
imageHTTP路由配置(HTTPRoute)
-
virtualservice.http配置如何处理http流量
-
服务的端口协议是HTTP、HTTP2和GRPC,即在服务的端口名中包含http-、http2-和grpc-等;
-
Gateway的端口协议是HTTP、HTTP2和GRPC,或者Gateway终结了TLS;
-
ServiceEntry的端口协议是HTTP、HTTP2和GRPC;
-
-
路由机制及服务韧性等相关的配置,即满足HTTPMatchRequest条件的流量可以做如下处理
-
路由到指定目标(HTTPRouteDestination)
-
执行重定向(HTTPRedirect)
-
URL重写(HTTPRewrite)
-
请求重试(HTTPRetry)
-
故障注入(HTTPFaultInjection)
-
跨站资源引用(CorsPolicy)
-
VirtualService and HTTPRoute CRD
imageHTTPRoute配置示例
示例一
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v2
url重写示例
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: demoapp
spec:
hosts:
- demoapp
http:
- name: rewrite
match:
- uri:
prefix: /canary
rewrite:
uri: /
route:
- destination:
host: demoapp
subset: v11
- name: redirect
match:
- uri:
prefix: "/backend"
redirect:
uri: /
authority: backend
port: 8082
- name: default
route:
- destination:
host: demoapp
subset: v10
fault-injection示例
kind: VirtualService
metadata:
name: demoapp
spec:
hosts:
- demoapp
http:
- name: canary
match:
- uri:
prefix: /canary
rewrite:
uri: /
route:
- destination:
host: demoapp
subset: v11
fault:
abort:
percentage:
value: 20
httpStatus: 555
- name: default
route:
- destination:
host: demoapp
subset: v10
fault:
delay:
percentage:
value: 20
fixedDelay: 3s
参考文档
https://istio.io/latest/zh/docs/reference/config/networking/virtual-service/
通过例子来理解
有两个Deployment(nginx 及 httpd),通过Service关联到一起,通过访问Service只能做到简单的负载均衡,通过实验发现 nginx 和 httpd 流量各自在 50% 左右。
image.png
Deployment & Service
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
server: web
spec:
containers:
- image: 'nginx:latest'
name: nginx-deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: httpd
name: httpd-deployment
spec:
replicas: 1
selector:
matchLabels:
app: httpd
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: httpd
server: web
spec:
containers:
- image: 'httpd:latest'
name: httpd-deployment
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: httpd-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: httpd
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
server: web
type: ClusterIP
如果想实现更加细颗粒度的流量管控,通过引入Istio Vistrual Service 非常简单的就实现复杂的流量管理。
VirtualService 根据 Destination 进行调度,并且设置相关的负载百分比实现精准的控制。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: web-vs
spec:
hosts:
- web-service
http:
- route:
- destination:
host: nginx-service
weight: 80
- destination:
host: httpd-service
weight: 20
通过客户端测试以上的实验,请留意客户端也必须经过 Istio 注入,因为只有客户端被 Istio 注入才可以接收到来自 Pilot 有关 Virtual Service 和 Destination Rule 的配置信息,才可以保证流量接管生效。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: client-deployment
name: client-deployment
spec:
replicas: 1
selector:
matchLabels:
app: client-deployment
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: client-deployment
spec:
containers:
- image: 'busybox:latest'
name: client-deployment
command: [ "/bin/sh", "-c", "sleep 3600"]
进入客户端容器执行 wget -q -O - web-service
观察执行结果
Vistrual Service 条件匹配
很多场景下,需要针对不同的用户已提供个性化的服务等(提前内测新版本),例如针对地理位置、是否为VIP等等,那就需要对 httpd 流量进行识别匹配。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: web-vs
spec:
hosts:
- web-service
http:
- match:
- headers:
end-user:
exact: carryyip
uri:
prefix: "/health"
ignoreUriCase: true
route:
- destination:
host: httpd-service
- route:
- destination:
host: nginx-service
基于 HttpMatchRequest,路由规则从上到下进行优先级排序,在生产环境中建议使用一个无条件的规则作为最后规则,确保流量始终会匹配到最少一条规则,防止意外情况的方式。
路由规则从 match 关键字开始匹配,可以使用精确 exact 和 前缀 prefix 或者 正则表达式进行不同场景下的匹配。
Destination Rule
目标规则(Destination Rule)是 Istio 重要的资源对象之一,它不能独自使用,必须跟 Virtual Service 共同发挥作用,作用是将流量标记分组并路由到具体服务。
Destination Rule 还可以做什么
通常在生产场景下,用使用 Destination Rule 对用户进行身份、地址位置等条件的识别后的流量路由,例如部分用户优先享用新版本,则可以通过HTTP Header附加相关的字段进行识别,路由到新版本的服务上。或者在版本更新的时候,使用灰度发布,对新旧版本标记子集,按照不同的负载百分比进行调整逐步迭代。
DestinationRule配置要点
-
DestinationRule用于配置路由完成之后的应用于服务的流量策略,即配置如何将流量调度至上游端点,同时也是为VirtualService的Destination指定的目标提供具体的定义和实现;主要包括以下配置项
-
负载均衡配置
-
Sidecar连接池
-
异常值检测相关的配置,即异常端点驱逐机制
-
-
DestinationRule的关键字段
-
host:必选字段,指定规则的适用对象,可以使用短域名;可用值是在服务注册中心注册的服务名,即网格内的服务或者是以ServiceEntry注册的网格外的服务;
-
trafficPolicy:具体的规则内容,包括负载均衡、连接池策略和异常值检测;
-
subsets:服务的子集定义,通常一个子集用于定义一个服务版本;
-
exportTo:用于控制DestinationRule跨名称空间的可见性,即控制一个名称空间下定义的DestinationRule资源对象是否可被其它名称空间下的Sidecar执行;
-
“.”:表示仅应用于当前名称空间;
-
“*”:表示应用于所有名称空间;
-
-
-
Subset:服务子集
-
name:子集名称、
-
labels:子集上的标签
-
trafficPolicy:应用于当前子集的流量策略
-
-
TrafficPolicy主要包含如下几项重要配置
-
loadBalancer:定义使用的负载均衡器,即负载均衡算法;
-
简单负载均衡:
- ROUND_ROBIN、LEAST_CONN、RANDOM和PASSTHROUTH
-
一致性哈希:consistentHash仅对HTTP协议有效,它支持基于httpHeaderName、httpCookie、useSoureIp进行hash计算,并能够通过minimumRingSize指定Hash环大小;
-
httpHeaderName
-
httpCookie
-
useSourceIp
-
httpQueryParameterName
-
minimumRingSize
-
-
localityLbSetting:位置权重负载均衡相关的设置,基于Client和Server端Pod上的annotation时设置
-
常用参数:distribute、failover、failoverPriority、enabled
-
常用Annotation:topology.kubernetes.io/region、topology.kubernetes.io/zone、topology.istio.io/subzone
-
-
-
outlierDetection:异常值检测;
-
consecutiveErrors:实例被驱逐前的连续错误次数和,默认值为5;
-
interval:驱逐的时间间隔,默认值为10秒,支持以时、分、秒和毫秒为单位;
-
baseEjectionTime:基准驱逐时长,具体时长取决于退避算法;
-
maxEjectionPercent:可被驱逐的最大实例比例,默认为10%;
-
minHealthPercent:启用异常值检测时要满足的最小健康状态实例比例,小于此比例,异常值检测将被禁用;默认为50%;
-
-
connectionPool:连接池配置
-
TCP连接池配置:
-
maxConnections:为上游服务的所有实例建立的最大连接数,默认为1024;
-
connectTimeout:TCP连接超时时长;对于HTTP协议来说,它仅适用于HTTP/1;
-
tcpKeepalive:TCP keepalives机制,通过定期给发送一个keepalive探测报文来判断连接是否可用;
-
-
HTTP连接池配置
-
http1MaxPendingRequests:允许挂起的最大HTTP请求数,默认为1024,仅适用于HTTP/1.1;
-
http2MaxRequests:允许的HTTP/2最大请求数,默认为1024;HTTP/1.1的由maxConnections设置即能实现;
-
maxRequestsPerConnection:每连接的最大请求数,默认为无限制,而1则表示禁用Keep-alive;
-
maxRetries:最大重试次数,默认为3;
-
idleTimeout:空闲超时时长;
-
-
-
PortTrafficPolicy:流量策略要应用的目标端口;
-
DestinationRule配置生效示意图
imageDestinationRule CRD
imageDestinationRule配置示例
子集示例
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: demoapp
spec:
host: demoapp
subsets:
- name: v10
labels:
version: v1.0
- name: v11
labels:
version: v1.1
负载均衡
kind: DestinationRule
metadata:
name: demoapp
spec:
host: demoapp
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
subsets:
- name: v10
labels:
version: v1.0
trafficPolicy:
loadBalancer:
consistentHash:
httpHeaderName: X-User
- name: v11
labels:
version: v1.1
示例三
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: bookinfo-ratings
spec:
host: ratings.prod.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
subsets:
- name: testversion
labels:
version: v3
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
参考文档
https://istio.io/latest/zh/docs/reference/config/networking/destination-rule/
通过例子来理解
有两个Deployment(nginx 及 httpd),通过Service关联到一起,通过访问Service只能做到简单的负载均衡,通过实验发现 nginx 和 httpd 流量各自在 50% 左右。
image.pngDeployment & Service
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
server: web
spec:
containers:
- image: 'nginx:latest'
name: nginx-deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: httpd
name: httpd-deployment
spec:
replicas: 1
selector:
matchLabels:
app: httpd
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: httpd
server: web
spec:
containers:
- image: 'httpd:latest'
name: httpd-deployment
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
server: web
type: ClusterIP
如果想实现更加细颗粒度的流量管控,通过引入Istio Vistrual Service 及 Destination Rule,非常简单的就实现复杂的流量管理。
DestinationRule 根据标签将流量分成不同的子集,已提供 VirtualService 进行调度,并且设置相关的负载百分比实现精准的控制。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: web-dr
spec:
host: web-svc
subsets:
- name: httpd
labels:
app: httpd
- name: nginx
labels:
app: nginx
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: web-vs
spec:
hosts:
- web-service
http:
- route:
- destination:
host: web-service
subset: nginx
weight: 80
- destination:
host: web-service
subset: httpd
weight: 20
通过客户端测试以上的实验,请留意客户端也必须经过 Istio 注入,因为只有客户端被 Istio 注入才可以接收到来自 Pilot 有关 Virtual Service 和 Destination Rule 的配置信息,才可以保证流量接管生效。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: client-deployment
name: client-deployment
spec:
replicas: 1
selector:
matchLabels:
app: client-deployment
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: client-deployment
spec:
containers:
- image: 'busybox:latest'
name: client-deployment
command: [ "/bin/sh", "-c", "sleep 3600"]
进入客户端容器执行 wget -q -O - web-service
观察执行结果
更丰富的流量策略
在生产环境中,应用到的流量策略不单单只是加权的负载均衡那么简单, Destination Rule 还支持 最小连接数、随机负载等等。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: web-dr
spec:
host: web-svc
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: httpd
labels:
app: httpd
- name: nginx
labels:
app: nginx
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
Destination Rule 字段解析
- host - 指的是 Kuberentes 中的服务
- subsets - 针对不同标签选择的流量子集
- loadBalancer - 负载均衡路由策略