集群网络创建过程
集群网络创建过程
K8S 集群网络配置完成之后,如下图所示:包括集群 CIDR、VPC 路由表、节点网络、节点的 podCIDR、节点上的虚拟网桥 cni0、连接 Pod 和网桥的 veth 等部分
初始阶段
集群的创建,基于云资源 VPC 和 ECS,在创建完 VPC 和 ECS 之后,我们基本上可以得到如下图的资源配置。我们得到一个 VPC,这个 VPC 的网段是 192.168.0.0/16,我们得到若干 ECS,他们从 VPC 网段里分配到 IP 地址。
集群阶段
在以上出初始资源的基础上,利用集群创建控制台得到集群 CIDR。这个值会以参数的形式传给集群节点 provision 脚本,并被脚本传给集群节点配置工具 kubeadm。kubeadm 最后把这个参数写入集群控制器静态 Pod 的 yaml 文件 kube-controller-manager.yaml。
集群控制器有了这个参数,在节点 kubelet 注册节点到集群的时候,集群控制器会为每个注册节点,划分一个子网出来,即为每个节点分配 podCIDR。如上图,Node B 的子网是 172.16.8.1/25,而 Node A 的子网是 172.16.0.128/25。这个配置会记录到集群 node 的 podCIDR 数据项里。
节点阶段
经过以上集群阶段,K8S 有了集群 CIDR,以及为每个节点划分的 podCIDR。在此基础上,集群会下发 flanneld 到每个阶段上,进一步搭建节点上,可以给 Pod 使用的网络框架。这里主要有两个操作:
- 第一个是集群通过 Cloud Controller Manager 给 VPC 配置路由表项。路由表项对每个节点有一条,每一条的意思是,如果 VPC 路由收到的目的地址是某一个节点 podCIDR 的 IP 地址,那么路由会把这个网络包转发到对应的 ECS 上;
- 第二个是创建虚拟网桥 cni0 以及与 cni0 相关的路由。这些配置的作用是,从阶段外部进来的网络包,如果目的 IP 是 podCIDR,则会被节点转发到 cni0 虚拟局域网里。
注意:实际实现上,cni0 的创建,是在第一个使用 Pod 网络的 Pod 被调度到节点上的时候,由下一节中 flannal cni 创建的,但是从逻辑上来说,cni0 属于节点网络,不属于 Pod 网络,所以在此描述。
Pod 阶段
在前边的三个阶段,集群实际上已经为 Pod 之间搭建了网络通信的干道。这个时候,如果集群把一个 Pod 调度到节点上,kubelet 会通过 flannel cni 为这个 Pod 本身创建网络命名空间和 veth 设备,然后,把其中一个 veth 设备加入到 cni0 虚拟网桥里,并为 Pod 内的 veth 设备配置 IP 地址。这样 Pod 就和网络通信的干道连接在了一起。
前一节的 flanneld 和这一节的 flannel cni 完全是两个组件。flanneld 是一个 daemonset 下发到每个节点的 pod,它的作用是搭建网络(干道),而 flannel cni 是节点创建的时候,通过 kubernetes-cni 这个 rpm 包安装的 cni 插件,其被 kubelet 调用,用来为具体的 pod 创建网络(分枝)。理解这两者的区别,有助于我们理解 flanneld 和 flannel cni 相关的配置文件的用途。
通讯
本地通信,说的是 Pod 内部,不同容器之间的通信。因为 Pod 内网容器之间共享一个网络协议栈,所以他们之间的通信,可以通过 loopback 设备完成。
同节点 Pod 之间的通信,是 cni0 虚拟网桥内部的通信,这相当于一个二层局域网内部设备通信。
跨节点 Pod 通信略微复杂一点,但也很直观,发送端数据包,通过 cni0 网桥的网关,流转到节点上,然后经过节点 eth0 发送给 VPC 路由。这里不会经过任何封包操作。当 VPC 路由收到数据包时,它通过查询路由表,确认数据包目的地,并把数据包发送给对应的 ECS 节点。而进去节点之后,因为 flanneld 在节点上创建了 cni0 的路由,所以数据包会被发送到目的地的 cni0 局域网,再到目的地 Pod。
最后一种情况,Pod 与非 Pod 网络的实体通信,需要经过节点上 iptables 规则做 SNAT,而此规则就是 flanneld 依据命令行 –ip-masq 选项做的配置。