提问者:小点点

Kubernetes中的自定义负载平衡


我们正在开发一个模拟软件,该软件使用kubernetes在多个pod之间部署和扩展。当用户发出模拟请求时,会选择一个开始执行工作并被视为忙碌的pod。当另一个用户发出模拟请求时,它应该被路由到下一个空闲pod。目前,通常会选择一个繁忙的pod(即使有空闲的pod),因为kubernetes不知道哪些pod是忙/空闲的。

是否可以以始终选择空闲pod的方式平衡请求?(假设pod中的每个应用程序实例都公开了一个HTTPendpoint,该endpoint告诉它当前的繁忙/空闲状态)


共2个答案

匿名用户

我认为您可以使用就绪探头:

有时,应用程序暂时无法服务于流量。例如,应用程序可能需要在启动期间加载大型数据或配置文件,或者在启动后依赖于外部服务。在这种情况下,您不想终止应用程序,但也不想向它发送请求。Kubernetes提供了检测和缓解这些情况的就绪探针。一个带有容器的pod报告它们还没有准备好,它不会通过Kubernetes服务接收流量。

您可以使用非200返回代码使应用程序响应探测请求。需要注意的是,在准备就绪探测再次成功之前,不会有新的请求传入。但也有缺点:

  • 当所有pod都很忙时,您将收到502错误;
  • 用户将无法向他们的pod提交后续请求(因为pod会很忙);
  • 更改就绪状态需要一些时间,因此如果您在短时间内(探测间隔)收到大量请求(超过pod数量),某些pod可能需要多个请求。

匿名用户

上面答案中建议的另一个解决方案是利用无头服务和一些反向代理/负载平衡器,比如HAProxy(我用过)。

所以你可以有一个无头服务或者改变现有的服务,如下图所示。配置clusterIP:None将负责创建无头服务。

apiVersion: v1
kind: Service
metadata:
  name: some-service
  namespace: dev
  labels:
    app: <labels here>
spec:
  ports:
    - port: <port>
      targetPort: <tport>
  selector:
    app: <selectors here>
  clusterIP: None

然后您可以像下面这样部署HAProxy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: haproxy-headless
  namespace: dev
  labels:
    app: haproxy-headless
spec:
  replicas: 1
  selector:
    matchLabels:
      app: haproxy-headless
  template:
    metadata:
      labels:
        app: haproxy-headless
    spec:
      containers:
      - name: haproxy-headless
        image: haproxy:1.9
        ports:
        - containerPort: 8888
          name: management
        - containerPort: 8085
          name: http
        volumeMounts:
         - name: haproxy-config
           mountPath: "/usr/local/etc/haproxy/haproxy.cfg"
      volumes:
        - name: haproxy-config
          configMap:
            name: haproxy-config

Haproxy的配置图:

apiVersion: v1
kind: ConfigMap
metadata:
  name: haproxy-config
  namespace: dev
data:
   haproxyconfig.cfg: |
     
     defaults
       mode tcp
       log global
       option httplog
       retries 5
       timeout connect 10s
       timeout client 300s
       timeout server 300s 
     
     resolvers test_resolver
       nameserver dns1 <your dns server address>
       resolve_retries 30
       timeout retry 2s
       hold valid 10s
       accepted_payload_size 8192
     
     frontend stats
        mode http
        bind :8888
        stats enable
        stats uri /
        stats refresh 15s
     
     frontend test_fe
       bind :8085
       timeout client 60s
       default_backend test_be
       
     backend test_be
       balance leastconn
       server-template srv 7 <service-name>.<your namespace>.svc.cluster.local:6311 check resolvers test_resolver

重要的是要了解我们如何配置我们的HAProxy在这里服务器模板被用于使用K8s的DNS进行服务发现,您可以使用平衡leastconn来确保使用最少使用的服务器。

最终,HAProxy需要一项服务

apiVersion: v1
kind: Service
metadata:
  name: haproxy-service
  namespace: dev
spec:
  selector:
    app: haproxy-headless
  ports:
    - name: be
      protocol: TCP
      port: 6311
      targetPort: 8085
    - name: mngmnt
      protocol: TCP
      port: 8888
      targetPort: 8888
  type: <Type as per requirement>

现在,只要您想访问应用程序,就可以使用上述服务。也许你可以了解一下如何在k8s中使用HAProxy进行负载平衡,它主要做服务发现负载平衡。

也许yaml中显示的一些配置不正确或不匹配,但我希望概念清楚如何实现这一点。