首页 > 其他分享 >ipvs 连接复用引发的系列问题

ipvs 连接复用引发的系列问题

时间:2024-02-21 16:44:58浏览次数:28  
标签:复用 ipvs mode Pod 连接 conn

在 Kubernetes 社区里面有一个讨论已久的 bug (#81775),这个问题是当 client 对 service 发起大量新建 TCP 连接时,新的连接被转发到 Terminating 或已完全销毁的旧 Pod 上,导致持续丢包 (报错 no route to host),其根因是内核 ipvs 连接复用引发,本文来详细掰扯下。

conn_reuse_mode 简介

在介绍原因之前,我们先介绍下 conn_reuse_mode 这个内核参数,它是以下两个 patch 引入的:

  1. year 2015 d752c364571743d696c2a54a449ce77550c35ac5
  2. year 2016 f719e3754ee2f7275437e61a6afd520181fdd43b

其目的是:

  1. 当 client ip:client port 复用发生时,对于 TIME_WAIT 状态下的 ip_vs_conn,进行重新调度,使得 connection 在 rs 上的分布更均衡,以提高性能。
  2. 如果该 mode 是 0,则会复用旧 ip_vs_conn 里的 rs,使得连接更不均衡。

所以当 conn_reuse_mode 为 0 表示启用 ipvs 连接复用,为 1 表示不复用,是不是有点反直觉?这个确实也比较有争议。

conn_reuse_mode=1 的 bug

开启这个内核参数 (conn_reuse_mode=1) 本意是为了提高新建的性能,实际结果是大幅度降低了性能,实际测试中发现 cps 从 3w 降低到了 1.5K,这也表明内核社区的一些 patch 没有经过严格的性能测试。

开启这个内核参数实际就表示 ipvs 转发时不做连接复用,每次新建的连接都会重新调度 rs 并新建 ip_vs_conn,但它的实现有个问题: 在新建连接时 (SYN 包),如果 client ip:client port 匹配到了 ipvs 旧连接 (TIME_WIAT 状态),且使用了 conntrack,就会丢掉第一个 SYN 包,等待重传后 (1s) 才能成功建连,从而导致建连性能急剧下降。

Kubernetes 社区也发现了这个 bug,所以当 kube-proxy 使用 ipvs 转发模式时,默认将 conn_reuse_mode 置为 0 来规避这个问题,详见 PR #71114 与 issue #70747 。

conn_reuse_mode=0 引发的问题

由于 Kubernetes 为了规避 conn_reuse_mode=1 带来的性能问题,在 ipvs 模式下,让 kube-proxy 在启动时将 conn_reuse_mode 置为了 0 ,即使用 ipvs 连接复用的能力,但 ipvs 连接复用有两个问题:

  1. 只要有 client ip:client port 匹配上 ip_vs_conn (发生复用),就直接转发给对应的 rs,不管 rs 当前是什么状态,即便 rs 的 weight 为 0 (通常是 TIME_WAIT 状态) 也会转发,TIME_WAIT 的 rs 通常是 Terminating 状态已销毁的 Pod,转发过去的话连接就必然异常。
  2. 高并发下大量复用,没有为新连接没有调度 rs,直接转发到所复用连接对应的 rs 上,导致很多新连接被 "固化" 到部分 rs 上。

业务中实际遇到的现象可能有很多种:

  1. 滚动更新连接异常。 被访问的服务滚动更新时,Pod 有新建有销毁,ipvs 发生连接复用时转发到了已销毁的 Pod 导致连接异常 (no route to host)。
  2. 滚动更新负载不均。 由于复用时不会重新调度连接,导致新连接也被 "固化" 在某些 Pod 上了。
  3. 新扩容的 Pod 接收流量少。 同样也是由于复用时不会重新调度连接,导致很多新连接被 "固化" 在扩容之前的这些 Pod 上了。

规避方案

我们知道了问题原因,那么在 ipvs 转发模式下该如何规避呢?我们从南北向和东西向分别考虑下。

南北向流量

  1. 使用 LB 直通 Pod。对于南北向流量,通常依赖 NodePort 来暴露,前面的负载均衡器将流量先转到 NodePort 上,然后再通过 ipvs 转发到后端 Pod。现在很多云厂商都支持 LB 直通 Pod,这种模式下负载均衡器直接将请求转发到 Pod,不经过 NodePort,也就没有 ipvs 转发,从而在流量接入层规避这个问题。
  2. 使用 ingress 转发。在集群中部署 ingress controller (比如 nginx ingress),流量到达 ingress 再向后转时 (转发到集群内的 Pod),不会经过 service 转发,而是直接转发到 service 对应的 Pod IP:Port,也就绕过了 ipvs。Ingress controller 本身结合使用前面所说的 LB 直通 Pod 方式部署,效果更佳。

东西向流量

集群内的服务间调用 (东西向流量),默认还是会走 ipvs 转发。对于有这种高并发场景的业务,我们可以考虑使用 Serivce Mesh (如 istio) 来治理流量,服务间转发由 sidecar 代理,并且不会经过 ipvs。

终极方案: 内核修复

conn_reuse_mode=1 引发性能急需下降的 bug,目前在腾讯云提供的 TencentOS-kernel 开源内核已修复,对应 PR #17, TKE 上的解决方案就是使用这个内核 patch,依赖禁用 ipvs 连接复用 (conn_reuse_mode=1),这样同时也就解决了 ipvs 连接复用引发的系列问题,且经过了大规模生产验证。

不过以上修复并未直接合并到 linux 社区,当前已有两个相关 patch 合并到了 linux 内核主干 (自 v5.9),分别解决 conn_reuse_mode 为 0 和 1 时的上述 bug,其中一个也是借鉴了腾讯云修复的思路,详见 k8s issue #93297 。

如果你使用了 v5.9 以上的内核,理论上就没有本文所述的问题了。既然 v5.9 以上的内核已修复上述 bug,那么 kube-proxy 就无需显式去设置 conn_reuse_mode 这个内核参数了,这也是 PR #102122 所做的事。不过值得注意的是,社区 patch 目前并未看到有大规模的生产验证,试用有风险。

标签:复用,ipvs,mode,Pod,连接,conn
From: https://www.cnblogs.com/cheyunhua/p/18025612

相关文章

  • appium inspector 连接安卓设备
    首先找到app的包名和activity。查看包名adbshell"dumpsyswindow|grepmCurrentFocus"查看包对应的activity,输入下面的命令,再找到cmpadbshellmonkey-pcom.jingdong.app.mall-vvv1启动appiumserver启动inspector,配置信息{"platformName":"Android","a......
  • 数据库连接关键参数推荐配置
     一、MySQL连接参数配置(druid)1、关键参数配置连接池大小a)对于大部分OLTP应用,推荐如下配置:jdbc.druid.initialSize=4jdbc.druid.minIdle=4jdbc.druid.maxActive=12b)针对高并发的api接口,避免瞬间创建大量连接,推荐设置minIdle=initSize=maxActivejdbc.druid.i......
  • 在k8S中,当一个Pod有多个容器时,如何连接到指定容器?
    在Kubernetes(k8S)中,当一个Pod包含多个容器时,可以通过kubectlexec命令连接到指定的容器。kubectlexec命令允许您在运行中的Pod中执行命令或打开交互式shell。要连接到多容器Pod中的特定容器,请按照以下格式执行命令:kubectlexec-it<pod-name>-c<container-nam......
  • orchard core 开启openid 使用uniapp结合oidc-client 作为客户端连接
    官方的项目地址:https://github.com/onestar1/OrchardSkills.OrchardCore.OIDC.Vue.js/tree/main/OrchardSkills.OrchardCore.MaterialDesignTheme操作步骤:单独clonehttps://github.com/OrchardSkills/OrchardSkills.OrchardCore.MaterialDesignTheme1、打开Recipes目录下......
  • 【转帖】阿里云ssh远程连接短时间就会断掉的解决方案
    https://zhuanlan.zhihu.com/p/423385471 本文已收录公众号《极客运维之家》,欢迎关注公众号一起交流学习文章目录问题重现问题分析问题解决打开sshd的配置文件修改如下参数重启服务:补充总结问题重现阿里云服务器,使用Finalshell远程连接,在操作中没有出现任务......
  • Go语言精进之路读书笔记第29条——使用接口作为程序水平组合的连接点
    如果说C++和Java是关于类型层次结构和类型分类的语言,那么Go则是关于组合的语言。——RobPike,Go语言之父“偏好组合,正交解耦”29.1一切皆组合在语言设计层面,Go提供了诸多正交的语法元素供后续组合使用,包括:Go语言无类型体系(typehierarchy),类型定义独立;方法和类型是正交......
  • Python异步编程原理篇之IO多路复用模块selector
    selector简介selector是一个实现了IO复用模型的python包,实现了IO多路复用模型的select、poll和epoll等函数。它允许程序同时监听多个文件描述符(例如套接字),并在其中任何一个就绪时进行相应的操作。这样可以有效地管理并发I/O操作,提高程序的性能和资源利用率。本篇主要......
  • Mogeaver 连接数据库
    下载安装Mogeaver是一款开源软件,下载地址如下:https://docs.mogdb.io/zh/mogdb/v3.0/mogeaver-release-notes根据您的操作系统选择相应的安装包,下载完成后直接双击安装即可。配置连接串首次打开软件会弹出“创建新连接”窗口,如下图所示选择MogDB在测试连接可能会出现的问题1......
  • Oracle 低版本客户端连接19C报错ORA-28040
    适用范围12.2+问题概述客户使用Oracle11.2客户端连接Oracle19c的时候,报错:ORA-28040:NomatchingauthenticationprotocolORA-28040:没有匹配的验证协议问题原因原因客户端与服务器的没有匹配的认证协议解决方案1、在数据库服务器上的$ORACLE_HOME/network/admin/sql......
  • Docker 安装 SqlServer 和连接
    dockerpullmcr.microsoft.com/mssql/server:2019-latest--拉取dockerrun-e"ACCEPT_EULA=Y"-e"MSSQL_SA_PASSWORD=MyName2024"-p14330:1433--namesql1--hostnamesql1-dmcr.microsoft.com/mssql/server:2019-latest--运行-d是你......