Istio通过设置DestinationRule来指定服务的负载均衡策略,Istio提供了两种常用的负载均衡策略:简单负载均衡(simple)和一致性哈希负载均衡(consistentHash)。可以为服务设置默认的负载均衡策略,也可以在单独的服务子集中设置负载均衡策略,服务子集中的设置会覆盖服务设置的默认负载均衡策略。我们还可以设置端口级别的负载均衡策略(portLevelSettings),可以为服务设置默认的端口级别的负载均衡策略。当然,我们也可以在单独的服务子集上设置端口级别的负载均衡策略。
1.简单负载均衡
简单负载均衡策略提供了如下4种负载均衡算法:
·轮询(ROUND_ROBIN):把请求依次转发给后端健康实例,这是默认算法。
·最少连接(LEAST_CONN):把请求转发给活跃请求最少的后端健康实例,此处的活跃请求数是Istio自己维护的,是Istio调用后端实例且正在等待返回响应的请求数。由于服务实例可能还有其他客户端在调用,没有经过Istio统计,所以Istio维护的活跃请求数并不是此时实例真正的活跃请求数。由于Envoy与服务部署在一个Pod中,并拦截所有流量,因此一般情况下,可以把Istio维护的活跃请求数看成是服务实例的真正活跃请求数。
·随机(RANDOM):把请求随机转发给后端健康实例。
·直连(PASSTHROUGH):将连接转发到调用方请求的原始IP地址,而不进行任何形式的负载平衡,这是高级用法,一般情况下不会使用。
使用示例:
1 apiVersion: networking.istio.io/v1alpha3 2 kind: DestinationRule 3 metadata: 4 name: service-go 5 spec: 6 host: service-go 7 trafficPolicy: 8 loadBalancer: 9 simple: ROUND_ROBIN 10 subsets: 11 - name: v1 12 labels: 13 version: v1 14 - name: v2 15 labels: 16 version: v2 17 trafficPolicy: 18 loadBalancer: 19 simple: LEAST_CONN 20 portLevelSettings: 21 - port: 22 number: 80 23 loadBalancer: 24 simple: RANDOM
第7~9行定义了默认的负载均衡策略为轮询方式。
第17~19行定义了对于名称为v2的实例子集负载均衡策略为最少连接方式。
第20~24行定义了端口级别的负载均衡策略,指定80端口的负载均衡策略为随机方式。
2.一致性哈希负载均衡
一致性哈希负载均衡策略只适用于使用HTTP类协议(HTTP 1.1/HTTPS/HTTP2)的请求,可以基于请求头、Cookie或者来源IP做会话保持,让同一用户的请求一直转发到后端同一实例,当实例出现故障时会选择新的实例。当添加删除新实例时,会有部分用户的会话保持失效。
使用示例:
1 apiVersion: networking.istio.io/v1alpha3 2 kind: DestinationRule 3 metadata: 4 name: service-go 5 spec: 6 host: service-go 7 trafficPolicy: 8 loadBalancer: 9 consistentHash: 10 httpHeaderName: x-lb-test 11 subsets: 12 - name: v1 13 labels: 14 version: v1 15 - name: v2 16 labels: 17 version: v2
第7~10行定义了默认的负载均衡策略为一致性哈希,基于x-lb-test请求头进行一致性哈希负载均衡。
【实验】
1)创建测试Pod:
$ kubectl apply -f kubernetes/dns-test.yaml
2)创建service-go服务的路由规则:
$ kubectl apply -f istio/route/virtual-service-go.yaml
3)访问service-go服务:
$ kubectl exec dns-test -c dns-test -- curl -s -H "X-lb-test: 1" http://service-go/env {"message":"go v1"} $ kubectl exec dns-test -c dns-test -- curl -s -H "X-lb-test: 1" http://service-go/env {"message":"go v2"}
在没有创建一致性哈希负载均衡规则时访问service-go服务,同样的请求头,会落到service-go服务的v1和v2两个版本。
4)创建一致性哈希负载均衡规则:
$ kubectl apply -f istio/resilience/destination-rule-go-lb-hash.yaml
5)访问service-go服务:
$ kubectl exec dns-test -c dns-test -- curl -s -H "X-lb-test: 1" http://service-go/env {"message":"go v2"} $ kubectl exec dns-test -c dns-test -- curl -s -H "X-lb-test: 2" http://service-go/env {"message":"go v2"} $ kubectl exec dns-test -c dns-test -- curl -s -H "X-lb-test: 3" http://service-go/env {"message":"go v1"}
在创建一致性哈希负载均衡规则后访问service-go服务,同样的请求头,只会落到service-go服务的同一个版本上。
6)清理:
$ kubectl delete -f kubernetes/dns-test.yaml $ kubectl delete -f istio/route/virtual-service-go.yaml $ kubectl delete -f istio/resilience/destination-rule-go-lb-hash.yaml
总结: 从以上的实验结果可以看出,实验部署了两个版本的service-go服务实例,每个版本一个Pod,默认情况下访问service-go服务会轮询地转发到后端Pod上,因此多次访问会看到两个版本的响应结果;当配置了一致性哈希负载均衡规则以后,以固定的X-lb-test请求头值请求时,多次访问只能获取到同一个版本的服务实例响应信息。
实验结果可能与上面的结果并不完全一致,但是结论是一致的,当请求携带同样的X-lb-test请求头访问service-go服务时,只会得到同一个版本的服务响应结果。