
# CCE集群IPVS转发模式下conn_reuse_mode问题说明
#### 问题说明
对于节点内核版本小于5.9的场景，CCE集群在IPVS模式下，通过Service方式访问集群内部服务，偶现1秒延时或者后端业务升级后访问Service失败的情况，引起该问题的主要原因为社区IPVS连接复用Bug。
#### IPVS连接复用参数说明
IPVS对端口的复用策略主要由内核参数net.ipv4.vs.conn_reuse_mode决定。
1. 当net.ipv4.vs.conn_reuse_mode=0时，IPVS不会对新连接进行重新负载，而是复用之前的负载结果，将新连接转发到原来的RS（IPVS的后端）上。
2. 当net.ipv4.vs.conn_reuse_mode=1时，IPVS则会对新连接进行重新负载。
 
#### IPVS连接复用参数带来的问题
- **问题1**
  当net.ipv4.vs.conn_reuse_mode=0时，对于端口复用的连接，IPVS不会主动进行新的调度，也并不会触发结束连接或DROP操作，新连接的数据包会被直接转发到之前使用的后端pod。如果此时后端pod已经被删除或重建就会出现异常，根据当前的实现逻辑，高并发访问Service场景下，不断有端口复用的连接请求发来，旧的转发连接不会被kube-proxy删除，导致访问Service失败。
  
- **问题2**
  当net.ipv4.vs.conn_reuse_mode=1时，高并发场景下发生源端口与之前链接重复的情况，不会复用链接，而是会重新进行调度。根据ip_vs_in()的处理逻辑，当开启了net.ipv4.vs.conntrack时，这种情况会先DROP掉第一个SYN包，导致SYN的重传，有1秒延迟。导致性能下降。
  
 
#### 社区当前行为及在CCE集群中影响
节点上net.ipv4.vs.conn_reuse_mode的初始默认值为1，但社区kube-proxy会对该参数进行重新设置：
| 集群版本    | kube-proxy行为                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 对CCE集群的影响                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
|:---|:---|:---|
| 1.17及以下 | kube-proxy默认将net.ipv4.vs.conn_reuse_mode设置为0，详情请参见[fix IPVS low throughput issue](https://github.com/kubernetes/kubernetes/pull/71114)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 如果CCE 1.17及以下版本的集群使用IPVS作为服务转发模式，所有节点net.ipv4.vs.conn_reuse_mode参数都会被kube-proxy默认设置为0，因此将存在**[•问题1]**，即端口复用下的RS无法移除问题。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| 1.19及以上 | kube-proxy会根据内核的版本进行选择，详情请参见[ipvs: only attempt setting of sysctlconnreuse on supported kernels](https://github.com/kubernetes/kubernetes/pull/88541)。 - 内核版本大于4.1：将net.ipv4.vs.conn_reuse_mode设置为0。  - 其他情况：保持系统原有的默认值（即net.ipv4.vs.conn_reuse_mode=1）。   说明： 由于Linux 5.9内核已修复该问题，从Kubernetes 1.22版本开始，对于5.9及以上的内核，kube-proxy不再修改net.ipv4.vs.conn_reuse_mode参数，详情请参见[Don't set sysctl net.ipv4.vs.conn_reuse_mode for kernels \>=5.9](https://github.com/kubernetes/kubernetes/pull/102122)。 | 在CCE 1.19.16-r0及以上版本集群中，使用IPVS作为服务转发模式的情况下，由于节点内核版本不同，不同操作系统情况如下： - 当节点的OS版本为EulerOS 2.5和CentOS 7.6时， - 当集群版本在v1.19.8-r0到v1.19.16-r60（不包括v1.19.16-r60）、v1.21.1-r0到v1.21.11-r20（不包括v1.21.11-r20）、v1.23.1-r0到v1.23.10-r0（不包括v1.23.10-r0）、v1.25.1-r0到v1.25.5-r0（不包括v1.25.5-r0）、v1.27.1-r0到v1.27.2-r0（不包括v1.27.2-r0）的范围内时，OS内核版本低于4.1，因此kube-proxy会保持系统原有的默认值net.ipv4.vs.conn_reuse_mode=1，将存在**[•问题2]**，即高并发场景存在1秒延时。  - 其他版本集群：设置net.ipv4.vs.conn_reuse_mode=0，存在**[•问题1]**，即端口复用下的RS无法移除问题。    - 当节点的OS版本为Ubuntu 18.04时，内核版本高于4.1，因此kube-proxy会设置net.ipv4.vs.conn_reuse_mode=0，存在**[•问题1]**，即端口复用下的RS无法移除问题。  - 当节点的OS版本为EulerOS 2.9时，低版本内核情况下kube-proxy设置net.ipv4.vs.conn_reuse_mode=0会引发**[•问题1]** ，将内核版本升级至指定版本即可修复该问题，参见[修复计划]。  - 当节点的OS版本为Huawei Cloud EulerOS 2.0、Ubuntu 22.04时，内核版本大于5.9，操作系统已修复该问题。   |
   
#### 建议
请您对该问题的影响进行评估，如果上述问题会对您的业务产生影响建议您采取以下措施：
1. 使用不涉及该问题的操作系统，如Huawei Cloud EulerOS 2.0、Ubuntu 22.04。对于EulerOS 2.9的节点，新建节点不涉及该问题，存量低版内核的节点需要升级至已修复版本，详情请参见[修复计划]。
2. 使用服务转发模式为iptables的集群。
 
 #### 修复计划
如果您使用EulerOS 2.9的节点，请确认节点内核版本是否满足以下要求。如节点内核版本过低，可以选择重置节点或者重新创建节点解决该问题。
已修复的内核版本如下：
- x86：4.18.0-147.5.1.6.h686.eulerosv2r9.x86_64
- ARM： 4.19.90-vhulk2103.1.0.h584.eulerosv2r9.aarch64
 
K8s社区issue：<https://github.com/kubernetes/kubernetes/issues/81775>
