K8S – IPVS下线POD导致调用方超时问题

最近上K8S,遇到了发布引发调用方超时的困扰,经过一周多的折腾,问题得到了定位,对kube-proxy这一套工作逻辑也有了更具体的认识。

下面记录一下。

背景

发布应用时候,调用方出现较多的超时调用。

分析摘要

明确是IPVS引起。

发布应用的时候,IPVS降权下线POD的weight=0,但仍旧将新建连接的流量引入到下线POD。

结合K8S ISSUE和UCLOUD给的线索,明确因为公司的短连接调用方式可以在短时间内复用端口,导致触发IPVS的conntrack表转发表记录的决策复用,导致新连接流量被送入最近一次的后端POD。

最初尝试conn_reuse_mode=1禁止新链接复用已有conntrack转发关系,但是遇到频繁的调用超时报错,经猜测怀疑是因为conntrack表性能问题:

因为conntrack hash分桶取模的依据是源IP+源PORT,而我们关闭了对已有记录的复用选项,所以短链接调用场景下会导致单个桶内大量同来源的记录,链表导致conntrack hash表性能蜕化。

目前可以明确conn_reuse_mode以及相关联的几个参数均是kube-proxy在ipvs模式下代码启动阶段直接设置到sysctl的,默认是conn_reuse_mode=0,也就是复用转发关系,因此只有在下线POD时才会遇到流量损失,而平时就不会。(详细见代码:https://github.com/kubernetes/kubernetes/blob/release-1.15/pkg/proxy/ipvs/proxier.go):

官方ISSUE:https://github.com/kubernetes/kubernetes/issues/81775,仍在活跃状态,需持续关注进展。

已知的解决选项(倾向iptables方案)

1)保持IPVS:每次发布都会超时报错,等待社区的解决方案。

2)切到iptables:根据各方反馈可以解决问题,但是需要控制集群规模(具体看下面ucloud测试结论)。(PS:切换过程理论只需要新建iptables node,下线ipvs node)

3)采用ingress:仍需面对dns延迟,endpoint摘除延迟等问题,也改变了现有的K8S技术架构。

参考链接

自从我们反馈问题到ucloud之后,ucloud和tencent都快速的给出了分析:

https://tencentcloudcontainerteam.github.io/2019/12/15/no-route-to-host/

https://docs.ucloud.cn/compute/uk8s/introduction/kubeproxy_mode

详细了解conntrack:

https://opengers.github.io/openstack/openstack-base-netfilter-framework-overview/

详细学习iptables:

在我的博客搜索《2小时学会iptables》。

相关概念

https://opengers.github.io/openstack/openstack-base-netfilter-framework-overview/

conn_reuse_mode – INTEGER
1 – default

Controls how ipvs will deal with connections that are detected
port reuse. It is a bitmap, with the values being:

0: disable any special handling on port reuse. The new
connection will be delivered to the same real server that was
servicing the previous connection. This will effectively
disable expire_nodest_conn.

bit 1: enable rescheduling of new connections when it is safe.
That is, whenever expire_nodest_conn and for TCP sockets, when
the connection is in TIME_WAIT state (which is only possible if
you use NAT mode).

bit 2: it is bit 1 plus, for TCP connections, when connections
are in FIN_WAIT state, as this is the last state seen by load
balancer in Direct Routing mode. This bit helps on adding new
real servers to a very busy cluster.

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~