问题
在一次k8s容器网络排障的时候,发现从容器内部经过节点访问外部业务的时候,时通时不通,经过抓包,发现大量了报错TCP Port numbers reused,详细信息是A new tcp session is started with the same ports as an earlier session in this trace。推测容器网络异常跟TCP端口重用有关。
TCP端口重用
遇到 "TCP Port numbers reused" 的情况通常指的是在一段时间内,同一组源和目的IP地址与端口号的组合被多次使用来建立TCP连接。在TCP/IP协议中,每个连接都是由四元组(源IP,源端口,目的IP,目的端口)唯一标识的。当一个连接被关闭后,其端口通常会进入TIME_WAIT状态,等待一定时间(通常是2MSL,即最大段生存期的两倍)之后才被系统回收,以确保任何在网络中可能滞留的旧数据包不会干扰新建立的连接。
排查
经过检查,发现在节点上,配置了nodeport访问,默认端口一般是30000-32767,而该节点默认的sysctl 参数 net.ipv4.ip_local_port_range指定的TCP发起连接端口范围1024 65535,会导致系统分配给 TCP 客户端的端口可能与 NodePort 相同,从而导致出现问题。简单来说,当pod从节点访问出去使用了源端口32767,而此时nodeport也使用了32767作为目的端口,因此导致端口重用,TCP连接异常。
解决办法
修改net.ipv4.ip_local_port_range参数
将其改为32768 60999,避免与nodeport端口分配范围相同
#确认参数
sysctl -a|grep net.ipv4.ip_local_port_range
#修改参数
vim /etc/sysctl.conf
#按照如下修改
net.ipv4.ip_local_port_range = 32768 60999
#保存生效
sysctl -p
修改k8s默认的nodeport范围
也可以考虑修改k8s默认端口范围,避免与 net.ipv4.ip_local_port_range相同,还可以按照网络安全限制要要求修改,例如修改为30000-52767
#登录master节点。修改kube-apiservice的配置文件,添加--service-node-port-range=30000-52767字段
# vi /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.25.80:6443
creationTimestamp: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:icon
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.25.80
#......省略一些参数
- --service-cluster-ip-range=10.96.0.0/12
- --service-node-port-range=30000-52767 #在这里添加nodeport范围字段
#......省略一些参数
#修改完成后重启kube-apiservice
# 1. 删除kube-api容器
docker ps -a|awk '/kube-api/{cmd="docker rm -f "$1;system(cmd)}'
# 2. 重启kubelet
systemctl restart kubelet
# 3. 等待kube-api容器重新拉取,确认正常运行
docker ps -a|grep kube-api
#其他master也这样执行
关于k8s节点内核参数优化
以下是常用的节点内核参数优化