网关
负责转发源ip地址的请求到目标ip地址。当路由表中将网关设置为0.0.0.0
时,表示源ip地址直连网卡。
跨主机网络 - overlay network
flannel
整个过程参见张磊的极客课程深入剖析Kubernetes 32~35章节
基于UDP的跨主机通信的基本原理如图所示:
可以看到每次数据从一个主机发出去的之前会进行三次用户态和内核态的切换(container0 - docker0, flannel0 - flanneld, flanneld - eth0),非常耗时。所以后来被VXLAN(虚拟可扩展局域网)所取代,如图所示:
docker0和flannel0之间通过路由表进行协作。
在k8s中,有一个单独的网桥来代替docker0,它的名字叫cni网桥,在宿主机上的默认设备名称为cni0
,查看route,可以看到10.244.1.0/24网段都会经过cni0
路由,而10.244.0.0/24、10.244.2.0/24,10.244.3.0/24都会经过flannel.1
路由。flannel.1
是VXLAN中的一个VTEP设备。
1 | [root@n167 ~]# route -n |
k8s中容器网络是由cni插件创建的,cni插件可以有多个,在dockershim启动的时候,会选择一个cni插件(如flannel)作为默认插件。当kubelet创建一个pod的时候,首先创建一个infra容器(由dockershim调用docker api创建),紧接着执行一个叫SetUpPod
的方法,在这个方法里面就会调用cni插件为infra容器配置网络。cni插件在配置网络的时候,首先会将dockershim传过来的Network Configuration进行补充(包括将Delegate的Type设置为bridge,表示交由CNI bridge
插件来配置网络;设置ipam,即设置kubeadm init --pod-network-cidr 10.244.0.0/16
中的子网,路由信息等),交给cni插件的Delegate
插件即CNI bridge
插件来完成网络配置。CNI bridge
插件首先会检查宿主机上CNI网桥即cni0
是否存在,不存在就创建;然后进入infra容器的Net ns中,创建一对Veth Pair设备,eth0
放在容器里面,vethb4963f
放在宿主机上,这就是我们执行命令ifconfig
可以看到的很多以veth开头的网络设备,如图所示:
接下来,CNI bridge
插件会将vethb4963f
设备连接在cni0
网桥上,使得容器和宿主机互通。同时,需要让容器可以“自己访问自己”,即容器里面访问映射到主机上的端口,这时候需要开启Hairpin Mode
。接下来,CNI bridge
插件会调用CNI ipam
插件从ipam.subnet
字段规定的网段中为容器分配一个ip地址并添加到容器里面的eth0
上。最后把ip地址返回给dockershim,并被kubelet写到pod的Status字段。