背景:在工作中遇到需要为k8s集群扩容(原集群主机:10.33.44.116/24网段),增加不同网段(10.33.44.208/24)的主机到k8s集群中。
步骤一:两个网段的主机双向开通网络策略。
tcp udp icmp协议的全部端口双向开通,在208网段和116网段的主机都要开通
步骤二:添加主机到集群中
【不完全记录】:因为增加节点的实际的操作人是其他同事,有些步骤我不清楚。
遇到的问题:
1、新增的机器能正常创建pod,状态也是正常的,但是在跨pod通信时(具体提现为一个pod通过http:POST请求集群中的服务时(http://serivename.namespace:8080/filename))出现以下报错:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for “http://xxx-test.incstest:8080/xxx”: connect timed out;
nested exception is java.net.SocketTimeoutException: connect timed out
但是将两个程序部署在同个pod的两个容器中,调用就能正常发起。
2、在写入数据到数据库中报错
org.springframework.data.redis.RedisConnectionFailureException: java.net.SocketException: Connection timed out (Write failed); nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Connection timed out (Write failed)
原因:MTU值设置。116网段机器网卡MTU值是1500,calico中配置的是1500,而208网段的MTU值为1450。calico的IPIP模式中数据包是经过tunnel传输,会封装一个新的20字节的ip包头,所以当发送大量数据时,calico生成的1450大小的数据包再加上20大小的ip包头,就无法通过eth0网卡来转发通过calico的通信数据包
解决:将veth_mtu参数设置为1450-50=1400
参考:k8s集群通信故障
扩展:
1、MTU:通信术语
最大传输单元(Maximum Transmission Unit)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。一般本地的MTU值要比网卡的MTU值小
参考:
MTU查看与修改
2、k8s网络
首先来了解容器网络。参考:
容器网络1
容器网络详解
容器网络模型:
在机器中每创建一个容器,都会新增一对虚拟网络设备接口veth pair。一个在主机上可以查,一个在容器中可查。
参考:k8s集群网络
k8s中同网段通信走的是二层路由
k8s中不同网段通信走的是三层路由
k8s中同个pod不同容器拥有同一个网络栈,其实就相当于一台主机上的不同进程。所以同个pod的不同容器通信时不需要经过网卡和虚拟网络设备接口。这也是为什么服务在调用同个pod中的另一个容器中的服务http://xxx-test.incstest:8080/xxx时不会失败。即使MTU值设置不合理。
k8s的网桥:
CNI即容器网络的API接口。它是k8s中标准的一个调用网络实现的接口,kubelet通过这个API来调用不同的网络插件以实现不同的网络配置,实现了这个接口的就是CNI插件。如:calico、flannel等。
CNI维护了一个单独的网桥来代替 docker0。这个网桥的名字就叫作:CNI 网桥,它在宿主机上的设备名称默认是:cni0。
CNI插件有三种网络实现模式:
overlay:
三层路由模式:
三层路由模式下的flannel(host-gw):
当node1(10.168.0.2/24;cni0:10.244.1.0/24)上container-1(10.244.0.2)要发数据给node2(10.168.0.3/24;cni0:10.244.1.0/24)上的container2(10.244.1.3)时,会匹配到如下的路由表
10.244.1.0/24 via 10.168.0.3 dev eth0
以上可以看到host-gw工作原理,其实就是在每个node节点配置到每个pod网段的下一跳为pod网段所在的node节点IP,pod网段和node节点ip的映射关系,flannel保存在etcd或者k8s中。flannel只需要watch 这些数据的变化来动态更新路由表即可。
这种网络模式最大的好处就是避免了额外的封包和解包带来的网络性能损耗。缺点我们也能看见主要就是容器ip包通过下一跳出去时,必须要二层通信封装成数据帧发送到下一跳。如果不在同个二层局域网,那么就要交给三层网关,而此时网关是不知道目标容器网络的(也可以静态在每个网关配置pod网段路由)。所以flannel host-gw必须要求集群宿主机是二层互通的(宿主机需要是同一网段?)。
三次路由模式下的calico:
不同于flannel通过k8s或者etcd存储的数据来维护本机路由信息的做法,calico是通过BGP动态路由协议来分发整个集群路由信息。
calico还和flannel host-gw不同之处在于,它不会创建网桥设备,而是通过路由表来维护每个pod的通信。
这样一来,随着节点规模数量N的增加,连接会以N的2次方增长,会集群网络本身带来巨大压力。
所以一般这种模式推荐的集群规模在50节点左右,超过50节点推荐使用另外一种RR(Router Reflector)模式。
underlay网络: