如何优雅的在 Kubernetes 上对 gRPC 进行负载均衡

如何优雅的在 Kubernetes 上对 gRPC 进行负载均衡

来源:admin 发布时间:2022-08-16 09:36:17 点击数:


长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

Kubernetes 上的 gRPC 负载平衡

gRPC 是用于进程间通信的最流行的现代 RPC框架之一。是微服务架构的绝佳选择。而且,毫无疑问,部署微服务应用程序最流行的方式是 Kubernetes

Kubernetes 部署可以具有相同的后端实例,为许多客户端请求提供服务。KubernetesClusterIP 服务提供负载均衡的 IP 地址。但是这种默认的负载平衡不适用于 gRPC 开箱即用。

如果您使用 gRPC 并在 Kubernetes 上部署了许多后端,那么本文档适合您。

为什么要负载均衡?

大规模部署有许多相同的后端实例和许多客户端。每个后端服务器都有一定的容量。负载均衡用于在可用服务器之间分配来自客户端的负载。

在开始详细了解Kubernetes中的gRPC负载平衡之前,让我们先了解一下负载平衡的好处。

负载平衡有很多好处,其中一些是:

  • 故障容忍度:如果您的一个副本出现故障,那么其他服务器可以为该请求提供服务。
  • 增加的可伸缩性:您可以跨多个服务器分配用户流量,从而增加可伸缩性。
  • 提高吞吐量:您可以通过将流量分布到不同的后端服务器来提高应用程序的吞吐量。
  • 部署没有缺点:使用滚动部署技术可以实现无停机部署。

负载平衡还有许多其他好处。你可以在这里阅读更多关于负载均衡器的内容。

https://www.appviewx.com/education-center/load-balancer/

gRPC的负载均衡选项

gRPC中有两种类型的负载平衡选项——代理和客户端。

代理负载平衡

在代理负载均衡中,客户端将rpc发送给LB (load Balancer)代理。LBRPC调用分发到一个可用的后端服务器,该后端服务器实现为调用提供服务的实际逻辑。LB跟踪每个后端的负载,并实现公平分配负载的算法。客户端本身并不知道后台服务器。客户端是不可信的。这种体系结构通常用于面向用户的服务,其中来自开放互联网的客户端可以连接到服务器

客户端负载均衡

在客户端负载平衡中,客户端知道许多后端服务器,并为每个RPC选择一个后端服务器。如果客户端希望实现基于服务器负载报告的负载均衡算法。对于简单的部署,客户机可以在可用的服务器之间轮询请求。

有关gRPC负载均衡选项的更多信息,可以查看文章gRPC负载均衡。

https://grpc.io/blog/grpc-load-balancing/

与gRPC负载均衡相关的挑战

gRPCHTTP/2上工作。http/2上的TCP连接是长期存在的。一个连接可以使多个请求多路复用。这减少了与连接管理相关的开销。但这也意味着连接级负载平衡不是很有用。Kubernetes中的默认负载均衡是基于连接级负载均衡的。由于这个原因,Kubernetes的默认负载平衡不能与gRPC一起工作。

为了确认这个假设,让我们创建一个Kubernetes应用程序。这个应用程序由-组成

  • Server pod :Kubernetes部署带有三个gRPC服务端pod
  • Client pod: Kubernetes部署带有一个gRPC客户端pod
  • Service : ClusterIP Service,选择所有服务端pod
长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

创建服务端部署

要创建部署,请将以下代码保存在 YAML 文件中,例如 deployment-server.yaml,然后运行命令kubectl apply -f deployment-server.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpc-server
  labels:
    app: grpc-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: grpc-server
  template:
    metadata:
      labels:
        app: grpc-server
    spec:
      containers:
        - name: grpc-server
          image: techdozo/grpc-lb-server:1.0.0

这将创建一个具有三个副本的 gRPC 服务端。该GRPC服务端在端口上运行8001。要验证 pod是否成功创建,请运行命令kubectl get pods

NAME                           READY   STATUS    RESTARTS   AGE
grpc-server-6c9cd849-5pdbr    1/1    Running  0          1m
grpc-server-6c9cd849-86z7m    1/1    Running  0          1m
grpc-server-6c9cd849-mw9sb    1/1    Running  0          1m

您可以运行命令kubectl logs --follow grpc-server-<>查看日志。

创建服务

要创建服务,请将以下代码保存在 YAML 文件中,例如service.yaml,然后运行命令kubectl apply -f service.yaml

apiVersion: v1
kind: Service
metadata:
  name: grpc-server-service
spec:
  type: ClusterIP
  selector:
    app: grpc-server
  ports:
    - port: 80
      targetPort: 8001

ClusterIP服务提供负载平衡的 IP 地址。它在通过标签选择器匹配的pod 端点之间负载平衡流量。

Name:              grpc-server-service
Namespace:        default     
Selector:          app=grpc-server
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:      IPv4
IP:                10.96.28.234
IPs:              10.96.28.234
Port:              <unset>  80/TCP
TargetPort:        8001/TCP
Endpoints:        10.244.0.11:8001,10.244.0.12:8001,10.244.0.13:8001
Session Affinity:  None

如上所示,PodIP 地址是 - 10.244.0.11:8001,10.244.0.12:8001,10.244.0.13:8001。如果客户端调用端口 80上的服务,那么它将跨端点(PodIP 地址)对调用进行负载平衡。但对于gRPC 而言,情况并非如此,您很快就会看到。

创建客户端部署

要创建客户端部署,请将以下代码保存在 YAML 文件中,例如 deployment-client.yaml,然后运行命令 kubectl apply -f deployment-client.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpc-client
  labels:
    app: grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grpc-client
  template:
    metadata:
      labels:
        app: grpc-client
    spec:
      containers:
        - name: grpc-client
          image: techdozo/grpc-lb-client:1.0.0
          env:
            - name: SERVER_HOST
              value: grpc-server-service:80

gRPC 客户端应用程序在启动时使用一个通道在 10 个并发线程中对服务器进行 1,000,000 次调用。该SERVER_HOST环境变量指向DNS服务的grpc-server-service。在 gRPC 客户端上,通过将SERVER_HOST(serverHost)传递为:

ManagedChannelBuilder.forTarget(serverHost) .defaultLoadBalancingPolicy("round_robin") .usePlaintext() .build();

如果您检查服务器日志,您会注意到所有客户端调用仅由一个服务器 pod 提供服务。

使用无头服务的客户端负载平衡

您可以使用Kubernetes headless service进行客户端循环负载平衡。这种简单的负载平衡与 gRPC一起开箱即用。缺点是它没有考虑服务器上的负载。

什么是无头服务?

幸运的是,Kubernetes 允许客户端通过DNS查找来发现 pod IP。通常,当您对服务执行DNS 查找时,DNS 服务器会返回一个 IP — 服务的集群 IP。但是,如果您告诉 Kubernetes您的服务不需要集群 IP(您可以通过将服务规范中的 clusterIP 字段设置为 None 来实现),DNS 服务器将返回 pod IP 而不是单个服务 IPDNS 服务器将返回服务的多个 A 记录,而不是返回单个 DNS A记录,每个记录都指向当时支持该服务的单个 podIP。因此,客户端可以进行简单的 DNS A 记录查找并获取属于服务的所有podIP。然后,客户端可以使用该信息连接到其中一个、多个或全部。

将服务规范中的 clusterIP字段设置为None 会使服务无头,因为 Kubernetes 不会为其分配集群IP,客户端可以通过该IP连接到支持它的pod

将无头服务定义为:

apiVersion: v1
kind: Service
metadata:
  name: grpc-server-service
spec:
  clusterIP: None
  selector:
    app: grpc-server
  ports:
    - port: 80
      targetPort: 8001

要使服务成为无头服务,您唯一需要更改的.spec.clusterIP字段是将字段设置为None

验证 DNS

要确认无头服务的 DNS,请创建一个镜像为tutum/dnsutilspod

kubectl run dnsutils --image=tutum/dnsutils --command -- sleep infinity

然后运行命令

kubectl exec dnsutils -- nslookup grpc-server-service

这将无头服务的 FQDN 返回为:

Server:         10.96.0.10
Address:        10.96.0.10#53
Name:  grpc-server-service.default.svc.cluster.local
Address: 10.244.0.22
Name:  grpc-server-service.default.svc.cluster.local
Address: 10.244.0.20
Name:  grpc-server-service.default.svc.cluster.local
Address: 10.244.0.21

如您所见,无头服务解析为所有通过 service 连接的 podIP 地址。将此与非无头服务返回的输出进行对比。

Server: 10.96.0.10 Address: 10.96.0.10#53 Name: grpc-server-service.default.svc.cluster.local Address: 10.96.158.232

配置客户端 客户端应用程序剩下的唯一变化是指向带有服务器 pods 端口的无头服务,如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpc-client
  labels:
    app: grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grpc-client
  template:
    metadata:
      labels:
        app: grpc-client
    spec:
      containers:
        - name: grpc-client
          image: techdozo/grpc-lb-client:1.0.0
          env:
            - name: SERVER_HOST
              value: grpc-server-service:8001

请注意,SERVER_HOST现在指向无头服务 grpc-server-service和服务器端口 8001。您还可以使用 SERVER_HOST 作为 FQDN

name: SERVER_HOST 
value: "grpc-server-service.default.svc.cluster.local:8001"

如果您通过首先删除客户端部署来再次部署客户端:

kubectl delete deployment.apps/grpc-client

然后再次部署客户端:

kubectl apply -f deployment-client.yaml

您可以看到 pod打印的日志。

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

代码示例

本文的工作代码示例列在GitHub 上 。您可以使用kind在本地 Kubernetes 集群上运行代码。

https://github.com/techdozo/grpc-lb

https://techdozo.dev/2021/getting-started-with-kind-quick-start-a-multi-node-local-kubernetes-cluster/

概括

gRPC 中有两种可用的负载平衡选项——代理和客户端。由于 gRPC 连接是长期存在的,Kubernetes的默认连接级负载平衡不适用于 gRPCKubernetes Headless服务是一种可以实现负载均衡的机制。Kubernetes 无头服务 DNS 解析为支持 PodIP

参考资料

[1]

gRPC 负载均衡: https://grpc.io/blog/grpc-load-balancing/。

[2]

Kubernetes 上的 gRPC 负载均衡: https://kubernetes.io/blog/2018/11/07/grpc-load-balancing-on-kubernetes-without-tears/。


本文转载自:「云原生CTO」,原文:https://tinyurl.com/4maxs765,版权归原作者所有。


长治等保,等保,网络安全,网络等保,等级保护,网络安全等保,网络安全等级保护,长治网络安全等级保护,等保公司,等保测评,等级保护2.0,定级,定级备案,等保备案,长治等保备案,山西等保备案,系统测评,系统备案,网安备案,等保备案服务,等保咨询,公安局备案,二级等保,三级等保,三级测评,系统整改,做等保的公司,网站建设,企业网站建设,企业网站开发,企业网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

Powered by 园鉴科技 ©2021-2024  www.anycastyun.com

首 页
产 品
方 案
客 服