容器跨主机网络-UDP解析
1. 容器跨主机网络的问题
上一节描述了同一宿主机下容器访问宿主机或其他容器的方式,默认docker配置下,不同宿主机之间的容器网络没有任何关联,所以无法做到跨主通信。要解决跨主通信的问题,就需要在已有的主机网络通过软件再构建一个可以把所有容器连通起来的虚拟网络,这个技术就是我们常聊到的overlay network。容器跨主机的访问常用的主流方法有UDP、VXLAN、host-gw
2.UDP模式
UDP因为性能原因目前基本被弃用,但作为最直接也是最容易的实现,其他方案也基本在此方案上进行改造,所以以该方案开始进行解析。
2.1.flannel UDP详解
执行过程如下:
1. consul-0(10.244.3.40)访问consul-2(10.244.2.91),通过cni0网桥出来。此处在容器的网络解析处已经说明,这里不再细述。
2. 由于ip的默认地址是10.244.2.91,在node-3上执行route,匹配到flannel0设备,该设备是一个TUN设备,TUN设备用于在操作系统和用户应用程序之间传递IP包。
3. 当ip包进入flannel0设备后,flannel进程会收到这个ip包,并进行UDP封装,此时flannel进程只收到目标容器位置,怎么准备找到对应的宿主机呢,这里flannel进程会去读取etcd,根据子网key,找到相关宿主机。在上诉图中涉及两个子网(10.244.3.0/24,10.244.2.0/24),每个宿主机的所有容器都会分配至该宿主机所属的子网。
4. UDP封装dst为宿主机172.253.67.150,则意味着找到了目标容器所属的宿主机。而目标端口8285被flannel进程监听,flannel监听到ip包后会解析封装的原ip包。此时确认需要发往目标地点为10.244.2.91.
5. 通过cni0网桥进入容器访问到consul-2。
2.2.flannel UDP性能分析
相比宿主机直接通信,flannel udp模式下通信额外多了flannel的处理、容器与宿主机之间的通信,这里涉及到三次用户态与内核态的数据复制。在linux操作系统中,上下文切换与用户态操作的代价很大。所以在优化上有个很重要的原则,减少用户态到内核态的切换次数。典型的如零拷贝的实现方式。
用户态和内核态的切换
1. containner到cni0网桥
2. cni0网桥到flanneld进程
3. flanneld进程到ens192.