• kubernetes: headless service


    背景:
    有时候我们创建的服务不想走 负载均衡,想直接通过 pod-ip 链接后端, 怎么办呢, 使用headless service接可以解决。
    1.什么是headless service
    headless service 是将service的发布文件中的clusterip=none ,不让其获取clusterip , DNS解析的时候直接走pod
    2.实验
    部署pod

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80

    部署常规service

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
      labels:
        app: nginx
    spec:
      ports:
      - port: 88
        targetPort: 80
      selector:
        app: nginx
      type: NodePort
    

    查看 部署的service
    10.97.134.133是 clusterip
    在这里插入图片描述
    部署headlessservice

    apiVersion: v1
    kind: Service
    metadata:
      name: headless-service
    spec:
      selector:
        app: nginx
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
      clusterIP: None
    
    

    查看详情
    在这里插入图片描述
    测试服务解析
    service 的 FQDN: nginx-service.default.svc.cluster.local
    headless service的FQDN: headless-service.default.svc.cluster.local
    我们在容器里面ping FQDN , service解析出的地址是clusterip
    在这里插入图片描述
    headless service 解析出来的地址是 pod ip
    在这里插入图片描述
    所以在微服务相关场景 如果需要直通pod的时候 我们就可以使用headless service 绕过 k8s的转发机制,直接访问pod了。

    参考资料
    https://kubernetes.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

  • 相关阅读:
    北京Uber优步司机奖励政策(3月3日)
    ubuntu安装phpstorm
    ubuntu安装typora
    PHP定时任务Crontab结合CLI模式详解
    mysql创建用户,并授予权限
    ubuntu下使用crontab定时器
    Ubuntu 查看当前目录使用的总空间大小
    ubuntu安装ruby,安装sass,安装compass
    open_basedir restriction in effect,解决php引入文件权限问题 lnmp
    canvas 画线
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/16212246.html
Copyright © 2020-2023  润新知