Kubernetes网络模型
Kubernetes 是通过一个叫作 CNI 的接口,维护了一个单独的网桥来代替 docker0。
这个网桥的名字就叫作:CNI 网桥,它在宿主机上的设备名称默认是:cni0。
在这里,Kubernetes 为 Flannel 分配的子网范围是 10.244.0.0/16。
这个参数可以在部署的时候指定,比如:
1 | kubeadm init --pod-network-cidr=10.244.0.0/16 |
注:也可以在部署完成后,通过修改 kube-controller-manager 的配置文件来指定。
假设 Infra-container-1 要访问 Infra-container-2(也就是 Pod-1 要访问 Pod-2)
,这个 IP 包的源地址就是 10.244.0.2,目的 IP 地址是 10.244.1.3。而此时,Infra-container-1 里的 eth0 设备,同样是以 Veth Pair 的方式连接在 Node 1 的 cni0 网桥上。所以这个 IP 包就会经过 cni0 网桥出现在宿主机上。
需要注意的是,CNI 网桥只是接管所有 CNI 插件负责的、即 Kubernetes 创建的容器(Pod
)。而此时,如果你用 docker run 单独启动一个容器,那么 Docker 项目还是会把
这个容器连接到 docker0 网桥上。所以这个容器的 IP 地址,一定是属于 docker0 网桥的
172.17.0.0/16 网段。
Kubernetes 之所以要设置这样一个与 docker0 网桥功能几乎一样的 CNI 网桥,主要原因
包括两个方面:
- Kubernetes 项目并没有使用 Docker 的网络模型(CNM),所以它并不希望、也不具备配置 docker0 网桥的能力;
- 这还与 Kubernetes 如何配置 Pod,也就是 Infra 容器的 Network Namespace 密切相关。
我们知道,Kubernetes 创建一个 Pod 的第一步,就是创建并启动一个 Infra 容器,用
来“hold”住这个 Pod 的 Network Namespace,所以,CNI 的设计思想,就是:Kubernetes 在启动 Infra 容器之后,就可以直接调用CNI 网络插件,为这个 Infra 容器的 Network Namespace,配置符合预期的网络栈。
CNI 插件的部署和实现方式
我们在部署 Kubernetes 的时候,有一个步骤是安装 kubernetes-cni 包,它的目的就是在
宿主机上安装CNI 插件所需的基础可执行文件。
在安装完成后,你可以在宿主机的 /opt/cni/bin 目录下看到它们
这些 CNI 的基础可执行文件,按照功能可以分为三类:
- 第一类:Main 插件,它是用来创建具体网络设备的二进制文件。
- 第二类: IPAM(IP Address Management)插件,它是负责分配 IP 地址的二进制文件。
- 第三类:由 CNI 社区维护的内置 CNI 插件。
接下来,你就需要在宿主机上安装 flanneld(网络方案本身)。而在这个过程中,flanneld 启动后会在每台宿主机上生成它对应的CNI 配置文件(它其实是一个ConfigMap),从而告诉 Kubernetes,这个集群要使用 Flannel 作为容器网络方案。
总结
Kubernetes 网络模型
- 所有容器都可以直接使用 IP 地址与其他容器通信,而无需使用 NAT。
- 所有宿主机都可以直接使用 IP 地址与所有容器通信,而无需使用 NAT。反之亦然。
- 容器自己“看到”的自己的 IP 地址,和别人(宿主机或者容器)看到的地址是完全一样的。
容器与容器之间要“通”,容器与宿主机之间也要“通”。并且,Kubernetes 要求这个“通”还必须是直接基于容器和宿主机的 IP 地址来进行的。