Kubernetes 中 Pod 之间的通知

Posted

技术标签:

【中文标题】Kubernetes 中 Pod 之间的通知【英文标题】:Notifications between Pods in Kubernetes 【发布时间】:2021-10-26 15:48:03 【问题描述】:

问题:

WebsocketsSocket.io 允许在客户端和网络服务器之间提供丰富的双向异步通知。

Socket.iohtml/javascript 客户端和入口“cookie”路由之间创建了 Deployment 中的 Pod(我们称之为 Deployment A 的这些 pod)和 HTML/javascript 客户端之间的状态关联。其他 Deployment 中的其他 Pod(我们称之为 Deployment B 和 Deployment C 的这些 Pod)可能希望将特定于 Pod A 显示的事件通知 Deployment A 中的特定 Pod。

是否有 Kubernetes 机制允许在 pod 之间进行这种注册和通信?

通用设置:

部署 A、B、C 各有多个副本。

来自 A、B 和 C 的 pod 可以读取和更新哑分布式存储中的记录。

来自 A 的每个 pod 将负责一组页面(即网络服务器)。特定 pod A 负责的页面集可以动态更改(即,用户决定编辑哪个页面)。 pod A 不是无状态的,因为“cookie”控制入口路由,并且 pod A 维护一个socket.io 到用户 html/javascript 页面。

B 或 C 中的 Pod 更新页面上的组件。如果一个页面组件被 B/C 更新,而当前 A 中的 pod 正在编辑,则 B/C pod 必须将更新通知特定的 pod A。

多个 pod A 可能正在编辑同一页面。

更多详情:

部署 A 是一个 nodejs express 服务器,托管来自 html/javascript 客户端的 socket.io。流量使用nginx.ingress.kubernetes.io/affinity: "cookie" 从入口路由,因此托管特定客户端的 pod 可以向客户端发送未经请求的流量。即异步双向流量。

部署 B 是部署 A 的后端。一个简单的socket.AF_INET 从部署 A 中的 pod 打开到用于部署 B 的服务。来自 B 的响应到达 A,然后到达客户端。到目前为止,一切顺利,一切正常,但仅在 1 个节点配置上进行了测试。

部署 C 是部署 B 的后端。从 B 向 C 的服务打开一个套接字。从 C 到 B 到 A 到 WebClient 的响应工作正常(再次在 1 节点配置上)

问题:

部署 B 和 C 可能会从其他来源获取处理信息的请求,这些信息会更改向用户显示的内容。我想将部署 A 上托管 socket.io 的任何 pod 更新到显示此页面的客户端。

到目前为止的描述/实现不会异步更新 pod A,除非用户进行整页刷新。

多个用户可能显示相同的页面,但通过入口 cookie 关联到不同的部署 A pod。

就目前而言,用户 1 只能看到用户 1 发起的更新,而用户 2 只能看到用户 2 的更新。除非每个用户都进行页面刷新。

我希望 B 和 C 向 A 中显示正在更新的页面的所有 pod 发送更新。

感觉 Kubernetes 不干净的解决方案:

想要通知页面上组件更改的 pod 将创建一条记录,表明它对此页面感兴趣,其中包含其 pod 的 IP 地址和一个有效的时间戳

当客户端显示页面时,托管 A pod 将更新分布式数据存储中的记录,以表明它想要更新此页面上的组件。每隔一段时间,Pod A 会更新此记录中的保持活动时间。当用户离开此页面时,关联的 Pod A 将删除此记录。

页面的任何 pod 更新记录都会检查此记录并打开一个到另一个 pod 的套接字以通知它更改。

审核将删除任何因 pod 异常终止而未正确清理的过期记录,因为该 pod 在注册其有兴趣收到更改通知后。

问题重述:

这是一个干净的 Kubernetes 解决方案还是 Kubernetes 中有什么东西可以让这个更干净?

Kubernetes 新手:我是否在我的问题的任何地方弄乱了 Kubernetes 命名法?

【问题讨论】:

【参考方案1】:

没有本地方法可以在不同 Deployment 的 pod 之间进行可靠通信。在所有 pod 都具有已知且稳定的名称的 StatefulSet 的情况下,这是可能的。

在您的情况下,假设我正确理解您的要求,我建议您使用队列消息传递软件,例如 RabbitMQ 或 Kafka

【讨论】:

如果我理解正确,分配给 pod 的 ip 地址可以路由到所有其他 pod。你知道这是否正确吗?当一个 pod 被杀死或死亡时,它与 html/javascript 客户端之间的 socket.io 连接也是如此。如果上述 2 项正确,则 pod 可以与其他 pod 通信,就像 pod 可以托管到客户端 html/javascript 页面的 socket.io 连接一样可靠。我是 Kubernetes 新手,如果我弄错了,请多多指正。 kubernetes.io/docs/concepts/cluster-administration/networking 说“一个节点上的 Pod 可以在没有 NAT 的情况下与所有节点上的所有 Pod 通信”。 使用 microk8s Kubernetes,看起来 pods 呆了很久。仅当 pod 崩溃或网络更改或系统更新时才会关闭。所以 Pod 和客户端 html/javascript 之间的 socket.io 是相当稳定的。 google Kubernetes 是不是也熬夜了,还是经常被系统重置?换句话说,对于使用 WebSockets 的应用程序来说,谷歌 Kubernetes 是否足够稳定以提供良好的用户体验?我假设答案是肯定的。 RabbitMQ 或 Kafka 的快速阅读:看起来它可以完成这项工作,但还有很多。对于使用 WebSockets / Socket.io 在 Kubernetes 上托管的 nodejs/express 等应用程序,我看不到这些通过简单的 INET TCP 套接字和更新集中存储以标记对通信的兴趣给我带来了什么。我对 Kubernetes 的评价是否过高? Pod 是有生命的,无论出于何种原因,它们都可能消失,并且在 Deployment 下创建的替换 pod 对其前身的状态一无所知。 Pod 不会保存它们的 IP 或名称和服务对象,这些对象会平衡与 Pod 的连接,并作为 Pod 应用程序的服务发现,随机(或均匀)转发连接到一组 Pod。另一方面,StatefulSets 为它们的 pod 提供可预测的名称,而 Headless Service 可以帮助连接到特定的 pod。它通常用于 HA 有状态应用程序或数据库 Pod。

以上是关于Kubernetes 中 Pod 之间的通知的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes-Service介绍-服务发现

Kubernetes_14_静态Pod网关apiserver底层都是restful接口

Kubernetes_14_静态Pod网关apiserver底层都是restful接口

Kubernetes 中 2 个 pod 之间的通信

如何在 Kubernetes 集群中的 Pod 之间或节点之间复制文件?

为内存达到 90% 且未暴露于 Internet(后端微服务)的 kubernetes pod 配置通知/警报的方法