• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

背景:

有时候我们创建的服务不想走负载均衡,想直接通过pod-ip链接后端,怎么办呢,使用无头服务接可以解决。

1.什么是无头服务

无头服务是将服务的发布文件中的clusterip=none,不让其获取集群ip,DNS解析的时候直接走豆荚

2.实验

部署豆荚

应用程序接口版本:应用程序/v1

kind:部署

元数据:

名称: nginx-部署

标签:

app: nginx

spec:

副本: 1

选择器:

匹配标签:

app: nginx

模板:

元数据:

标签:

app: nginx

spec:

集装箱:

-名称: nginx

图像: nginx :最新测试

端口:

-集装箱港口: 80

部署常规服务

应用程序接口版本: v1

kind:服务

元数据:

名称: nginx-服务

标签:

app: nginx

spec:

端口:

-端口: 88

目标端口: 80

选择器:

app: nginx

:型节点端口

查看部署的服务

10.97.134.133是clusterip

在这里插入图片描述

部署headlessservice服务服务

应用程序接口版本: v1

kind:服务

元数据:

名称:无头服务

spec:

选择器:

app: nginx

端口:

-协议: TCP

端口: 80

目标端口: 80

clusterIP:无

查看详情

在这里插入图片描述

测试服务解析

服务的FQDN:nginx服务。默认。SVC。集群。当地的

无头服务的FQDN:无头服务。默认。SVC。集群。本地

我们在容器里面平FQDN,服务解析出的地址是clusterip

在这里插入图片描述

无头服务解析出来的地址是pod ip

在这里插入图片描述

所以在微服务相关场景如果需要直通豆荚的时候我们就可以使用无头服务绕过k8s的转发机制,直接访问豆荚了。

参考资料

https://kube

rnetes.io/docs/concepts/services-networking/service/#headless-services

 

如果您使用 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 podKubernetes部署带有一个gRPC客户端pod
  • Service : ClusterIP Service,选择所有服务端pod

图片

创建服务端部署

要创建部署,请将以下代码保存在 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

如上所示,Pod 的 IP 地址是 - 10.244.0.11:8001,10.244.0.12:8001,10.244.0.13:8001。如果客户端调用端口 80上的服务,那么它将跨端点(Pod 的 IP 地址)对调用进行负载平衡。但对于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 记录查找并获取属于服务的所有pod的 IP。然后,客户端可以使用该信息连接到其中一个、多个或全部。

将服务规范中的 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/dnsutils的 pod :

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 连接的 pod的 IP 地址。将此与非无头服务返回的输出进行对比。

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打印的日志。

图片

代码示例

本文的工作代码示例列在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

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now