Flannel

容器跨主通信Flannel

在已有宿主机网络上,再通过软件构建一个覆盖在已有宿主机网络之上的、可以把所有容器连通在一起的虚拟网络,这种技术被称为:Overlay Network(覆盖网络)

Flannel UDP

准备

  • 宿主机Node1上有一个容器container-1,IP地址:100.96.1.2,对应docker0网桥地址:100.96.1.1/24
  • 宿主机Node2上有一个容器container-2,IP地址:100.96.2.3,对应docker0网桥地址:100.96.2.1/24

过程

  • container-1容器里的进程发起IP包,源地址是100.96.1.2,目的地址就是100.96.2.3。由于不在Node1的docker0网桥的网段,所以这个IP包会被交给默认路由规则,从而出现在宿主机上
  • 这个IP包的下一个目的地,取决于宿主机上的路由规则。Flannel已经在宿主机上创建出了一系列路由规则,会进入flannel0的设备中
    • 100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.2.0 flannel设备
    • 100.96.1.0/24 dev docker0 proto kernel scope link src 100.96.2.1 本机flannel分配的网段
  • flannel0设备是一个TUN设备,工作在三层的虚拟设备:在操作系统内核和用户应用程序之间传递IP包
  • 当操作系统将一个IP包发送给flannel0设备之后,flannel0就会把这个IP包交给Flannel进程,这是从内核态向用户态的流动;反之Flannel进程向flannel0设备发送一个IP包,那么这个IP包就会出现在宿主机网络栈中,然后根据宿主机的路由表进行下一步处理,这是用户态向内核态的流动
  • 所以,当 IP 包从容器经过 docker0 出现在宿主机,然后又根据路由表进入 flannel0 设备后,宿主机上的 flanneld 进程(Flannel 项目在每个宿主机上的主进程),就会收到这个 IP 包。然后,flanneld 看到了这个 IP 包的目的地址,是 100.96.2.3,就把它发送给了 Node 2 宿主机。
  • flanneld收到container-1发送给container-2的IP包之后,就会把这个IP包直接封装在一个UDP包里,然后发送给Node2,UDP包的源地址就是flanneld所在Node1的地址,而目的地址,则是container-2所在宿主机Node2的地址
  • 这个请求得以完成的原因是,每台宿主机上的 flanneld,都监听着一个 8285 端口,所以 flanneld 只要把 UDP 包发往 Node 2 的 8285 端口即可。
  • container-2所在宿主机的flanneld从UDP包中解析出封装在里面的原IP包,发送给flannel0设备
  • 通过本机的路由表来寻找IP包的流向,第三条路由规则发送给docker0网桥
  • 通过docker网桥原理,docker0网桥地址范围分配为Flannel为宿主机分配的子网,通过bip参数设置

flannel 如何知道这个IP地址对应的容器,是运行在Node2上的

  • flannel事先给Node节点分配子网如100.96.2.0/24 ,将子网与宿主机的对应关系保存在Etcd中。
  • 所以,flanneld 进程在处理由 flannel0 传入的 IP 包时,就可以根据目的 IP 的地址(比如 100.96.2.3),匹配到对应的子网(比如 100.96.2.0/24),从 Etcd 中找到这个子网对应的宿主机的 IP 地址是 10.168.0.3

UDP模式有严重的性能问题

  1. 仅在发出IP包的过程中,就需要经过三次用户态和内核态之间的数据拷贝

image.png

  1. Flannel进行UDP封装和解封装的过程,都是用户态完成的,代价是比较高的

Flannel VXLAN

VXLAN:Virtual Extensible LAN(虚拟可扩展局域网),是Linux内核本身就支持的一种网络虚拟化技术。VXLAN可以完全在内核态实现上述封装和解封装的工作

VXLAN的覆盖网络设计思想:在现有三层网络之上,”覆盖“一层虚拟的、由内核VXLAN模块负责维护的二层网络。

VXLAN在宿主机上设置一个特殊的网络设备作为”隧道“的两端。这个设备就叫做VTEP,它和flanneld进程非常相似,只不过进行封装和解封装的对象是二层数据帧,全部在内核完成

数据包流程

  • 源IP:10.1.15.2 目IP:10.1.16.3的数据包经过docker0网桥

  • 路由到本机的flannel.1设备处

  • 获取需要封装目的VTEP设备信息的IP和MAC

    • 每台宿主机上的flanneld进程负责维护,每次新加入节点flanneld中会添加一条路由规则,有目的IP地址
    • mac地址也由flanneld维护
  • Linux内核开始二层封装工作,添加Inner Ethernet Header(目的VTEP设备的MAC地址),Inner IP Header(目的容器的IP地址),单纯添加头

  • 上面的VTEP设备的MAC地址对宿主机网络没有作用,需要额外封装成普通数据帧

  • 封装一个VXLAN头,其中头有一个重要的标志叫做VNI,它是VTEP设备识别某个数据帧是不是归自己处理,在Flannel中,VNI默认是1

  • flannel.1设备实际扮演一个”网桥“的角色,在Linux内核里,网桥设备转发的依据是一个叫做FDB(Forwarding Database)的转发数据库。flannel.1的FDB也是flanneld维护。通过之前的VTEP的mac地址可以找到目的主机IP

  • 目的主机的MAC,通过Node1 ARP表要学习的内容
    image20210826000406044.png

  • 封包完成

  • Node1上的flannel.1设备把这个数据帧从Node1的eth0网卡发出去,经过Node2的eth0网卡

  • Node2的内核网络栈发现数据帧中的VXLAN Header,并且VNI=1,内核进行拆包,交给flannel.1设备

  • 而flannel.1设备进行进一步拆包,取出”原始IP包“
    image20210826000758597.png

# k8s  

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×