概述
kubernetes四层网络模型
上图引用自平凡人笔记-深入理解K8S网络原理上
在此先罗列几个概念
- eth0:是主机上的网卡 也是流量出入的设备 也支持k8s集群节点之间做网络寻址和互通的设备
- docker0:是一个虚拟网桥 简单理解为是一个虚拟交换机 支持节点上面或节点之间进行IP寻址和互通的设备
- veth0:是pod上的虚拟网卡 支持pod内容器互通的设备 内部的容器可以通过localhost相互访问
- network namespace(网络命名空间):将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信。
- Iptables/Netfilter:Netfilter 负责在内核中执行各种挂接的规则(过滤、修改、丢弃等),运行在内核中;Iptables 模式是在用户模式下运行的进程,负责协助维护内核中 Netfilter 的各种规则表;通过二者的配合来实现整个 Linux 网络协议栈中灵活的数据包处理机制。
- Veth Pair:Veth设备对的引入是为了实现在不同网络命名空间的通信,总是以两张虚拟网卡(veth peer)的形式成对出现的。并且,从其中一端发出的数据,总是能在另外一端收到。
单机容器网络
pod内部通信
同一Pod中的任何容器都将共享相同的名称空间和本地网络,容器可以很容易地与其他容器在相同的POD中进行通信,k8s中每个Pod中管理着一组容器,这些容器共享同一个网络命名空间,Pod中的每个容器拥有与Pod相同的IP和port地址空间,并且由于他们在同一个网络命名空间,他们之间可以通过localhost相互访问(可见POD内部的通信是不经过数据IP数据通信通信网络的)。
同节点(宿主机)的pod之间通信
不同pod之间的通信,就是使用linux虚拟以太网设备或者说是由两个虚拟接口组成的以太网接口对使不同的网络命名空间链接起来,这些虚拟接口分布在多个POD上,通过网桥把不同的POD组成为一个以太网,直接进行二层以太网通信。
跨主机容器网络
host之间的通讯需要依赖路由或者借助各种隧道技术,比如vxlan。这些路由和隧道技术大都由第三方提供,比如flannel等。Flannel支持三种后端实现,分别是VXLAN、host-gw、UDP,这三种后端实现代表了3种容器跨主网络的主流实现方法。
UDP方法。对于网段不在docker0网桥内的地址,会通过容器的网关进入docker0网桥(实为CNI网桥,下同)后,出现在宿主机上,并通过路由规则匹配,进入flannel0设备。子网与宿主机的关系保存于etcd中,flanneld进程可以通过目标IP地址匹配到对应的子网并转发相应UDP包。
UDP模式有显著的性能缺点,在使用flannel0的过程中,需要进行三次用户态与内核态之间的数据复制(UDP包的封装与解封装需要在用户态进行),这也是UDP如今逐渐走向废弃的原因。
VXLAN(virtual extensible LAN,虚拟可扩展局域网),是一种Linux内核本身支持的网络虚拟化技术,VXLAN可以直接在内核态完成封装与解封装的操作。VXLAN实现了一层虚拟的网络,使得分布在不同宿主机上的“主机”能如同局域网一般通信。它的隧道规则与UDP方法非常相似,区别在于封装与解封装二层数据帧(Ethernet frame)在内核态完成(因为VXLAN就是Linux内核的一个模块)。
Flannel的host-gw模式是一种“纯三层”(pure layer 3)的网络方案,Flannel会在宿主机上为容器配置路由规则,标记IP的下一跳(next-hop)地址,即子网对应的主机的IP地址,这一主机将会充当容器通信路径的“网关”。
子网和主机的信息都保存在etcd中,flanneld只需要watch这些数据的变化,实时更新路由表即可。
CNI网桥
CNI网桥接管所有CNI插件负责的(kubernetes创建的)容器,其功能与docker的网桥docker0非常相似,但k8s本身不具备配置docker网络模型的能力,也不以docker为默认容器,故一般不引入docker0网桥。
参考文章
《深入剖析Kubernetes》,张磊 著,人民邮电出版社