LB 压测 NodePort CPS 低

    环境说明: 用户使用的黑石TKE,不是公有云TKE,黑石的机器是物理机,LB的实现也跟公有云不一样,但 LoadBalancer 类型的 Service 的实现同样也是 LB 绑定各节点的 NodePort,报文发到 LB 后转到节点的 NodePort, 然后再路由到对应 pod,而测试在公有云 TKE 环境下没有这个问题。

    看到 数量在不断增加,也就是 conntrack 在插入很多新连接的时候失败了,为什么会插入失败?什么情况下会插入失败?

    在我们这个问题里实际就是 netfilter 做 SNAT 时源端口选举冲突了,黑石 LB 会做 SNAT,SNAT 时使用了 16 个不同 IP 做源,但是短时间内源 Port 却是集中一致的,并发两个 SYN a 和SYN b,被 LB SNAT 后源 IP 不同但源 Port 很可能相同,这里就假设两个报文被 LB SNAT 之后它们源 IP 不同源 Port 相同,报文同时到了节点的 NodePort 会再次做 SNAT 再转发到对应的 Pod,当报文到了 NodePort 时,这时它们五元组不冲突,netfilter 为它们分别创建了 conntrack 表项,SYN a 被节点 SNAT 时默认行为是 从 port_range 范围的当前源 Port 作为起始位置开始循环遍历,选举出没有被占用的作为源 Port,因为这两个 SYN 源 Port 相同,所以它们源 Port 选举的起始位置相同,当 SYN a 选出源 Port 但还没将 conntrack 表项插入时,netfilter 认为这个 Port 没被占用就很可能给 SYN b 也选了相同的源 Port,这时他们五元组就相同了,当 SYN a 的 conntrack 表项插入后再插入 SYN b 的 conntrack 表项时,发现已经有相同的记录就将 SYN b 的 conntrack 表项丢弃了。