文章目录
前言
在传统的单机环境下,容器之间的网络通信相对简单,通常通过Docker默认的网桥模式就可以实现。然而,将容器部署到分布式的集群环境中时,跨主机的容器网络通信就成为了一个亟待解决的问题。因为在Docker的默认配置下,不同宿主机上的容器是无法直接通过IP地址进行互相访问的。这是因为每个宿主机上的Docker网络都是独立的,它们各自管理着自己的私有网段。这种隔离虽然在安全性方面有所裨益,但也阻碍了容器之间的直接通信。
因此为了解决这个"跨主通信"的难题,容器社区提出了多种网络方案。这些方案的核心目标是在不同宿主机上的容器之间建立一个虚拟的网络,使得它们能够像在同一个局域网内一样进行通信。这就是所谓的"覆盖网络"(Overlay Network)技术。
一、了解overlay、underlay容器网络
underlay容器网络
代表承载容器的虚拟机或者物理机网络环境能够识别、转发容器ip。开源网络插件方案如Flannel的host-gw模式、calico的bgp模式。
容器网络可以不通过隧道封装,依托于网络插件组件功能(增加路由表)和网络要求(k8s管理的节点在同一子网,不跨三层网络)
overlay容器网络
代表承载容器的虚拟机或者物理机网络环境能够识别、转发容器ip。需要通过每个虚拟机上的封包、解包处理后在转发给容器。
开源网络插件方案如Flannel的vxlan模式、calico的ipip模式.
容器网络通过节点隧道封装后基于承载网络转发,只要求kubernetes管理的节点三层网络可达
二、网络通信
1.分类
(1)容器间通信:
同一个pod内的多个容器间的通信,通过lo即可实现;
(2)pod之间的通信:
同一节点的pod之间通过cni网桥转发数据包。
不同节点的pod之间的通信需要网络插件支持。
(3)pod和service通信:
通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs只能做负载均衡,而做不了nat转换。
(4)pod和外网通信:
iptables的MASQUERADE。
(5)Service与集群外部客户端的通信:
(ingress、nodeport、loadbalancer...)
2.网络虚拟设备对
2.1、什么是网络虚拟设备对veth pair?
veth是虚拟以太网卡的缩写。veth设备总是成对的,因此称为veth pair.一端发送数据,另一端接收数据,常被用于跨网络空间的通信。
但如果仅有veth pair设备,容器是无法访问外部网络的,因为从容器发出的数据包实际上进入了veth pair设备对的协议栈,如果容器需要访问网络还需要
使用网桥bridge等技术将veth pair设备接收的数据包通过某种方式转发出去。以下是veth pair的基本工作原理
2.2、如何查看容器的网卡与主机的哪个veth设备对是成对的关系?
方法一
在容器查看该文件中的值 cat /sys/class/net/eth0/iflink
在主机查看 /sys/class/net下面的所有的子目录ifindex的值和容器里查出来的值进行对比,一样的话就是一个设备对
方法二
在容器执行 ip link show eth0,如下所示
116: eth0@if117: xxxx
从这个可以看出116是eth0接口的index,117是和它成对的veth的index
在主机上执行 ip link show | grep 117即可查看设备对
3、vxlan和vtep
3.1、vtep
VTEP设备是Flannel VXLAN模式的核心组件,它通过在物理网络之上构建虚拟覆盖网络,实现了高效、灵活的容器跨主机通信。
为了能够在二层网络上打通“隧道”,VXLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。
这个设备就叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)
作用
VTEP设备在每个宿主机上都会被创建,通常命名为flannel.1。这个设备既有IP地址,也有MAC地址,可以被视为一个虚拟的网络接口。
VTEP设备的主要作用:
是执行VXLAN封装和解封装操作,使得容器可以在不同宿主机之间进行通信.
注意事项:
它进行封装和解封装的对象,是二层数据帧(Ethernet frame),而且这个工作的执行流程,
全部是在内核里完成的(因为 VXLAN 本身就是 Linux 内核中的一个模块)
当在k8s宿主机上查看网络设备时,可以看到flannel.1设备的存在
[root@k8s-master~]# ip addr show flannel.1
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN
link/ether c6:58:f3:29:cb:d8 brd ff:ff:ff:ff:ff:ff
inet 10.244.1.0/32 brd 10.244.1.0 scope global flannel.1
valid_lft forever preferred_lft forever
inet6 fe80::c458:f3ff:fe29:cbd8/64 scope link
valid_lft forever preferred_lft forever
从上述输出中,我们可以看到flannel.1设备的MAC地址和IP地址。这些信息在VXLAN网络中用于标识不同的VTEP设备
优点
VTEP设备的引入使得Flannel能够在现有的三层网络上构建一个虚拟的二层网络。
这种方式不仅保证了容器网络的隔离性,还提供了良好的可扩展性。
与UDP模式相比,VXLAN模式的VTEP设备能够在内核态完成封装和解封装操作,大大减少了用户态和内核态之间的切换,从而提高了网络性能。
此外,VTEP设备还支持多播和广播,这使得ARP请求和DHCP等基于广播的协议能够在VXLAN网络中正常工作。这一特性进一步增强了VXLAN网络的灵活性和兼容性
3.2、vxlan相关概念
vxlan作用
VXLAN (Virtual Extensible LAN) 是一种覆盖网络技术,全称是虚拟可扩展的局域网。
1、它主要用于解决传统 VLAN 技术的一些限制,如 VLAN ID 数量限制(只有4096个)。
VXLAN 可以支持高达1600万个虚拟网络,极大地扩展了网络的规模和灵活性。
2、提供封装与隧道技术
VXLAN 通过封装原始的以太网帧(Layer 2)到 UDP 数据包(Layer 3)中来工作。
这意味着它可以跨越不同的网络和子网,实现跨网络边界的通信。
3、提供VXLAN 网络标识符 (VNI)
每个 VXLAN 网络都有一个唯一的标识符,称为 VNI(VXLAN Network Identifier),它提供了地址隔离
确保各个 VXLAN 网络之间的数据包不会互相干扰
4、提供VTEP(VXLAN Tunnel Endpoint)
VTEP 是 VXLAN 架构中的端点设备,负责封装和解封装数据包,且这个工作的执行流程,全部是在内核里完成的。
每个通过 VXLAN 通信的网络设备都有一个或多个 VTEP
vxlan通信流程---啰嗦版
1、每台设备上已经有了VTEP设备和相应的路由规则,源容器发出请求后,数据包包含了源容器ip和目的容器ip,
这个原始数据包首先会通过虚拟网卡对出现在docker0网桥上,然后根据路由规则到达VTEP设备,
且要发往的网关地址为目的VTEP设备的ip,然后VTEP会从ARP表里获取到对应的MAC地址,并进行二层封包,得到一个二层数据帧,
我们把它称为“内部数据帧”。
2、 接下来,Linux 内核会在“内部数据帧”前面,加上一个特殊的 VXLAN 头,用来表示这实际上是一个 VXLAN 要使用的数据帧,
而这个 VXLAN 头里有一个重要的标志叫作 VNI,它是 VTEP 设备识别某个数据帧是不是应该归自己处理的重要标识,
而在 Flannel 中,VNI 的默认值是 1
3、然后,Linux 内核会从FDB数据库里读取到对应的目的宿主机ip,把“内部数据帧”和目的宿主机ip封装进一个 UDP 包里,
我们把它称为“外部数据帧”,这个“外部数据帧”里包含了源节点ip和目的节点ip,
然后Linux内核会在这个“外部数据帧”前面加上目的宿主机的MAC地址,这样,封包工作就宣告完成了。
4、接下来,源宿主机上的 flannel.1 设备就可以把这个数据帧从源宿主机的 eth0 网卡发出去,
数据帧会经过宿主机网络来到目的宿主机的 eth0 网卡。这时候,目的宿主机的内核网络栈会发现这个数据帧里有 VXLAN Header,
并且 VNI=1。所以 Linux 内核会对它进行拆包,拿到里面的内部数据帧,然后根据 VNI 的值,把它交给 flannel.1 设备。
而 flannel.1 设备则会进一步拆包,取出“原始 IP 包”,
然后根据路由规则,将它交给docker0网桥,经过虚拟网卡对就进入到了目的容器里。
vxlan通信流程---精简版
1、首先,当一个容器发送数据包到另一个宿主机上的容器时,这个数据包会被路由到本机的VTEP设备。
2、然后,VTEP设备会对这个原始数据包进行VXLAN封装。
封装过程中,VTEP会在原始数据包外层添加VXLAN头部、UDP头部、IP头部和以太网头部。
这个过程将原始的二层数据帧封装成一个可以在物理网络中传输的UDP数据包。
3、接下来,封装后的数据包会通过物理网络发送到目标宿主机。
4、在目标宿主机上,该主机的VTEP设备会接收到这个封装后的数据包,并进行解封装操作。
解封装过程会移除外层的头部信息,还原出原始的数据包。
5、最后,解封装后的原始数据包会被转发到目标容器。
上述vxlan通信过程可以使用下方图进行一个描述
三、Flannel网络模式剖析
0、flannel的作用
1、协助k8s,给每一个Node上的Docker容器分配互相不冲突的IP地址。
2、建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动的传递到目标容器。
覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。
覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离,在将封装的数据包转发到端点后,将其解封装。
3、创建一个新的虚拟网卡Flannel0接收docker网桥的数据,通过维护路由表,对接受到的数据进行封包和转发。
4、etcd保证了所有node上flanneld所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化
1、flannel三种网络模式
udp网络模式
UDP 模式是 Flannel 最早支持的一种实现方式。
它通过在用户态将容器间通信的数据包封装在 UDP 包中进行传输。
虽然实现简单直观,但由于涉及频繁的用户态与内核态切换,以及数据的多次拷贝,导致性能较差。因此,UDP 模式目前已被弃用。
host-gw网络模式
host-gw(host gateway)模式是一种直接利用宿主机作为网关的实现方式。
它通过在各个宿主机上添加路由规则,将目标容器所在宿主机的 IP 地址设置为网关,从而实现容器跨主机通信。
这种模式性能较高,但要求所有宿主机都在同一个二层网络内
【工作原理】
当容器需要与其他宿主机上的容器通信时,数据包会先发送到本机的网桥设备。
然后,根据路由表,数据包会被转发到目标容器所在的宿主机。
目标宿主机接收到数据包后,再将其转发给目标容器。
【优点】
性能高:由于不需要额外的封装和解封装过程,host-gw模式的性能接近于原生网络。
配置简单:不需要额外的网络设备或协议支持。
【缺点】
要求所有宿主机在同一个二层网络:这限制了其在跨数据中心或云环境中的应用。
路由表膨胀:随着节点数量的增加,每个节点上的路由表会变得很大。
vxlan网络模式
VXLAN(Virtual Extensible LAN)是 Linux 内核原生支持的网络虚拟化技术。
它通过在现有的三层网络上覆盖一层虚拟的二层网络,实现了跨主机的容器通信。
VXLAN 模式能够在内核态完成封装和解封装工作,因此性能较好,逐渐成为了主流的容器网络方案。
【工作原理】
当容器需要与其他宿主机上的容器通信时,数据包会被路由到本机的VTEP设备
然后,VTEP设备会对这个原始数据包在内核进行VXLAN封装,将原始的二层数据帧封装成一个可以在物理网络中传输的UDP数据包
封装后的数据包会通过物理网络发送到目标宿主机。在目标宿主机上,该主机的VTEP设备会接收到这个封装后的数据包,并进行解封装操作。
解封装过程会移除外层的头部信息,还原出原始的数据包。
【优点】
性能高:在内核态完成封装和解封装工作
覆盖和底层网络是完全独立的,因此如果底层网络拓扑发生变化,覆盖网络不会受到影响
2、通过UDP网络模式剖析奠定后续基础
2.1、跨主机容器通信示例
为了理解Flannel的UDP模式工作原理,来看一个具体的跨主机容器通信示例。
假设有两台宿主机:Node 1和Node 2,其中:
在Node 1上,我们有一个名为container-1的容器,其IP地址为10.244.0.13。对应的docker0网桥地址是10.244.0.1/24。
在Node 2上,我们有另一个名为container-2的容器,其IP地址为10.244.1.14。对应的docker0网桥地址是10.244.1.1/24。