【问题标题】:In Kubernetes, how to make sure one pod only serve one connection在 Kubernetes 中,如何确保一个 pod 只服务一个连接
【发布时间】:2020-06-08 09:44:16
【问题描述】:

情况

我想要一个 poolserving 豆荚(假设我有 50 个 serving 豆荚在周围)。它们将通过 LoadBalancer 服务公开。

我想确保:

  1. 每个 pod 只提供一个 TCP 连接,并保持此连接处于活动状态,直到客户端终止它。在此 pod 生命周期结束之前,它不会接收任何其他 TCP 连接。
  2. 一旦客户端终止连接,Pod 就会自行清理并销毁它。
  3. 启动另一个 pod 以匹配所需的副本编号。由于它当前不提供任何 TCP 连接,因此可以选择为下一个进入 LoadBalancer 服务的 TCP 连接提供服务。

例子

1. Initially, a `Deployment` specifies a pool of 2 pods behind a LoadBalancer Service.

[1] [2]


------LoadBalancer-------



2. A client initiates a TCP connection to the LoadBalancer (e.g. telnet loadbalancer.domain.com 80) and the TCP connection is routed to the first vacant pod.

[1] [2]
 |
 |
------LoadBalancer-------
 |
 |
cl1



3. 24 hours after that (assuming data has been passing between client1 & pod1), another client hits to the same Load Balancer public domain. Since pod1 is serving client1, I want the second client to be routed to another vacant pod, such as pod 2.

[1] [2]
 |   |
 |   |
------LoadBalancer-------
 |   |
 |   |
cl1 cl2



4. 24 hours after that, client 1 terminates the connection, I want pod1 to do clean up and destroy itself shortly afterwards. No new connections should be routed to it. That leaves pod2 the only one still running.

[2]
 |
 |
------LoadBalancer-------
 |
 |
cl2



5. `Deployment` will create additional pods to ensure the number of replicas. So pod3 is created.

[1] [3]
 |   
 |   
------LoadBalancer-------
 |   
 |   
cl1 



6. Another client hits the same endpoint and is routed to a vacant pod (pod 3 in this case).

[1] [3]
 |   |
 |   |
------LoadBalancer-------
 |   |
 |   |
cl1 cl3

And so on and so forth.

有人知道如何在 K8s 上解决这个问题吗?

【问题讨论】:

    标签: kubernetes


    【解决方案1】:

    所以我想这会起作用。

    首先设置一个 ReadinessProbe 以非常积极地(尽可能频繁地)轮询 pod 上的端点/tcp 端口。

    然后,一旦您获得连接,请确保 ReadinessProbe 失败,但同时确保 LivenessProbe 不会失败。

    最后,客户端断开连接后终止应用程序。

    您的部署需要有足够的副本来服务所有可以同时进入的客户端,因为一个 pod 永远不会服务两个客户端。

    【讨论】:

    • 你知道吗,这是一种非常有创意的使用探针的方式。我要试试看。
    • 我刚刚测试了它,但它不起作用。当您的就绪探测失败时,连接也会被强制切断。
    • 哦,所以我猜当 ip 从 iptables 中的虚拟 ip 中删除时,它也会终止连接:( 嗯,这是一个很好的尝试。
    【解决方案2】:

    你看过 k8s 的sessionAffinity,这可能对我有帮助。 This link 说:

    kube-proxy 在决定使用哪个后端 Pod 时会考虑 Service 的 SessionAffinity 设置。

    如果您想确保来自特定客户端的连接每次都传递到同一个 Pod,您可以通过将service.spec.sessionAffinity 设置为“ClientIP”(默认为“没有”)。您还可以通过适当设置service.spec.sessionAffinityConfig.clientIP.timeoutSeconds 来设置最大会话粘性时间。

    客户端终止后,让服务端在/clientstatus这样的路径返回失败码,使用readinessProbe/livenessProbe每秒检查该路径,如果readinessProbe/livenessProbe失败则删除pod。

    【讨论】:

    • 感谢您的建议。我知道sessionAffinity。它不会解决我的问题。但是,在客户端终止后杀死 pod 的想法是有道理的。
    【解决方案3】:

    我认为可以在 kubernetes 之上使用无服务器技术来实现这一点。检查Knative serving,这是一项无服务器技术。但是在这种情况下,没有预先创建 Pod 池,Pod 在客户端请求到来时按需创建,并在请求完成后销毁。

    【讨论】:

    • 感谢您告诉我有关 Knative 的信息。我不知道它存在。为什么您认为这只有在 Kubernetes 之上的无服务器技术才能实现?
    • 我想要的意思是 kubernetes 可能没有以一种直接的方式具有此功能..除非您对 @Andreas 提到的 kubernetes 提供的核心抽象进行一些处理
    【解决方案4】:

    您可以使用StatefulSet 部署pods,这样您就可以使用Headless Service

    无头服务不包含 ClusterIP。相反,它创建了几个用于生成 DNS 记录的端点。每个 DNS 记录都绑定到一个 pod。所有这些都由 Kubernetes 内部完成,但最好了解它是如何做到的。

    您可以阅读有关Kubernetes StatefulSets 101 - State of the Pods 的更多信息。

    然后您可以实现一个脚本(部署在 StatefulSet 前面),它将客户端路由到一个 DNS 记录。

    您还可以查看一些消息队列代理。

    KubeMQRabbitMQRedisGCPAWS 上也有 Pub/Sub。

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 1970-01-01
      • 2020-08-04
      • 2019-04-23
      • 1970-01-01
      • 2021-12-07
      • 2018-09-03
      • 2022-06-16
      • 2021-01-17
      相关资源
      最近更新 更多