插件介绍
flannel项目本身只是一个框架 真正为用户提供容器网络功能的是后端实现 目前支持三种方式
1.VXLAN
2.host-gw
3.UDP
flannel会在宿主机上创建一个flannel0设备和创建一系列的路由表规则
flannel0设备介绍
负责在操作系统内核和用户应用程序之间传递IP包
1.内核态向用户态流动
当操作系统将一个IP包发送给flannel0设备后,flannel0设备就会把这个IP包交给
创建这个设备的应用程序也就是flanneld进程
2.用户态向内核态流动
flanneld进程向flannel0设备发送了一个IP包 这个IP包就会出现在宿主机的网络栈中 然后根据宿主机上的路由表规则处理
flannel子网
每台宿主机都会被flannel分配一个单独的子网段
每台宿主机上的所有容器地址都是这个子网段中的一个IP地址
子网信息和宿主机的对应关系都保存在etcd中
必须把docker0网桥的地址范围设置成flannel为宿主机分配的子网
dockderd --bip=flannel_subnet
UDP模式
UDP数据包封装模式
容器进程 -> docker0 >内核 用户态到内核态
内核 > flannel0 > flanneld进程 内核态到用户态
flanneld进程 > 内核 > eth0物理机网卡发出 用户态到内核态
由于UDP模式在内核态和用户态切换次数过多 所以性能比较差
系统级别编程的优化原则就是要减少用户态到内核态的切换次数 并且把核心的处理逻辑都放在内核态进行
数据包流程分析
UDP包的源地址和目标地址都是物理机地址 目标主机的flanneld进程在收到UDP包后
1.flanneld进程解析UDP包里的容器源IP和目标容器IP然后把解析后的包发给flannel0设备
2.操作系统自动接收flannel0中的数据 根据宿主机路由表转发到docker0设备
3.docker0通过自身的端口找到目标容器
VXLAN模式
VXLAN本身是Linux内核自带的模块 完全可以在内核态实现封装和解封装的操作
VXLAN的设计思想
在现有的三层网络上 构建一个虚拟的 由内核VXLAN模块负责维护的二层网络
使得连接在这个VXLAN二层网络中的虚拟机或者容器可以像在一个LAN中自由通信
在一个LAN中的所有主机相当于连接在一个交换机上 通过交换机就可以找到目标机
VTEP虚拟隧道端点设备 在宿主机上创建的设备叫flannel1
VTEP设备既有自己的IP地址 也有自己的MAC地址
VTEP设备和flannel0设备的作用相同 区别在于VTEP设备封装和解封装的对象是二层数据帧
flannel0设备封装和解封装的对象是UDP数据包
通过每个宿主机上的VTEP设备组成了一个虚拟的二层网络 通过二层数据帧进行通信
二层通信需要封装源MAC地址和目标MAC地址
根据目标IP来查找目标的MAC地址 是通过ARP表来实现的
flanneld进程会在每个节点上自动维护VTEP的IP和MAC地址的对应关系
ip neigh show dev flannel.1
flanneld进程
1.维护主机路由表 记录网段 网关 处理网卡设备信息
根据路由记录找到目标设备的IP地址
2.维护VTEP设备的ARP表 记录VTEP的IP和MAC地址的对应关系
根据目标设备的IP地址找到目标设备的MAC地址
3.维护FDB 网桥转发规则 记录VTEP的MAC地址和宿主机IP对应关系
4.flannel子网和宿主机之间的对应关系
flanneld做为宿主机上的一个用户进程 它们之间只要宿主机能相互通信
那么每个宿主机上的flanneld进程是可以通过宿主机网络相互传递数据包的
最新版本的 Flannel 并不依赖 L3 MISS 事件和 ARP 学习,而会在每台节点启动时把它的 VTEP 设备对应的 ARP 记录,直接下放到其他每台宿主机上
封装好VTEP设备的MAC地址(内部数据帧),对于宿主机网络来说并没有什么实际意义所以上面封装出来的这个数据帧,并不能在我们的宿主机二层网络里传输
所以接下来,Linux 内核还需要再把“内部数据帧”进一步封装成为宿主机网络里的一个普通的数据帧,好让它“载着”“内部数据帧”,通过宿主机的eth0网卡进行传输
VNI机制
Linux 内核会在“内部数据帧”前面,加上一个特殊的 VXLAN 头,用来表示这个“乘客”实际上是一个 VXLAN 要使用的数据帧。而这个 VXLAN 头里有一个重要的标志叫作 VNI,它 是 VTEP 设备识别某个数据帧是不是应该归自己处理的重要标识。而在Flannel中,VNI 的默认值是1,这也是为何宿主机上的 VTEP 设备都叫作flannel.1 的原因,这里的“1”,其 实就是 VNI 的值
VXLAN模式组建的覆盖网络,其实就是一个由不同宿主机上的VTEP设备,也就是 flannel.1 设备组成的虚拟二层网络.对于VTEP设备来说,它发出的“内部数据帧”就仿佛是一直在这个虚拟的二层网络上流动.这,也正是覆盖网络的含义
UDP模式原理
通过的是两个宿主机之间UDP通信 直接像目标主机发送UDP数据包即可(只要求宿主机之间可以相互访问即可)
通过flannel维护了一个子网(容器网段)和宿主机IP的对应关系路由规则即可
VXLAN模式原理
通过VXLAN搭建的一个虚拟二层网络 二层网络通信就必须由自己的MAC地址才行
创建自己的VTEP设备(有自己的IP和MAC地址) IP是用来给路由表用的 MAC地址是用来在虚拟二层网络中通信用的
封装好的二层数据帧本质上还是走的宿主机之间的UDP通信机制 也只要求宿主机之间能够连通即可
目标容器IP 根据路由规则找到 目标VTEP设备的IP 目标设备IP 根据ARP表找到目标设备MAC 目标MAC地址根据FDB表找到目标宿主机IP
找到目标宿主机IP就变成了两个宿主机之间的UDP通信 封装和解析UDP包的内容交给了f'lannel和其创建的独特的网络设备
host-gw模式
三层网络方案 而在这种模式下 容器通信的过程就免除了额外的封包和解包带来的性能损耗
host-gw 模式能够正常工作的核心,就在于 IP 包在封装成帧发送出去的时候,会使用路由表里的“下一跳”来设置目的 MAC 地址。这样,它就会经过二层网络到达目的宿主机。
flannel host-gw 模式必须要求集群宿主机之间是二层连通的
由flanneld负责创建和维护路由规则
在宿主机10.168.0.2执行ip route...
10.244.1.0/24 via 10.168.0.3 dev eth0
10.244.1.0/24 目标容器网段
10.168.0.3 容器网段所对应的宿主机
dev eth0 源主机上的处理网络设备
目的IP地址属于 10.244.1.0/24 网段的IP包,应该经过本机的 eth0 设备发出去(即:dev eth0;
并且它下一跳地址(next-hop)是 10.168.0.3(即:via 10.168.0.3)
所谓下一跳地址就是:如果IP包从主机A发到主机B,需要经过路由设备X的中转
那么X的IP地址就应该配置为主机A的下一跳地址
10.244.1.x是宿主机10.168.0.3创建的容器ip地址段 当10.168.0.2主机
上的容器要访问10.244.1.x容器的时候 IP包从网络层进入链路层2主机会把
下一跳地址的MAC地址(3主机MAC)封装成目标MAC地址
正因如此就要求两个宿主机10.168.0.2和10.168.0.3必须在同一个二层网络中 只有这样两个主机才能直接通过MAC地址通信