Istio虚拟服务 (Virtual Service)
1、概述
虚拟服务(Virtual Service) 和目标规则(Destination Rule) 是 Istio 流量路由功能的关键拼图。虚拟服务让您配置如何在服务网格内将请求路由到服务,这基于 Istio 和平台提供的基本的连通性和服务发现能力。每个虚拟服务包含一组路由规则,Istio 按顺序评估它们,Istio 将每个给定的请求匹配到虚拟服务指定的实际目标地址。您的网格可以有多个虚拟服务,也可以没有,取决于您的使用场景。
2、有了 Kubernetes Service,为什么还需要 Istio Virtual Service
简单来说,基于 Kubernetes Service,只可以实现简单的流量负载均衡,如果想实现基于HTTP Header,负载百分比等等复杂的流量控制就无从下手了,Istio Vistrual Service在原本 Kubernetes Service 的功能之上,提供了更加丰富的路由控制。
3、virtualservices.networking.istio.io资源结构
通过kubectl get customresourcedefinitions.apiextensions.k8s.io virtualservices.networking.istio.io -o yaml命令查看virtualservices资源的apiGroups、apiVersions 和 resources 以及资源的 scope信息,可以看到资源scope是Namespaced。
spec:
conversion:
strategy: None
group: networking.istio.io
names:
categories:
- istio-io
- networking-istio-io
kind: VirtualService
listKind: VirtualServiceList
plural: virtualservices
shortNames:
- vs
singular: virtualservice
scope: Namespaced
.....
4、Virtual Service示例
有两个Deployment(nginx 及 httpd),通过Service关联到一起,通过访问Service只能做到简单的负载均衡,通过实验发现 nginx 和 httpd 流量各自在 50% 左右。

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 #name可以随便取值
spec:
hosts:
- web-service #hosts值必须是kubernetes里面的服务名
http:
- route:
- destination:
host: nginx-service #k8s服务名
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 观察执行结果,可以测试出nginx流量在80%左右,httpd 流量在20%左右。
这里解释下 wget -q -O -含义:
-q的含义是:--quiet,安静模式,无信息输出。
-O的含义是把后面网址下载后,改成一个指定的名称,如果后面没有跟着一个名字,而是“-”,则表示将下载后的内容输出到标准输出,也就是输出到屏幕上。
-qO-的含义:把下载的内容输出到标准输出
5、Vistrual Service配置详解
除了权重之外,还有条件匹配,很多场景下,需要针对不同的用户已提供个性化的服务等,例如针对地理位置、是否为VIP等等,那就需要对http流量进行识别匹配,示例如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: web-vs
spec:
hosts:
- web-service
http:
- match:
- headers:
end-user:
exact: jason
uri:
prefix: "/health"
ignoreUriCase: true
route:
- destination:
host: httpd-service
- route:
- destination:
host: nginx-service
5.1 hosts字段
使用 hosts 字段列举虚拟服务的主机——即用户指定的目标或是路由规则设定的目标。这是客户端向服务发送请求时使用的一个或多个地址。
hosts: - web-service #hosts值如果是域名形式必须是kubernetes里面的服务名
在Kubernetes里面虚拟服务主机名是k8s服务clusterIp或者k8s服务的短名称(Pod DNS配置文件里面的search域会自动拼成"服务名.namespace.svc.cluster.local"形式),隐式或显式地指向一个完全限定域名(FQDN)。您也可以使用通配符(“*”)前缀,让您创建一组匹配所有服务的路由规则。虚拟服务的 hosts 字段实际上不必是 Istio 服务注册的一部分,它只是虚拟的目标地址。这让您可以为没有路由到网格内部的虚拟主机建模。
5.2 路由规则(match 字段、destination字段)
match 字段
在 http 字段包含了虚拟服务的路由规则,用来描述匹配条件和路由行为,它们把 HTTP/1.1、HTTP2 和 gRPC 等流量发送到 hosts 字段指定的目标(您也可以用 tcp 和 tls 片段为 TCP 和未终止的 TLS 流量设置路由规则)。一个路由规则包含了指定的请求要流向哪个目标地址,具有 0 或多个匹配条件,取决于您的使用场景。
示例中的第一个路由规则有一个条件,因此以 match 字段开始。在本例中,您希望此路由应用于来自 ”jason“ 用户的所有请求,所以使用 headers、end-user 和 exact 字段选择适当的请求。
- match:
- headers:
end-user:
exact: jason
路由规则优先级
路由规则按从上到下的顺序选择,虚拟服务中定义的第一条规则有最高优先级。本示例中,不满足第一个路由规则的流量均流向一个默认的目标,该目标在第二条规则中指定。因此,第二条规则没有 match 条件,直接将流量导向nginx-service服务。
- route:
- destination:
host: nginx-service
路由规则的更多内容
正如上面所看到的,路由规则是将特定流量子集路由到指定目标地址的强大工具。您可以在流量端口、header 字段、URI 等内容上设置匹配条件。例如,这个虚拟服务让用户发送请求到两个独立的服务:ratings 和 reviews,就好像它们是 http://bookinfo.com/ 这个更大的虚拟服务的一部分。虚拟服务规则根据请求的 URI 和指向适当服务的请求匹配流量。
您可以使用 AND 向同一个 match 块添加多个匹配条件,或者使用 OR 向同一个规则添加多个 match 块。对于任何给定的虚拟服务也可以有多个路由规则。这可以在单个虚拟服务中使路由条件变得随您所愿的复杂或简单。匹配条件字段和备选值的完整列表可以在 HTTPMatchRequest 参考中找到。
另外,使用匹配条件您可以按百分比”权重“分发请求。这在 A/B 测试和金丝雀发布中非常有用:
- 添加或删除 header。
- 重写 URL。
- 为调用这一目标地址的请求设置重试策略。
想了解如何利用这些操作,查看 HTTPRoute 参考。
6、总结
在Kubernetes集群里面可以通过Istio Vistrual Service实现基于HTTP Header,负载百分比等等复杂的流量控制,相比于Kubernetes Service,它提供了更加丰富的路由控制。Vistrual Service资源scope是Namespaced级别的,Pod只有被Istio注入才可以接收到来自 Pilot 有关 Virtual Service 和 Destination Rule 的配置信息,才可以保证流量接管生效。Vistrual Service路由规则按从上到下的顺序选择,虚拟服务中定义的第一条规则有最高优先级,在生产环境中建议提供一个默认的“无条件”或基于权重的规则作为每一个虚拟服务的最后一条规则,这样才能确保流经虚拟服务的流量至少能够匹配一条路由规则。
参考:https://istio.io/latest/zh/docs/concepts/traffic-management/
浙公网安备 33010602011771号