使用 Linux Bridge 搭建 VXLAN Overlay 网络

前言

使用 Linux Bridge 搭建 VXLAN 网络不是件很难的事,但是目前确实有一些小坑,这里记录一下。

本文会介绍:

  • 如何使用 Linux Bridge 搭建一个 VXLAN Overlay 网络
  • 如何用 Namespace 模拟虚拟机验证通信
  • Linux VXLAN DOVE Extension 带来的新参数

本文不会介绍:

  • VXLAN 是什么
  • 现代 VXLAN 协议的发展与控制平面的演化

命令

没有多大难度,直接介绍使用的命令。

iptables -D INPUT -j REJECT --reject-with icmp-host-prohibited
# 在我的环境里总会有默认的两条 reject 规则,好烦,先干掉

ip link add vxlan21 type vxlan id 100 dev eth0
# 先添加 vxaln 接口,这个是比较简洁的版本(dev eth0 可以去掉),你可以依照喜好添加一些参数,比如:
# local 10.0.121.180,指定一个本地地址,linux 下的 VXLAN 接口可以不指定 IP 地址、网卡,也可以指定,看需要设置;
# group 239.1.1.1 使用组播模式,239.1.1.1 即为组播地址;
# dstport 4789 指定 vxlan 端口,如果不写的或者写 dspport 0 的话系统会自动使用 8472——根据 IANA 的[标准][1]现在应该使用 4789,包括 VMware NSX 6.2.3 开始也默认从 8472 该到了 4789;
# srcport 32768 61000 可以指定源端口的范围;
# 此外还有一些 DOVE Extension 带来的参数,放在后面介绍

ip link set vxlan21 up
# 将接口 UP,系统会起一个 UDP Socket 监听相应端口

brctl addbr lb-int
ip link set dev lb-int up
brctl addif vxlan21
brctl addif lb-int vxlan21
bridge fdb append to 00:00:00:00:00:00 dev vxlan21 dst 10.0.56.18
# 配置一个对端 VTEP

ip link add veth20 type veth peer name veth02
ip link set veth02 up
brctl addif lb-int veth02
ip netns add veth2
# 创建 namespace 和 veth 设备模拟虚拟机

ip link set dev veth20 netns veth2
ip netns exec veth2 ip a add dev veth20 192.168.0.12/24
ip netns exec veth1 ip link set veth20 up
ip netns exec veth2 ping 192.168.0.11
# 如果你在另一台 hypervisor(VTEP)做好了相应操作模拟了 192.168.0.11 地址,此时应该已经可以通讯了

DOVE Extension

DOVE 的全称是 Distributed Overlay Virtual Ethernet,是从 Linux 3.8 开始引入到内核,目的是方便为 Linux VXLAN 接入控制平面,提升效率。

引入 DOVE 后目前在创建 VXLAN 设备时可以添加下面几个参数:

  • l3miss,在 drivers.net.vxlan.vxlan_xmit 中,如果 VXLAN 设备开启了 Proxy,会尝试进行 ARP 压缩(drivers.net.vxlan.arp_reduce,尽量将 ARP 广播范围压缩到本地),如果此时查找不到这个 IP 对应的 ARP 记录的话,就会触发 l3miss,发送一条消息(netlink)到 userspace,这时 agent (userspace 程序,例如 docker overlay)可以直接添加一条 Neighbor 信息,以替代广播;
  • l2miss,VTEP 的 FDB 不存在目的 MAC 所对应的 VTEP IP 时,触发 l2miss,通过 netlink 发送一条消息到 userspace 替代复制到所有 VTEP;
  • proxy,在上面 l3miss 中说过了,用于做 ARP 本地压缩;
  • leraning,学习远端虚拟机的 MAC 地址,就是 VXLAN 的 flood and learn;
  • ageing,上面学习到本地 FDB 的虚拟机的 MAC 的超时时间;
  • maxaddress,FDB 表的最大条目数;
  • rsc,也就是 L3 switching,直接 switch 到目的地址,不需要经过路由(作者本人没有测试过,如果你做了测试欢迎交流)。

当然了,我说的都是错的,我建议你还是直接看代码。

如果觉得看 vxlan.c 比较困难的话,可以看 DOVE 的 Patch:http://lists.openwall.net/netdev/2012/11/15/96。

Reference

  1. Rami Cohen, et al: Distributed Overlay Virtual Ethernet (DOVE) integration with Openstack,
    IP/IEEE International Symposium on Integrated Network Management (IM 2013), 29-
    -May-2013, pp 1088-1089

  2. Etsuji Nakai: How VXLAN works on Linux, https://www.slideshare.net/enakai/how-vxlan-works-on-linux

  3. Joe Julian: How to configure linux vxlans with multiple unicast endpoints, https://joejulian.name/blog/how-to-configure-linux-vxlansith-multiple-unicast-endpoints/

  4. Thomas Richter: Software Defined Networking using VXLAN, LinuxCon Edinburgh 21-Oct-2013

  5. 刘世民: Neutron 理解(14):Neutron ML2 + Linux bridge + VxLAN 组网, http://www.cnblogs.com/sammyliu/p/4985907.html

写给 OpenStacker 的 ZStack 指南(一)

前言

相比 OpenStack 而言,ZStack 全异步、追求高稳定性和安全的代码是相对难读的,所以本文希望能通过一些简单的例子和与 OpenStack 的一些对比,将 ZStack 的特点、代码的原理尽量描述出来,降低 ZStack 的入门门槛。欢迎更多 OpenStacker 参与 ZStack 或从 ZStack 的代码中汲取经验。

从执行一个 API 说起

对一个业内人士,观察在页面上一个指令如何逐步被执行,无疑是最直观深入的了解方式。

第一步 前端

打开 Mevoco/ZStack 的界面,可以发现基本设计思路与其他 IaaS 或 OpenStack 是基本类似的,然而打开开发者面板就会发现大有不同。

OpenStack 的面板一般通过 HTTP 到 Web 后端,可能是一个像 Horizon 的中间件,也可能是直接把请求发到后面的具体服务的 API 服务,例如 nova-api 或 neutron-server。当然中间可能还会有负载均衡器或高可用之类的设施。

image_1b6dgt82i1rl0md5j8t8va1v4m9.png-305.3kB

图1 在OpenStack的Horizon面板上创建虚拟机出发的Post请求

而在 ZStack 的面板中开发者面板是很干净的,打开之后无论什么操作是不会触发 HTTP 请求的,数据和请求都在 WebSocket 传递,比如我们在面板上创建一个虚拟机,可以看到通过 WebSocket 发送一个 frame,一个 org.zstack.header.vm.APICreateVmInstanceMsg 的消息,后面跟着的是创建的参数。

image_1b6dhje891gd7rj61e551r9hv3vt.png-209.3kB
图2 ZStack面板上创建虚拟机发出的WebSocket帧

Continue reading

为什么在 VyOS(Vyatta)中 commit 会很慢

最近就这个问题调查了蛮久,其实原因比较显然,在看到 strace 的结果就已经明白了大半,但是本着求(xia)知(zhe)探(teng)索的想法,仔细验证了代码逻辑和时间(新技能 get!给 C++、Perl 混合代码调试性能),攒出了这篇文章。

ZStack 是一个开源的 IaaS 软件,架构和性能都很优秀,可以在 103 秒内并发创建 1000 台虚拟机,可惜这个数据是在扁平网络下测试得到的,一旦用上云路由网络,单个虚拟机的启动时间会延长到七秒左右。

我们现看下看下实际的占用时间,我在 vyatta 的代码里添加了日志(Repo 是 https://github.com/vyos/vyatta-cfg )综合 zstack、zstack-vyos、vyos 的日志可以看到大概是这样的(注意 zstack 的日志时间精度只提供到秒,没有毫秒):

2017-02-13 13:22:08 start executing flow[NetworkServiceManagerImpl.java:apply-network-service-DHCP]

2017-02-13 13:22:08 DEBUG [RECV] /setsnat
2017-02-13 13:22:09 DEBUG [HTTP POST][ASYNC REPLY TO /setsnat]

2017-02-13 13:22:09 DEBUG [RECV] /adddhcp

# 以下为 vyos 日志
2017-02-13 13:22:09:458 Entered cli_bin::doCommit
2017-02-13 13:22:10:216 Entered commit::doCommit
2017-02-13 13:22:10:901 notify other users in config mode
2017-02-13 13:22:12:260 cs.commitConfig complete
2017-02-13 13:22:12:557 Exit commit::doCommit
2017-02-13 13:22:12:557 Normal exit cli_bin::doCommit
# 退出 vyos 日志

2017-02-13 13:22:12 DEBUG [HTTP POST][ASYNC REPLY TO /adddhcp]

2017-02-13 13:22:12 DEBUG [RESPONSE] to /setdns
2017-02-13 13:22:12 DEBUG [HTTP POST][ASYNC REPLY TO /setdns]

2017-02-13 13:22:12 DEBUG [SimpleFlowChain] (zs-thread-81) [FlowChain: apply-network-service-to-vm-13d1359b8bd34a05a91f61dedb112e96] successfully executed flow[NetworkServiceManagerImpl.java:apply-network-service-DHCP]

可以把时间与调用关系结合起来做成一张图:

VyOS_Commit
Continue reading