浅谈k8s网络模型及不同node上Pod如何互访
- k8s网络模型
- CNI
- Kubernetes 使用 CNI 网络插件的基本工作流程:
- pod 网络模型
- 主流 Kubernetes 网络实现方案
- Pod间如何互访
- CNI
k8s网络模型
接上一篇文章:
Kubernetes 对容器技术做了更多的抽象,其中最重要的一点是提出 pod 的概念,pod 是 Kubernetes 资源调度的基本单元,我们可以简单地认为 pod 是容器的一种延伸扩展,从网络的角度来看,pod 必须满足以下条件:
- 每一个 pod 都有独特的 IP 地址,所有 pod 都在一个可以直接连通的、扁平的网络空间中;
- 同一个 pod 内的所有容器共享同一个网络命名空间;
基于这样的基本要求,我们可以知道:
- 同一个 pod 内的所有容器之间共享端口,可直接通过 localhost + port 来访问;
- 由于每个 pod 有单独的 IP,所以不需要考虑容器端口与主机端口映射以及端口冲突问题;
事实上,Kubernetes 进一步确定了对一个合格集群网络的基本要求:
- 任意两个 pod 之间其实是可以直接通信的,无需显式地使用 NAT 进行地址的转换;
- 任意集群节点与任意 pod 之间是可以直接通信的,无需使用明显的地址转换,反之亦然;
- 任意 pod 看到自己的 IP 跟别人看见它所用的 IP 是一样的,中间不能经过地址转换;
也就是说,必须同时满足以上三点的网络模型才能适用于 Kubernetes,事实上,在早期的 Kubernetes 中,并没有什么网络标准,只是提出了以上基本要求,只有满足这些要求的网络才可以部署 Kubernetes,基于这样的底层网络假设,Kubernetes 设计了pod-deployment-service 的经典三层服务访问机制。直到1.1发布,Kubernetes 才开始采用全新的 CNI(Container Network Interface) 网络标准。
CNI
其实,我们在前面介绍容器网络的时候,就提到了 CNI 网络规范,CNI 相对于 CNM(Container Network Model) 对开发者的约束更少、更开放,不依赖于容器运行时。事实上,CNI 规范确实非常简单,详情可以参考github资料:https://github.com/containernetworking/cni/blob/master/SPEC.md
实现一个 CNI 网络插件只需要一个配置文件和一个可执行文件:
- 配置文件描述插件的版本、名称、描述等基本信息;
- 可执行文件会被上层的容器管理平台调用,一个 CNI 可执行文件需要实现将容器加入到网络的 ADD 操作以及将容器从网络中删除的 DEL 操作(以及一个可选的 VERSION 查看版本操作);
Kubernetes 使用 CNI 网络插件的基本工作流程:
- kubelet 先创建 pause 容器创建对应的网络命名空间;
- 根据配置调用具体的 CNI 插件,可以配置成 CNI 插件链来进行链式调用;
- 当 CNI 插件被调用时,它根据环境变量以及命令行参数来获得网络命名空间、容器的网络设备等必要信息,然后执行 ADD 操作;
- CNI 插件给 pause 容器配置正确的网络,pod 中其他的容器都是复用 pause 容器的网络;
如果不清楚什么是 pause 容器,它在pod中处于什么样的位置,请查看从 container 到 pod。
通常来说,CNI 插件可以分为三种:Overlay、路由及 Underlay。
-
Overlay 模式的典型特征是容器独立于主机的 IP 段,这个 IP 段进行跨主机网络通信时是通过在主机之间创建隧道的方式,将整个容器网段的包全都封装成底层的物理网络中主机之间的包。该方式的好处在于它不依赖于底层网络;
-
路由模式中主机和容器也分属不同的网段,它与 Overlay 模式的主要区别在于它的跨主机通信是通过路由打通,无需在不同主机之间做一个隧道封包。但路由打通就需要部分依赖于底层网络,比如说要求底层网络有二层可达的一个能力;
-
Underlay 模式中容器和宿主机位于同一层网络,两者拥有相同的地位。容器之间网络的打通主要依靠于底层网络。因此该模式是强依赖于底层能力的。
了解了以上三种常用的实现模式之后,再根据自己的环境、需求判断可由哪一种模式进行实现,再在对应的模式中去找 CNI 插件。不过社区中有那么多插件,它们又都属于哪种模式?如何进行选择呢?怎么挑选适合自己的呢?我们可以从以下 3 个方面来考虑。
pod 网络模型
要了解 Kubernetes 网络模型的实现原理,我们就要从单个 pod 入手,事实上,一旦熟悉了单个 pod 的网络模型,就会发现 Kubernetes 网络模型基本遵循和容器网络模型一样的原理。
通过前面的笔记从 container 到 pod,我们知道 pod 启动的时候先创建 pause 容器创建对应的网络命名空间,然后与其他容器共享此网络命名空间。而对于单个容器的网络模型我们之前也介绍过,主要就是通过 docker0 网桥设备与 veth 设备对连接不同的容器网络命名空间,由此,我们可以得到如下图所示的单个 pod 网络模型:
主流 Kubernetes 网络实现方案
上一小节我们知道单个 pod 的网络模型是容器网络模型的扩展,但是 pod 与 pod 之间的是怎么相互通信的呢?这其实与容器之间相互通信非常类似,也分为同一个主机上的 pod 之间与跨主机的 pod 之间两种情况。
如容器网络模型一样,对于同一主机上的 pod 之间,通过 docker0 网桥设备直接二层(数据链路层)网络上通过 MAC 地址直接通信:
而跨主机的 pod 之间的相互通信也主要有以下两个思路:
-
修改底层网络设备配置,加入容器网络 IP 地址的管理,修改路由器网关等,该方式主要和 SDN(Software define networking) 结合。
-
完全不修改底层网络设备配置,复用原有的 underlay 网络平面,解决容器跨主机通信,主要有如下两种方式:
-
隧道传输(overlay):将容器的数据包封装到原主机网络的三层或者四层数据包中,然后使用主机网络的 IP 或者 TCP/UDP 传输到目标主机,目标主机拆包后再转发给目标容器。overlay 隧道传输常见方案包括 Vxlan、ipip 等,目前使用 overlay 隧道传输技术的主流容器网络有 Flannel 等;
-
修改主机路由:把容器网络加到主机路由表中,把主机网络设备当作容器网关,通过路由规则转发到指定的主机,实现容器的三层互通。目前通过路由技术实现容器跨主机通信的网络如 Flannel host-gw、Calico 等;
下面简单介绍几种主流的方案:
-
**Flannel **是目前使用最为普遍的方案,提供了多种网络后端,它支持多种数据路径,也适合于 overlay/underlay 等多种场景。对于 overlay 的数据包封装,可以使用用户态的 UDP,内核态的 Vxlan(性能相对较好),甚至在集群规模不大,且处于同一个二层域时可以采用 host-gw 的方式修改主机路由表;
-
**Weave **工作模式与 Flannel 很相似的,它最早只提供了 UDP(称为 sleeve 模式)的网络方式,后来又加上了 fastpass 方式(基于 VxLAN),不过 Weave 消除了 Flannel 中用来存储网络地址的额外组件,自己集成了高可用的数据存储功能;
-
**Calico ** 主要是采用了修改主机路由,节点之间采用 BGP 的协议去进行路由的同步,但是现实中的网络并不总是支持 BGP 路由的,因此 Calico 也支持内核中的 IPIP 模式,使用 overlay 的方式来传输数据;
可以看到,同一个 pod 里面的其他容器共享 pause 容器创建的网络命名空间,也就是说,所有的容器共享相同的网络设备、路由表设置、服务端口等信息,仿佛是在同一台机器上运行的不同进程,所以这些容器之间可以直接通过 localhost + port 通信;对于集群外部的请求,则通过 docker0 网桥设备充当的网关,同时通过 iptables 做地址转换。到这里我们就会发现,这其实就是对单个容器的 bridge 网络模型的扩展。
Pod间如何互访
容器到容器的通信
同一个Pod内的容器可以用localhost地址访问彼此的端口。
Pod之间的通信
同一个Node内Pod之间的通信
不同Node上Pod之间的通信
总结
今天的数据中心包含多个集群以及海量的物理机,Overlay 网络是虚拟机和底层网络设备之间的中间层,通过 Overlay 网络这一个中间层,我们可以解决虚拟机的迁移问题、降低二层核心网络设备的压力并提供更大规模的虚拟网络数量:
-
在使用 VxLAN 构成二层网络中,虚拟机在不同集群、不同可用区和不同数据中心迁移后,仍然可以保证二层网络的可达性,这能够帮助我们保证线上业务的可用性、提升集群的资源利用率、容忍虚拟机和节点的故障;
-
集群中虚拟机的规模可能是物理机是几十倍,与物理机构成的传统集群相比,虚拟机构成的集群包含的 MAC 地址数量可能多一两个数量级,网络设备很难承担如此大规模的二层网络请求,Overlay 网络通过 IP 封包和控制平面可以减少集群中的 MAC 地址表项和 ARP 请求;
-
VxLAN 的协议头使用 24 位的 VNI 表示虚拟网络,总共可以表示 1600 万的虚拟网络,我们可以为不同的虚拟网络单独分配网络带宽,满足多租户的网络隔离需求;
需要注意的是,Overlay 网络只是一种在物理网络上的虚拟网络,使用该技术并不能直接解决集群中的规模性等问题,而 VxLAN 也不是组建 Overlay 网络的唯一方法,在不同场景中我们可以考虑使用不同的技术,例如:NVGRE、GRE 等。