8.1 整体介绍

上一章

8.3 连接池

下一章

更多图书

8.2 负载均衡

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服务时,只会得到同一个版本的服务响应结果。