k8s 环境里 pod 之间 ICMP 通但 TCP 不通,client 收到 synack 却不响应。根因是 server 端 tunl 设备的 tx-checksumming 没生效,发出的包校验和错误,被 client 丢弃。
现象
有个 k8s 的环境,pod 之间 ICMP 是通的,TCP 不通。
client 发送的 SYN 报文,可以收到 server 的 SYNACK 回复,但是 client 并不响应这个 SYNACK 报文。
排查
通过 tcpdump -vvv 抓包,看到 server 发出的包,在 client 端依然 checksum incorrect。
怀疑是 server 端的 tx-checksumming: on 功能对 tunl 设备没有生效。
关闭 server 的该功能后正常:
ethtool -K tunl0 tx off
根因
1. tunl0 是个软件设备
client 和 server 用 tunnel 隧道来通信,这里的 tunl0 是个软件设备。
2. tx-checksumming 的作用
tx-checksumming: on 表示发送侧硬件校验和计算。
如果设置为 on,表示网卡支持该特性,kernel 发包的时候不计算校验和,让网卡发送的时候计算。
ethtool -K eth0 tx-checksum-ip-generic on|off
3. 问题出在哪
server 的 tunl 设备,也支持 tx-checksumming: on 选项。
这一批 server 发出的 SYNACK 报文,从 tunl0 网卡发出来的时候,期待着能在离开网卡的时候,报文的校验和被重新计算为正确的。
也就是 tx-checksumming: on 这个功能生效,但是,没生效,报文校验和依然错误。
4. client 端看到的现象
client 收到的 SYNACK 报文,用 tcpdump -vvv 看到有提示:
- 如果收到的报文校验和错误,有提示
incorrect - 如果正确,有提示
correct
server 端的网卡信息:
root@host:~# ip -d link show dev tunl0
26: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0 promiscuity 0 minmtu 0 maxmtu 0
ipip any remote any local any ttl inherit nopmtudisc addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
root@host:~# ethtool -k tunl0 | head
Features for tunl0:
rx-checksumming: off [fixed]
tx-checksumming: on
tx-checksum-ipv4: off [fixed]
tx-checksum-ip-generic: on
tx-checksum-ipv6: off [fixed]
tx-checksum-fcoe-crc: off [fixed]
tx-checksum-sctp: off [fixed]
scatter-gather: on
tx-scatter-gather: on
client 端抓包,tcpdump -vvv 加上 -vvv 才能看到 checksum 的结果。
发送的时候,cksum 0x972f (incorrect -> 0x4615) 没关系,因为离开网卡的时候,网卡会计算校验和,符合 tx-checksumming: on 这个功能的预期:
15:27:52.923926 ip: (tos 0x0, ttl 64, id 23082, offset 0, flags [DF], proto TCP (6), length 60)
10.0.0.42.43332 > 10.0.0.4.9400: Flags [S], cksum 0x972f (incorrect -> 0x4615), seq 4089076775, win 64800, options [mss 1440,sackOK,TS val 20860605 ecr 0,nop,wscale 10], length 0
接收的回复,这里 cksum 0xae7a (correct) 是正确的,如果:
15:27:52.924453 ip: (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60)
10.0.0.4.9400 > 10.0.0.42.43332: Flags [S.], cksum 0xae7a (correct), seq 1828286424, ack 4089076776, win 64260, options [mss 1440,sackOK,TS val 3284203794 ecr 20860605,nop,wscale 10], length 0
解决办法
因为这个 tunl 设备是 calico 创建的,想改 tunl 设备还要找好的时机。
可以修改物理机上的真实设备的 ethtool -K eth10 tx off 来解决。
同时要修改 rc.local 将该操作记录到开机启动中。
一点思考
同样的一批 64 台服务器,同样的 tunl 设备通信,有 16 台有问题。
看到这一批网卡跟正常网卡的区别是,异常服务器是定制的网卡,可能跟这个网卡不支持 tunl 设备的校验和计算有关系。
小结
- pod 之间 ICMP 通但 TCP 不通,优先怀疑校验和问题;
tx-checksumming: on表示让网卡在发送时计算校验和,但软件设备(tunl)上可能不生效;- 用
tcpdump -vvv抓包,看checksum incorrect/correct提示; - 关闭
ethtool -K tunl0 tx off可解决; - 同型号网卡也可能有差异,异常网卡可能不支持 tunl 设备的校验和计算。