问大家一个关于使用 K8s 的 Service 做长连接负载均衡的问题

2023-01-18 20:41:38 +08:00
 zhoudaiyu

背景是我们有 2 个 K8s 集群,上面都运行着一些 tomcat 应用,这两个集群有互相调用的需求,因此需要暴露出 NodePort 供另外一个集群的 Pod 调用(因为不同集群的 Pod 间无法通过 Pod IP 直接访问),又为了保证跨集群调用的高可用性,需要提供多个 Node 供服务调用方随机选择。图里给了个例子,下面我用调用方 A (服务 A )调用服务 B 为例讲一下整个调用的流程,首先在服务启动的时候,提供方 B 的所有应用 POd 的 IP 会被注册到注册中心,服务 A 如果想调用服务 B 的某个 POd ( IP 是随机的),服务注册的客户端发现对方的 IP 是另外一个集群的,无法直接访问,因此将 IP 替换为另外一个集群的 Node IP+NodePort ( Node IP 也是随机选一个),这时请求就到了某台机器的 Service ,Service 会再次负载均衡一下连接到某个 POd ,但是由于用了 netty 的长连接,因此连接一旦建立,就不会再销毁了。因此,虽然单独看某台 Node 的负载到 Pod 上的链接是均衡的,但是在所有被随机到的 Node 来看,可能并不是那么均衡(特别是当连接建立的比较少的时候),因此就会造成有的提供方 Pod 被调用的比较多,有的比较少的问题。请问这种长连接情况下,如何能把负载做的均衡一点?

2318 次点击
所在节点    Kubernetes
18 条回复
idblife
2023-01-18 20:46:55 +08:00
node 前加一层 haproxy ?
swulling
2023-01-18 20:47:12 +08:00
k8s 的 service 的负载均衡算法很固定,目前实现基本是 ipvs 。要想修改为适合长链接的最小链接算法,需要修改 kubeproxy 参数。

同时修改了 lb 算法后,可能还需要增加一个定时任务,检查不均衡的节点,主动断掉节点链接来促使 rebanlance 。
defunct9
2023-01-18 20:47:50 +08:00
改成短链接
zhoudaiyu
2023-01-18 21:36:21 +08:00
@swulling 哎 我们集群过于老,只有 iptables
@defunct9 短连接我们这辆估计撑不住啊
@idblife 不能解决问题吧,多了一层可能更不均衡了
Monad
2023-01-18 21:45:04 +08:00
是否可以由 B 服务的 Pod 注册 NodeIP+NodePort 到注册中心,同时 Service 启用 externalTrafficPolicy=Local ,这样调用方 A 可以直接随机选择,他们只会给本机上的 Pod 转发。
当然这样可能要通过 affinity 保持每个 Node 只有一个对应 Pod 。
ch2
2023-01-18 21:53:19 +08:00
改成基于 mq 的事件模式,不怕负载不均衡
zhoudaiyu
2023-01-18 22:06:48 +08:00
@Monad 这是一个不错的办法,目前可能唯一满足不了的就是只有 1 个 Pod ,因为集群比较小,现在还是有些应用不能满足只有 1 个 Pod ,不过我查了查,好像有多个 Pod 也是没问题的?
@ch2 这个改造成本有点过大了,时间不太允许呀
novolunt
2023-01-18 22:10:31 +08:00
上 istio ,svc 上 grpc 服务的问题就是通过这个解决的。不要怕没接触过,我们生产都在用
jaylee4869
2023-01-18 22:10:34 +08:00
一致性哈希。选 Node IP 那边的逻辑换成顺时针方向的哈希环节点选取,这能保证 Node 级别上一定程度均衡。
Pod 层面的话,试试根据 ClientIP 做 sessionAffinity ?
zhoudaiyu
2023-01-18 22:41:17 +08:00
@novolunt 用 istio 做跨集群调用吗?
@jaylee4869 node 层面看还算均衡,现在问题就出在 service 这里,没有那种全局的负载均衡
Monad
2023-01-19 00:02:38 +08:00
@zhoudaiyu 多个 pod 的话涉及到每个 nodeip 的权重了 如果没有这个概念调用方同等权重随机,从 pod 的角度看负载也不均衡了(除非能保证 pod 数在每个 node 一致,不过不清楚怎么办到)。
rrfeng
2023-01-19 08:35:39 +08:00
这问题跟 k8s 没关系,就是长链接的负载均衡问题。

假如你有 100 个实例,只有一个客户端,怎么也不可能均匀。
rushssss
2023-01-19 09:04:31 +08:00
取一个折中的办法: 在服务端或是客户端改造都行,每条长链接用过多少次之后就销毁(取值取决于你的负载情况),比如每条长链接处理过 1000 个请求就主动关闭,促使其重新建立连接,这样即能保证效率,与能保证大致的负载均衡
winglight2016
2023-01-19 09:17:25 +08:00
如果 service 级的 lb 没有问题,那只需要把 pod 均匀部署到 node 上就可以了,自己设计好,通过 affinity 指定 node

长连接不推荐,全部流量都走长连接,等于瓶颈和风险都放在这个长连接上,太不靠谱了
fangdaidai
2023-01-19 09:48:33 +08:00
lz 这个坑我们之前踩过,k8s 外部流量接入可以尝试下 ingress 来做负载均衡,内部转发可以用服务发现
retanoj
2023-01-19 09:53:48 +08:00
有考虑过两个集群网络互通么(逃..
zhoudaiyu
2023-01-19 09:54:31 +08:00
@fangdaidai #15 netty 需要 4 层的代理,而且 ingress 也是转到 svc 吧
zhoudaiyu
2023-01-19 10:08:18 +08:00
@retanoj 考虑过,昨天和领导提了 submariner 的方案,但是领导觉得这个可能不稳定,所以否了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/909772

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX