匿名
未登录
登录
Linux78|wiki
搜索
查看“Flannel网络方案”的源代码
来自Linux78|wiki
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
Flannel网络方案
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
wiki:用户|用户
您可以查看与复制此页面的源代码。
Fannel项目是CoreOS公司主推的容器网络方案。目前实现的技术有三种,分别是: *UDP *Vxlan *Host-GW === UDP方式 === Udp方式是Fannel项目最早支持的,也是性能最差的一种。目前已经被弃用,不过,这种方式最直接、也是最容易理解的跨主机实现。 [[文件:Fannel-1.jpg|有框|居中|Fannel-1]] 如图Fannel-1,有两台宿主机节点1和节点2,分别有下面的配置: 节点1:有容器1,IP地址是100.96.1.2,对应的docker0网桥IP地址是100.96.1.1,网络插件后台fanneld在udp端口8285上侦听,并创建了tun设备fannel0。 节点2:有容器3,IP地址是100.96.2.3,对应的docker0网桥IP地址是100.96.2.1,网络插件后台fanneld在udp端口8285上侦听,并创建了tun设备fannel0。 这里,先讲述下fannel0这个TUN设备是个什么样的设备?在linux中,TUN设备是一种工作在三层的虚拟网络设备。它的工作原理非常简单,即:在操作系统内核和用户空间程序传递IP包。fannel0这个设备的IP地址是100.96.1.0/16,其网络地址是100.96.0.0,子网掩码:255.255.0.0,主机地址是:100.96.1.0。 现在,来分析下节点1的容器1是如何与节点2的容器3之间互相IP通信的。 1)容器1查询路由表,匹配缺省路由,发送到容器2目的IP是100.96.2.3包到docker0(缺省网关100.96.1.1)。 2)节点1的交换设备docker0发现收到的报文目的mac是自己时,就不做二层转发,把报文送到ip协议栈,由内核路由转发。 在节点1 上 $ ip route default via 10.168.0.1 dev eth0 100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.1.0 100.96.1.0/24 dev docker0 proto kernel scope link src 100.96.1.1 10.168.0.0/24 dev eth0 proto kernel scope link src 10.168.0.2 路由匹配到第二条,就是100.96.0.0/16对应的路由规则,从而进入到fannel0这个设备。 3)在用户态的fanneld进程,会在fannel0设备上接收到这个IP包。fanneld进程查看报文的目的IP地址是100.96.2.3,通过查询etcd选择发送报文到哪个节点。 $ etcdctl ls /coreos.com/network/subnets /coreos.com/network/subnets/100.96.1.0-24 /coreos.com/network/subnets/100.96.2.0-24 /coreos.com/network/subnets/100.96.3.0-24 $ etcdctl get /coreos.com/network/subnets/100.96.2.0-24 {"PublicIP":"10.168.0.3"} 查询后,发现目的IP是100.96.2.3的容器在节点2上,fanneld把IP包封装在UDP发送给节点2。 4)节点2的处理流程与节点1类似,最终这个IP包会送到目的容器3。 这里需要掌握下面几个关键的知识点: 发到跨宿主机容器的IP包,是根据fanneld添加的路由规则,经过fannel0这个TUN设备送到fanneld这个服务程序的。 TUN这种虚拟的网络设备,用在内核和用户空间互相收发IP包。 Etcd会记录宿主机容器网络和宿主机网络的对应关系,fanneld进程根据这些记录选择发送目的容器的报文到哪个宿主机。 思考: fannel0这个设备的IP地址是100.96.1.0/16,可以设置成100.96.0.1吗?为什么不能设置成100.96.1.0/24? === VXLAN方式 === VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),类似于VLAN(Virtual LAN),用于在物理的网络内建立逻辑上独立的二层广播域。这里讲述下它们之间的差异: VLAN支持2^12=4096个标识,VXLAN支持2^24多大16M的标识。 VXLAN将VXLAN报文加上以太帧头后封装在UDP中,使用物理网络的ip和mac作为outer-header,通过IP网络转发;VLAN将VLAN报文加上以太帧头直接通过物理以太网转发。 VXlAN是在IP网络上构建的虚拟Overlay Network,这个IP网络可以跨主机、跨机房,跨地域,前提是IP互通;VLAN是在物理链路可访问的广播域局域网上建立的,地域上是有局限的。 VXLAN控制层面隧道实现主要分三种:软件自学习、通过控制协议学习(IS-IS或者BGP)和通过SDN controller实现。VLAN控制层面实现主要分二种:管理员静态配置(基于端口或者mac地址)和通过协议(GVRP、GARP)学习。 VXLAN根据不同的业务场景,分为三种不同的组网模式: Network Overlay 隧道封装在物理交换机完成。这种Overlay的优势在于物理网络设备性能转发性能比较高,可以支持非虚拟化的物理服务器之间的组网互通。 Host Overlay 隧道封装在vSwitch、具备VXLAN功能的软件完成,不用增加新的网络设备即可完成Overlay部署,可以支持虚拟化的服务器之间的组网互通。 Hybrid Overlay是Network Overlay和Host Overlay的混合组网,可以支持物理服务器和虚拟服务器之间的组网互通。 在学习了VXLAN基本原理以及组网模型后,再来理解在docker容器场景,通过VXLAN技术构建一个容器间可以互相访问的Overlay Network就比较容易了。Linux内核本身就支持VXLAN,所以说,通过内核实现Host Overlay方式组网,容器场景不需要满足多租户隔离,宿主机软件学习的方式实现控制层“隧道”,仅需构建一个bridge domain的VXLAN,容器就可以通过这个虚拟的Overlay Network互相访问了。 这里讲述下VTEP这个设备。为了能够打通“隧道”,VXLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备就叫作VTEP(VXLAN Tunnel End Point)。它的作用,就是封装和解封装容器发送和接收的二层数据帧(Ethernet Frame)。 [[文件:Fannel-2.jpg|有框|居中|Fannel-2]] 如图Figure -- 2所示,来分析下节点1的容器1是如何与节点2的容器3是如何IP访问。为了方便叙述,接下来会把这个容器发送的IP包称为“原始IP包”,节点1和节点2上的fannel设备分别称为“源VETP设备”和“目的VETP设备”。 1)容器1查询路由表,匹配缺省路由,发送到容器2目的IP是10.1.16.3包到docker0(缺省网关10.1.15.1)。 2)节点1的交换设备docker0发现收到的报文目的mac是自己时,就不做二层转发,把报文送到ip协议栈,由内核路由转发到fannel.1设备处理。 在节点1 上 $ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface ... 10.1.16.0 10.1.16.0 255.255.255.0 UG 0 0 0 flannel.1 这条路由规则的意思是:发往10.1.16.0/24网段的IP包,都需要经过fannel.1设备发出,并且下一跳网关地址是:10.1.16.0。这条路由是fanneld进程在节点2启动并加入到fannel网络后,在节点1(以及所以其他节点)上添加的。 3)节点1的fannel.1,这个“源VETP设备”收到“原始IP”后,添加Inner Ethernet Header和VXLAN Header,然后发送给“目的VTEP设备”,这个Inner二层帧格式如下: [[文件:Fannel-3.png|有框|居中]] VNI:Virtual network identify,类似于VLAN ID,用来区别不同的VXLAN网络,VNI不同的VXAN不能二层互通。fannel网络方案缺省创建VNI为1的VXLAN。 dst mac:“目的VTEP设备”的mac地址,在步骤二路由查询到“目的VTEP设备”的IP地址是10.1.16.0,根据ARP地址解析,来获得对应IP的mac地址。 在节点1上 $ ip neigh show dev flannel.1 10.1.16.0 lladdr 5e:f8:4f:00:e3:37 PERMANENT 这条ARP entry,与步骤2)的路由一样,也是fanneld进程在节点2启动加入fannel网络后添加到节点1(以及其他节点)上的。 4)Linux内核的VXLAN模块封装这个Inner ethernet frame到UDP发送。前面已经知道了“目的VTEP设备”的IP地址,不过它在哪台宿主机上呢?在前面讲VXLAN控制层面隧道实现时有讲到有“软件自学习”这种方式,在fannel网络场景下,fannel.1设备扮演一个“网桥”的角色,fanneld进程会在“网桥”的FDB(forwarding database)里添加这么一条记录: 在节点1上,使用“目的 VTEP 设备”的 MAC 地址进行查询 $ bridge fdb show flannel.1 | grep 5e:f8:4f:00:e3:37 5e:f8:4f:00:e3:37 dev flannel.1 dst 10.168.0.3 self permanent 发送到“目的VTEP设备”的数据,应该通过fannel.1设备,发往IP地址为10.168.0.3的主机,即节点2,UDP包要发往的目的地找到了。 5)接下来,就在宿主机上和正常的UDP报文(如图Fannel-4)发送一样了。 [[文件:Fannel-4.png|有框|居中]] 6)节点2的处理流程与节点1类似,最终这个IP包会送到目的容器3。 思考: fannel.1设备的IP地址是10.1.15.0/32,子网掩码是255.255.255.255,网络地址就是10.1.15.0,主机地址是0,这个fannel.1作为一个单点的局域网了,可以通过该设备发送包到网关10.1.16.0? 宿主机不在同一IP网络的情况下,VXLAN方式可行吗? === Host-GW方式 === 前面两小节,为大家讲述了docker容器fannel网络方案,运用UDP软件转发和VXLAN技术,解决了不同宿主机之间容器通信的问题。通过分析,这两种方式都存在着不小的性能损失。 UDP方式,“原始IP包”需要经过tun设备从内核态到fanneld用户态进程,然后通过UDP方式通过socket从用户态到内核态,最后通过主机网卡发送出去。 VXLAN方式,虽然linux内核本身就支持该功能,不过整个通信过程,多了额外的封装和解封装,也带来不少的性能损耗。 除了上面两种方式外,还有一种纯三层的网络方案(pure layer3),根据测试,host-gw的性能损失在10%左右,VXLAN方式,性能损失在20%~30%左右,UDP方式就更大了。而且,学习配置好路由规则后,数据层面的转发在内核IP路由完成,不需要额外的软件参与。 [[文件:Fannel-5.jpg|有框|居中]] 如图Fannel-5,节点1上的容器1访问节点2上的容器3。docker0设备在收到“原始IP包”后,查询路由表,发现这么一条路由规则: 10.1.16.0/24 via 10.168.0.3 dev eth0 这条规则的含义是:目的地址属于10.1.16.0/24网段的IP包,都应该经过本机的eth0发送出去,并且它的下一跳是10.168.0.3。从figure -- 8可以看到,这个下一跳就是目的宿主机节点2的IP地址。这样,这个数据帧就会从节点1通过宿主机的二层网络顺利到达节点2。 知识点: Host-gw的工作原理,其实就是在宿主机上,添加一条到达每个fannel子网的路由,这条路由的下一跳即网关就是相对应的fannel子网所在的“主机”。这些路由规则是fanneld根据容器部署的场景创建和更新的。
返回至
Flannel网络方案
。
导航
导航
首页
最近更改
随机页面
栏目
Nginx
Kubernetes
Spring Cloud
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志