Flannel中vxlan backend的原理和实现

这次分享介绍Flannel中的vxlan backend,包含两方面内容:

       深入理解内核中的VXLAN原理:使用iproute2和bridge等原生工具来搭建一个基于VXLAN的Overlay网络。

       理解Flannel使用vxlan backend时的工作原理: 有了前面对内核VXLAN原理的理解,通过分析Flannel部分源码来从根本上掌握其vxlan backend的原理。

一、VXLAN的原理

        Virtual eXtensible Local Area Network(VXLAN)是一个在已有的3层物理网络上构建2层逻辑网络的协议。

       在2012年底的v3.7.0之后,Linux Kernel加入了VXLAN协议支持,作者:Stephen Hemminger,所以如果要使用Linux Kernel中的VXLAN支持,最低内核版本3.7+(推荐3.9+)。

       Stephen Hemminger同时也实现了iproute2、bridge等工具,用以管理Linux中复杂的网络配置,目前在绝大多数Linux发行版中都是默认支持的。

       VXLAN本质上是一种tunnel(隧道)协议,用来基于3层网络实现虚拟的2层网络。泛泛地说,tunnel协议有点像今天电话会议,通过可视电话连接不同的会议室让每个人能够直接交谈,就好像坐在一个会议室里一样。很多tunnel协议,如GRE也有类似VXLAN中VNI的用法。

      tunnel协议的另外一个重要的特性就是软件扩展性,是软件定义网络(Software-defined Network,SDN)的基石之一。

      Flannel中有两个基于tunnel协议的backend:UDP(默认实现)和VXLAN,本质上都是tunnel协议,区别仅仅在于协议本身和实现方式。

       这里顺便提一句:tunnel协议在比较老的内核中已经有支持,我印象中v2.2+就可以使用tunnel来创建虚拟网络了,因此UDP backend适合在没有vxlan支持的linux版本中使用,但性能会相比vxlan backend差一些。

 以上是一些背景介绍,下面开始介绍VXLAN的内核支持

图1. VXLAN可以在分布多个网段的主机间构建2层虚拟网络

图2. VXLAN基本原理:套路还是tunnel那一套,区别仅仅在于tunnel协议本身的实现

       为了说明图1和图2中谈到的VXLAN原理,这里在两台不同网段的VPS上手动搭建一个Overlay Network,并在两个节点上分别运行了Docker Container,当我们看到容器之间使用虚拟网络的IP完成直接通信时,实验就成功了。

图3 手动搭建vxlan虚拟网络的网络拓扑

图3中提到一个VTEP的概念,全称VXLAN Tunnel Endpoint,本质上就是前面提到的tunnel中的endpoint

现在正式开始手动搭建图 3中的虚拟网络

第一步、创建docker bridge

       默认的docker bridge地址范围是172.17.0.1/24(比较老的版本是172.17.42.1/24), 而本实验中两个节点node1和node2的子网要求分别为: 192.1.78.1/24,192.1.87.1/24 。

      修改docker daemon启动参数,增加以下参数后重启docker daemon:

node1: --bip=192.1.78.1/24

node2: --bip=192.1.87.1/24

       这时node1和node2的容器之间还不能直接通信, node1也不能跨主机和node2上的容器直接通信,反之node2也无法直接和node1上的容器通信.。

第二步、创建VTEPs

在node1上执行以下命令:

PREFIX=vxlan

IP=$external-ip-of-node-1

DESTIP=$external-ip-of-node-2

PORT=8579

VNI=1

SUBNETID=78

SUBNET=192.$VNI.0.0/16

VXSUBNET=192.$VNI.$SUBNETID.0/32

DEVNAME=$PREFIX.$VNI

ip link delete $DEVNAME

ip link add $DEVNAME type vxlan id $VNI dev eth0 local $IP dstport $PORT nolearning

echo '3' > /proc/sys/net/ipv4/neigh/$DEVNAME/app_solicit

ip address add $VXSUBNET dev $DEVNAME

ip link set $DEVNAME up

ip route delete $SUBNET dev $DEVNAME scope global

ip route add $SUBNET dev $DEVNAME scope global

node2上执行以下命令:

PREFIX=vxlan

IP=$external-ip-of-node-2

DESTIP=$external-ip-of-node-1

VNI=1

SUBNETID=87

PORT=8579

SUBNET=192.$VNI.0.0/16

VXSUBNET=192.$VNI.$SUBNETID.0/32

DEVNAME=$PREFIX.$VNI

ip link delete $DEVNAME

ip link add $DEVNAME type vxlan id $VNI dev eth0 local $IP dstport $PORT nolearning

echo '3' > /proc/sys/net/ipv4/neigh/$DEVNAME/app_solicit

ip -d link show

ip addr add $VXSUBNET dev $DEVNAME

ip link set $DEVNAME up

ip route delete $SUBNET dev $DEVNAME scope global

ip route add $SUBNET dev $DEVNAME scope global

第三步、为VTEP配置forward table

# node1

$ bridge fdb add $mac-of-vtep-on-node-2 dev $DEVNAME dst $DESTIP

# node2

$ bridge fdb add $mac-of-vtep-on-node-1 dev $DEVNAME dst $DESTIP

第四步、配置Neighbors,IPv4中为ARP Table

# node1

$ ip neighbor add $ip-on-node-2 lladdr $mac-of-vtep-on-node-2 dev vxlan.1

# node2

$ ip neighbor add $ip-on-node-1 lladdr $mac-of-vtep-on-node-1 dev vxlan.1

      注意:ARP表一般不会手动更新,在VXLAN的实现中由对应的Network Agent监听L3 MISS来 动态更新;这里手动添加ARP entry仅仅是为了测试;另外,如果跨主机访问多个IP, 每个跨主机的IP就都需要配置对应的ARP entry。

      以上操作都需要root权限,完成后整个Overlay Network就搭建成功了,下面通过测试两种连通性来总结本实验:

node1容器与node2上的容器直接通信(容器与跨主机容器间直接通信)

node1与node2上容器直接通信;node2与node1上容器直接通信(主机和跨主机容器之间通信)

      先看容器与跨主机容器间直接通信的测试。

现在node1和node2上分别起一个busybox:

node1$ docker run -it --rm busybox sh

node1$ ip a

1: lo: mtu 65536 qdisc noqueue qlen 1

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

inet 127.0.0.1/8 scope host lo

  valid_lft forever preferred_lft forever

inet6 ::1/128 scope host

  valid_lft forever preferred_lft forever

6: eth0@if7: mtu 1500 qdisc noqueue

link/ether 02:42:c0:01:4e:02 brd ff:ff:ff:ff:ff:ff

inet 192.1.78.2/24 scope global eth0

  valid_lft forever preferred_lft forever

inet6 fe80::42:c0ff:fe01:4e02/64 scope link

  valid_lft forever preferred_lft forever

node2$ docker run -it --rm busybox sh

node2$ ip a

1: lo: mtu 65536 qdisc noqueue qlen 1

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

inet 127.0.0.1/8 scope host lo

  valid_lft forever preferred_lft forever

inet6 ::1/128 scope host

  valid_lft forever preferred_lft forever

10: eth0@if11: mtu 1500 qdisc noqueue

link/ether 02:42:c0:01:57:02 brd ff:ff:ff:ff:ff:ff

inet 192.1.87.2/24 scope global eth0

  valid_lft forever preferred_lft forever

inet6 fe80::42:c0ff:fe01:5702/64 scope link

  valid_lft forever preferred_lft forever

接下来让我们来享受一下容器之间的连通性。

node1@busybox$ ping -c1 192.1.87.2

PING 192.1.87.2 (192.1.87.2): 56 data bytes

64 bytes from 192.1.87.2: seq=0 ttl=62 time=2.002 ms

node2@busybox$ ping -c1 192.1.78.2

PING 192.1.78.2 (192.1.78.2): 56 data bytes

64 bytes from 192.1.78.2: seq=0 ttl=62 time=1.360 ms

然后看主机和跨主机容器之间连通性的测试。

node1$ ping -c1 192.1.87.2

PING 192.1.87.2 (192.1.87.2) 56(84) bytes of data.

64 bytes from 192.1.87.2: icmp_seq=1 ttl=63 time=1.49 ms

node2$ ping -c1 192.1.78.2

PING 192.1.78.2 (192.1.78.2) 56(84) bytes of data.

64 bytes from 192.1.78.2: icmp_seq=1 ttl=63 time=1.34 ms

具体实验的截屏可以访问:https://asciinema.org/a/bavkebqxc4wjgb2zv0t97es9y 。

二、Flannel中vxlan backend实现

 弄清楚了kernel中vxlan的原理后,就不难理解Flannel的机制了。

注意:

使用vxlan backend时,数据是由Kernel转发的,Flannel不转发数据,仅仅动态设置ARP entry

而udp backend会承担数据转发工具(这里不展开介绍其实现),UDP backend自带了一个C实现的proxy,连接不同节点上的tunnel endpoints 这里讨论的源码基于最新稳定版v0.7.0。

vxlan backend启动时会动态启动两个并发任务:

监听Kernel中L3 MISS并反序列化成Golang对象

根据L3 MISS和子网配置(etcd)来自动更新本地neighbor配置

关于源码,请看:http://dwz.cn/5MXKuC

最后,Flannel的实现中有一个小细节,在0.7.0中刚刚加入,即VTEP的IP加上了/32位的掩码避免了广播,此前的版本都是/16掩码,解决了VXLAN网络中由于广播导致的“网络风暴”的问题。

三、总结一下

Flannel中有多种backend,其中vxlan backend通过内核转发数据,而udp backend通过用户态进程中的proxy转发数据

Flannel在使用vxlan backend的时候,短暂启停flanneld不会造成网络中断,而udp backend会

很多第三方的网络测试表明,udp backend比vxlan backend网络的性能差大概1个数量级,一般来说只要内核支持(v3.9+),建议选择vxlan backend

Flannel中使用vxlan backend时,建议升级到0.7+,因为此前的版本都存在潜在的网络风暴问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容