DockOne微信分享(一一二):Flannel中vxlan backend的原理和实现

本文讲的是DockOne微信分享(一一二):Flannel中vxlan backend的原理和实现【编者的话】Overlay网络是kubernetes网络模型的重要解决方案之一,而Flannel作为焦躁出现的成熟的解决方案,可以基于多种backend来搭建Overlay网络,其中基于Linux内核的vxlan backend 在性能和易用性上都有比较明显的优势。

【上海站|3天烧脑式微服务架构训练营】培训内容包括:DevOps、微服务、Spring Cloud、Eureka、Ribbon、Feign、Hystrix、Zuul、Spring Cloud Config、Spring Cloud Sleuth 等。

这次分享介绍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 
node1$ bridge fdb add $mac-of-vtep-on-node-2 dev $DEVNAME dst $DESTIP 

node2

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

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

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

node2

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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> 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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> 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启动时会动态启动两个并发任务: 

  1. 监听Kernel中L3 MISS并反序列化成Golang对象
  2. 根据L3 MISS和子网配置(etcd)来自动更新本地neighbor配置

关于源码,可以猛戳这里

最后,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+,因为此前的版本都存在潜在的网络风暴问题

四、Q&A

Q:Flannel 创建多个网络,并且实现网络之间隔离可以实现吗?

A:是的,最新的Flannel中已经加入管理多个网络的能力,你可以在启动时制定多个网络,etcd中配置信息的的格式略有不同,启动flanneld时有参数可以制定初始化哪几个网络。

Q:如果使用Flannel过程中发现,跨节点无法访问,该从哪些方便着手排错?

A:首先看一下你指定的虚拟网络是否和现有物理网路中的网段冲突了;然后检查节点之间的UDP端口是否可以连通,最后还需要考虑当前系统是否支持VXLAN,最低要求v3.7,建议v3.9+,CentOS7的默认内核已经可以满足要求。

Q:过一组测试数据两台VM to VM (vlan): 7.74 GBits/sec,使用flannel vxlan,两个container之间 1.71 GBits/sec,请问这个数据正常吗,vxlan的带宽损耗发生哪, 有啥调优思路,谢谢。

A:首先我想确认一下你测试的结果是TCP还是UDP,建议实际测试一下,这个是我在Digital Ocean上2台VPS间的测试结果,仅供参考:
https://github.com/yangyuqian/ ... md%23 性能评估
搞清楚原理以后,相信很容易判断瓶颈位置:节点之间是通过UDP来转发L2的数据包的,我认为这部分可能有比较大的嫌疑。

Q:Flannel 在使用过程中,如果需要新增网段,如何让每个节点获取最新的路由表信息?需要更新所有节点的Flannel配置项,重启Flannel 吗?

A:这个问题其实还不错,比较接近实战了;首先你确实可以重启flanneld来更新网络配置;然后Flannel每24h会自动重新分配集群内的网络,所以你就算不重启,每24h也会自动刷新本地网络的,如果发现本地网络配置不符合Flannel在etcd中配置的要求,会重新生成网络配置。

Q:我在项目中用了flanne lvxlan backend。按照文中说法,转发由内核进行,Flannel挂掉并不影响通宵。但是实际使用中,Flannel挂掉确实导致外部其他访问不到Docker。请问这个可能是什么原因?

A:首先要澄清一下,并不是说挂掉网络没影响,flanneld挂掉会导致本地的ARP entry无法自动更新,但是已经生成的网络环境还是可用的,具体可以看我前面手动搭建overlay network的过程,根本在于ARP table。

以上内容根据2017年03月28日晚微信群分享内容整理。分享人杨谕黔,FreeWheel基础架构高级软件工程师,目前主要从事服务化框架、容器化平台相关的研发与推广,关注和感兴趣的技术主要有Golang、Docker、Kubernetes等。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesz,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

原文发布时间为:2017-04-02

本文作者:杨谕黔

本文来自合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:DockOne微信分享(一一二):Flannel中vxlan backend的原理和实现

时间: 2024-10-07 20:12:27

DockOne微信分享(一一二):Flannel中vxlan backend的原理和实现的相关文章

DockOne微信分享(一二六):Kubernetes在微服务化游戏中的探索实践

本文讲的是DockOne微信分享(一二六):Kubernetes在微服务化游戏中的探索实践[编者的话]随着Kubernetes的持续火热,那在线游戏领域又将如何使用,又将碰到哪些问题,以及带来哪些价值? 本次分享将为大家介绍微服务化架构游戏领域中,Kubernetes支撑技术方案选型,功能优化以及实践过程中的一些思考. [3 天烧脑式容器存储网络训练营 | 深圳站]本次培训以容器存储和网络为主题,包括:Docker Plugin.Docker storage driver.Docker Volu

DockOne微信分享(一二二):探索Kubernetes的网络原理及方案

本文讲的是DockOne微信分享(一二二):探索Kubernetes的网络原理及方案[编者的话]2016年ClusterHQ容器技术应用调查报告显示,一年来容器技术应用于生产的比例增长了96%,Kubernetes的使用率达到了40%,成为了最受欢迎的容器编排工具:那么Kubernetes到底是什么呢?它是一个用于容器集群的自动化部署.扩容以及运维的开源平台:那么通过Kubernetes能干什么呢?它能快速而有预期地部署你的应用,极速地扩展你的应用,无缝对接新的应用功能,节省资源,优化硬件资源的

DockOne微信分享(一二〇):基于Kubernetes的私有容器云建设实践

本文讲的是DockOne微信分享(一二〇):基于Kubernetes的私有容器云建设实践[编者的话]本次分享将为大家介绍易宝支付私有容器云从0到1的建设之路.包括技术选型.理论基础.基于Kubernetes的容器云和CI/CD落地过程中的挑战和踩过的坑. 建设背景及目标 在Docker技术流行开来之前,保证软件交付的质量和速度对于大多数企业来说都是困难的.业务的复杂性带来了应用的复杂性,面对成千上万的不同应用,运维部门需要时刻应对来自不同应用.不同环境的挑战.特别是在自动化运维程度不高的企业,"

DockOne微信分享(一二一):喜马拉雅FM测试环境的Docker化实践案例

本文讲的是DockOne微信分享(一二一):喜马拉雅FM测试环境的Docker化实践案例[编者的话]随着容器技术的流行,作为线上应用Docker的铺垫,喜马拉雅FM从16年开始推进测试环境Docker化.本次分享将重点为大家介绍我们在Docker化的过程中如何进行技术选型.环境搭建,特别是实践中碰到的一些问题及其解决方案. [3 天烧脑式 Docker 训练营 | 上海站]随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛.本次培训我们理论结合实践,从Docker应该场景.持续部

DockOne微信分享(一二九):聊聊Service Mesh:linkerd

本文讲的是DockOne微信分享(一二九):聊聊Service Mesh:linkerd[编者的话]随着企业逐渐将传统的单体应用向微服务或云原生应用的转变,虽然微服务或者云原生应用能给企业带来更多的好处,但也会带来一些具有挑战的问题,如怎么管理从单体应用转向微服务所带来的服务间通讯的复杂性,怎么实现微服务间安全,高效,可靠的访问,如何满足多语言多环境的透明通讯,服务发现.熔断,动态流量迁移,金丝雀部署,跨数据中心访问等等.本次分享给大家引入一新概念服务网格(Service Mesh)以及介绍业界

DockOne微信分享(一二四):轻松筹监控系统实现方案

本文讲的是DockOne微信分享(一二四):轻松筹监控系统实现方案[编者的话]监控系统是服务管理最重要的组成部分之一,可以帮助开发人员更好的了解服务的运行状况,及时发现异常情况.虽然阿里提供收费的业务监控服务,但是监控有很多开源的解决方案,可以尝试自建监控系统,满足基本的监控需求,以后逐步完善优化.这样既可以更灵活的满足自身业务的监控需求,也可以为以后自建机房提供技术积累.通过以下7个方面来建设监控系统. [3 天烧脑式 Docker 训练营 | 上海站]随着Docker技术被越来越多的人所认可

DockOne微信分享(一四二):容器云在万达的落地经验

本文讲的是DockOne微信分享(一四二):容器云在万达的落地经验[编者的话]容器生态是现在非常火热的技术生态之一,个人认为它主要囊括着四个方面的技术栈:一是容器核心技术栈(包括 Docker.rkt 及第三方公司自主研发的容器 Engine 等):二是容器基础技术栈(包括容器网络.存储.安全及服务发现等):三是容器编排技术栈(包括 Mesos/Marathon.Swarm.Kubernetes 及 OpenShift 等):四是容器应用技术栈(主要包括 CI/CD.监控.日志及微服务框架等).

DockOne微信分享(一一零):Docker在沪江落地的实践

本文讲的是DockOne微信分享(一一零):Docker在沪江落地的实践[编者的话]容器化是很多公司技术层向往又惧怕的一项热门技术,它的高效性,封装性能给开发.运维带来许多便利,但其本身也需要较强的技术能力去控制,否则会变成一个无法落地的概念.沪江作为教育界的独角兽,随着业务的增长,在开发.测试.运维上的成本增加日益显著.经过我们一年的探索,终于使Docker技术在沪江落地,不但成功的降低了成本,并吸引了其他部门的关注与试用,取得良好的成效. [上海站|3天烧脑式微服务架构训练营]培训内容包括:

DockOne微信分享(一一七):沪江容器化运维实践

本文讲的是DockOne微信分享(一一七):沪江容器化运维实践[编者的话]沪江目前容器技术主要应用场景:OCS课件业务无状态应用:基于Apache Mesos+Marathon实现沪江容器系统调度管理:Consul + Consul Template + Nginx实现服务自动发现和注册:Prometheus + Grafana + Alertmanager报警实现容器监控报警.本次分享将从以下几方面来讲解: 选择容器技术缘由 容器技术选型 容器存储 容器网络 监控报警 镜像管理 调度管理 服务