在使用gRPC(基于HTTP/2)的Kubernetes服务时,到目标的单个连接将在一个Pod处终止。如果从客户端发送了多条消息,则所有消息将由该Pod处理,从而导致负载不均衡。本文通过示例介绍gRPC服务间负载不均衡的问题以及如何实现负载均衡。
背景信息
gRPC是一种基于HTTP/2的服务通信协议,使用基于Protocol Buffers(简称为PB)格式的服务定义。服务之间调用的数据可以被序列化为较小的二进制格式进行传输。使用gRPC,可以从.proto文件生成多种语言的代码,这也就使得gRPC成为了多语言微服务开发的最佳选择之一。
使用基于HTTP/1.1的RPC时,一个简单的TCP负载均衡器足以胜任,因为这些连接都是短暂的,客户端将尝试重新连接,不会保持与运行中的旧Pod之间的连接。但是使用基于HTTP/2的gRPC时,TCP连接保持打开状态,这样将保持连接到即将失效的Pod,亦或使集群失去平衡。
前提条件
已创建test-grpc命名空间。
准备工作
在test-grpc命名空间下,部署gRPC服务的服务端istio-grpc-server。
使用以下内容,创建istio-grpc-server.yaml。
执行以下命令,部署istio-grpc-server。
kubectl apply -n test-grpc -f istio-grpc-server.yaml
在test-grpc命名空间下,部署gRPC服务的客户端istio-grpc-client。
使用以下内容,创建istio-grpc-client.yaml。
执行以下命令,部署istio-grpc-client。
kubectl apply -n test-grpc -f istio-grpc-client.yaml
验证默认的负载均衡效果
本示例演示在Kubernetes下gRPC服务间调用的负载不均衡问题。
执行以下命令,登录到客户端Pod容器。
kubectl exec -it -n test-grpc deployment/istio-grpc-client -it -- sh
进入容器后,重复多次执行以下命令。
/bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100
预期输出:
2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2024/02/07 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd
可以看到所有的请求都指向了一个Pod。由此可见,从客户端发送了所有消息都由一个Pod处理,从而导致负载不均衡。
配置高级流量管理
本示例说明如何通过ASM实现负载均衡。
为命名空间开启Waypoint
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
单击从Kubernetes集群同步自动注入,在弹出框中勾选数据面集群的名称,单击确定。在test-grpc命名空间的数据面模式列,单击切换为Ambient Mesh模式,在弹出框中单击确定。
部署Waypoint。
kubectl apply -n test-grpc -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: waypoint spec: gatewayClassName: istio-waypoint listeners: - name: mesh port: 15008 protocol: HBONE EOF
为test-grpc命名空间开启waypoint。
kubectl label namespace test-grpc istio.io/use-waypoint=waypoint --overwrite
验证负载均衡
执行以下命令,登录到客户端Pod容器。
kubectl exec -it -n test-grpc istio-grpc-client-dd56bcb45-zhfsg -c istio-grpc-client sh
进入容器后,执行以下命令。
/bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100
预期输出:
2024/02/07 14:53:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:53:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:53:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:53:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:53:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:53:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:53:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:53:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:53:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:53:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:53:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:53:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62
可以看到所有的请求分别指向了对应的2个Pod,比例接近于50:50,即负载均衡已生效。
配置服务网格ASM实例的控制平面。
使用以下内容,在test-grpc命名空间创建目标规则。具体操作,请参见管理目标规则。
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: dr-istio-grpc-server spec: host: istio-grpc-server trafficPolicy: loadBalancer: simple: ROUND_ROBIN subsets: - name: v1 labels: version: "v1" - name: v2 labels: version: "v2"
使用以下内容,在test-grpc命名空间创建虚拟服务。具体操作,请参见管理虚拟服务。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: vs-istio-grpc-server spec: hosts: - "istio-grpc-server" http: - match: - port: 8080 route: - destination: host: istio-grpc-server subset: v1 weight: 90 - destination: host: istio-grpc-server subset: v2 weight: 10
执行以下命令,登录到客户端Pod容器。
kubectl exec -it -n test-grpc istio-grpc-client-dd56bcb45-zhfsg -c istio-grpc-client sh
进入容器后,执行以下命令。
/bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100
预期输出:
2024/02/07 14:56:16 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm 2024/02/07 14:56:16 Hello world from istio-grpc-server-v1-546d9876c4-tndsm
可以看到所有的请求分别指向了对应的2个Pod,但比例接近于90:10。
调整虚拟服务的权重,查看调用的不同结果。
登录ASM控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在虚拟服务页面上方,选择test-grpc命名空间,在操作列,单击vs-istio-grpc-server对应的查看YAML,在编辑对话框中,调整虚拟服务的权重,然后单击确认。
修改内容如下:
route: - destination: host: istio-grpc-server subset: v1 weight: 0 - destination: host: istio-grpc-server subset: v2 weight: 100
执行以下命令,登录到客户端Pod容器。
kubectl exec -it -n test-grpc istio-grpc-client-dd56bcb45-zhfsg -c istio-grpc-client sh
进入容器后,执行以下命令。
/bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100
预期输出:
2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62 2024/02/07 14:58:30 Hello world from istio-grpc-server-v2-66d9b8847-99v62
可以看到所有的请求都指向了v2版本对应的Pod。