当前位置: 首页 > news >正文

linux对vxlan的支持

转载自:linux对vxlan的支持
vxlan实例
实验环境:

vm1

[root@test-1 ~]# uname -sr
Linux 3.10.0-693.el7.x86_64
[root@test-1 ~]# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1446 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:0c:e3:c6 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.11/24 brd 10.10.10.255 scope global dynamic eth0
valid_lft 84967sec preferred_lft 84967sec

vm2

[root@test-2 ~]# uname -sr
Linux 3.10.0-693.el7.x86_64
[root@test-2 ~]# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1446 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:50:61:0d brd ff:ff:ff:ff:ff:ff
inet 10.10.10.9/24 brd 10.10.10.255 scope global dynamic eth0
valid_lft 84929sec preferred_lft 84929sec
点对点的vxlan
完成一个最简单的vxlan网络,拓扑如下:

规划图1

开始配置

[root@test-1 ~]# ip link add vxlan1 type vxlan id 1 dstport 4789 remote 10.10.10.9 local 10.10.10.11 dev eth0
vxlan1 即为创建的接口名称 ,type 为 vxlan 类型。
id 即为 VNI。
dstport 指定 UDP的目的端口,IANA 为vxlan分配的目的端口是 4789。
remote 和 local ,即远端和本地的IP地址,因为vxlan是MAC-IN-UDP,需要指定外层IP,此处即指。
dev 本地流量接口。用于 vtep 通信的网卡设备,用来读取 IP 地址。注意这个参数和 local参数含义是相同的,在这里写出来是为了告诉大家有两个参数存在。
创建完成可看到

[root@test-1 ~]# ip addr show type vxlan
3: vxlan1: <BROADCAST,MULTICAST> mtu 1396 qdisc noop state DOWN qlen 1000
link/ether 86:65:ef:3d:a1:e7 brd ff:ff:ff:ff:ff:ff
接口现在还没有地址,也没有开启,接下来进行如下配置

[root@test-1 ~]# ip addr add 192.168.1.3/24 dev vxlan1
[root@test-1 ~]# ip link set vxlan1 up
[root@test-1 ~]# ip addr show type vxlan
3: vxlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1396 qdisc noqueue state UNKNOWN qlen 1000
link/ether 86:65:ef:3d:a1:e7 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.3/24 scope global vxlan1
valid_lft forever preferred_lft forever
vxlan1已经配置完成。

为什么vxlan1的MTU是 1396呢?
因为我的vm启在openstack云环境中,租户网络为vxlan,外网为vlan类型。
因此创建的内网网络MTU为 1446(1500 - 4(vlan) - 50(vxlan)),在vm中基于eth0又配置vxlan,因此MTU需要再减50,即 1396。
之后看一下路由表即vxlan 的 FDB表

#(仅列出vxlan部分)
[root@test-1 ~]# ip route
192.168.1.0/24 dev vxlan1 proto kernel scope link src 192.168.1.3
[root@test-1 ~]# bridge fdb
00:00:00:00:00:00 dev vxlan1 dst 10.10.10.9 via eth0 self permanent

即默认vxlan1 对端地址为 10.10.10.9,通过eth0进行报文交换

对test-2进行同样的配置,保证VNI和dstport一致。VNI一致是为了不进行vxlan隔离,dstport一致是因为IANA 为vxlan分配的目的端口是 4789。

之后在test-1上进行测试连通性

[root@test-1 ~]# ping 192.168.1.4 -c 3
PING 192.168.1.4 (192.168.1.4) 56(84) bytes of data.
64 bytes from 192.168.1.4: icmp_seq=1 ttl=64 time=0.424 ms
64 bytes from 192.168.1.4: icmp_seq=2 ttl=64 time=0.437 ms
64 bytes from 192.168.1.4: icmp_seq=3 ttl=64 time=0.404 ms

--- 192.168.1.4 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.404/0.421/0.437/0.027 ms
在对端抓取eth0报文如下

vxlan-tcpdump

组播模式vxlan
要组成同一个 vxlan 网络,vtep 必须能感知到彼此的存在。多播组本来的功能就是把网络中的某些节点组成一个虚拟的组,所以 vxlan 最初想到用多播来实现是很自然的事情。拓扑如下

vxlan-multicast

[root@test-1 ~]# ip link add vxlan1 type vxlan id 2 dstport 4789 group 224.0.0.1 dev eth0
[root@test-1 ~]# ip addr add 192.168.1.3/24 dev vxlan1
[root@test-1 ~]# ip link set vxlan1 up
[root@test-1 ~]# ip route
192.168.1.0/24 dev vxlan1 proto kernel scope link src 192.168.1.3
[root@test-1 ~]# bridge fdb
00:00:00:00:00:00 dev vxlan1 dst 224.0.0.1 via eth0 self permanent
这里最重要的参数是 group 224.0.0.1 (多播地址范围为224.0.0.0到239.255.255.255)表示把 vtep 加入到这个多播组。其他设备进行类似配置,确保VNI与group相同。

由于将vxlan1加入多播组,因此ARP请求这类报文不在进行广播,而是多播。

vxlan-mul-arp

可以与点对点形式的做对比

vxlan-point-to-point

ARP回应依然是单播报文。通信结束之后,查看ARP及fdb表项为

[root@test-1 ~]# ip neigh
192.168.1.4 dev vxlan1 lladdr a6:8b:d5:2d:83:3c STALE
[root@test-1 ~]# bridge fdb
00:00:00:00:00:00 dev vxlan1 dst 224.0.0.1 via eth0 self permanent
a6:8b:d5:2d:83:3c dev vxlan1 dst 10.10.10.9 self
利用 bridge 来接入容器
此处的bridge可以是linux的bridge,也可以是ovs的bridge,为了配置简单化,此处以linux举例。

上面两种拓扑将vxlan作为三层口,在云环境中基本没什么意义。在实际的生产中,每台主机上都有几十台甚至上百台的虚拟机或者容器需要通信,因此我们需要找到一种方法能够把这些通信实体组织起来——这正是引入桥的意义。

vxlan-bridge

下面用 network namespace来模拟tap(vm接口),进行如下配置

#创建vxlan接口
[root@test-1 ~]# ip link add vxlan1 type vxlan id 2 dstport 4789 group 224.0.0.6 dev eth0
#创建NS
[root@test-1 ~]# ip netns add vm0
[root@test-1 ~]# ip netns exec vm0 ip link set dev lo up
#创建veth 接口,并将其中一个veth口放到 NS中
[root@test-1 ~]# ip link add veth0 type veth peer name veth1
[root@test-1 ~]# ip link set veth0 netns vm0
[root@test-1 ~]# ip netns exec vm0 ip link set veth0 name eth0
[root@test-1 ~]# ip netns exec vm0 ip addr add 192.168.1.3/24 dev eth0
[root@test-1 ~]# ip netns exec vm0 ip link set dev eth0 up
[root@test-1 ~]# ip netns exec vm0 ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
8: eth0@if7: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN qlen 1000
link/ether 9e:ab:18:d5:25:55 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.1.3/24 scope global eth0
valid_lft forever preferred_lft forever
#创建桥,并将vxlan、veth加入桥
[root@test-1 ~]# ip link add br0 type bridge
[root@test-1 ~]# ip link set vxlan1 master br0
[root@test-1 ~]# ip link set vxlan1 up
[root@test-1 ~]#
[root@test-1 ~]# ip link set dev veth1 master br0
[root@test-1 ~]# ip link set dev veth1 up
[root@test-1 ~]# ip link set dev br0 up
[root@test-1 ~]# bridge link
6: vxlan1 state UNKNOWN : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1396 master br0 state forwarding priority 32 cost 100
7: veth1 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 2
其他设备进行类似配置(设备较多可用脚本实现)。利用命令 ip netns exec vm0 ping IP来验证连通性。

此过程为:

NS eth0 ARP广播,通过veth1到达br0。
br0上没有二层表,进行学习之后,每个口(除收报文口)进行转发,到达vxlan1。
vxlan1口fdb表默认走多播,进行外层封装之后从eth0接口发出。
手动维护 vtep 组
对 overlay 网络来说,它的网段范围是分布在多个主机上的,因此传统 ARP 报文的广播无法直接使用。要想做到 overlay 网络的广播,必须把报文发送到所有 vtep 在的节点,这才引入了多播。

如果提前知道哪些 vtep 要组成一个网络,以及这些 vtep 在哪些主机上,那么就可以不使用多播。

Linux 的 vxlan 模块也提供了这个功能,而且实现起来并不复杂。创建 vtep interface 的时候不使用 remote 或者 group 参数就行:

[root@test-1 ~]# ip link add vxlan1 type vxlan id 2 dstport 4789 dev eth0
[root@test-1 ~]# bridge fdb
01:00:5e:00:00:01 dev eth0 self permanent
由于没有指定 remote 和 group ,因此进行广播时不知道要发送给谁。但是可以手动添加默认的 FDB 表项

#环境只有两台设备,因此只添加一条表项
[root@test-1 ~]# bridge fdb append 00:00:00:00:00:00 dev vxlan1 dst 10.10.10.9
[root@test-1 ~]# bridge fdb
00:00:00:00:00:00 dev vxlan1 dst 10.10.10.9 self permanent
这种方式是手动维护多播组,解决了在某些 underlay 网络中不能使用多播的问题。但是由于需要手动维护,比较不方便,当然,可以编写脚本自动维护。

除此之外,这种方式也没有解决多播的另外一个问题:每次要查找 MAC 地址要发送大量的无用报文,如果 vtep 组节点数量很大,那么每次查询都发送 N 个报文,其中只有一个报文真正有用。

这个问题的解决可以参考此种方式,添加单播fdb表项!

手动维护 fdb 表
如果提前知道目的容器(或vm) MAC 地址和它所在主机的 IP 地址,也可以通过更新 fdb 表项来减少广播的报文数量。

[root@test-1 ~]# ip link add vxlan1 type vxlan id 2 dstport 4789 dev eth0 nolearning
nolearning 参数表示 vtep 不通过收到的报文来学习 fdb 表项的内容而是管理员维护。

[root@test-1 ~]# bridge fdb append 00:00:00:00:00:00 dev vxlan1 dst 10.10.10.9
[root@test-1 ~]# bridge fdb append 4e:e9:90:34:2e:b5 dev vxlan1 dst 10.10.10.9
第一条是默认表项;
第二条是明确的IP-MAC对应关系,注意:MAC是容器(vm)端口的MAC地址,而IP是NVE(Network Virtual Endpoint)的IP,即MAC是overlay的MAC,IP是underlay的IP。
不过此种方法只是把fdb进行手动维护,ARP广播没有任何改进,不过如果确定环境,那么可以手动维护ARP表项。

手动维护 ARP 表
如果能通过某个方式知道容器的 IP 和 MAC 地址对应关系,只要更新到每个节点,就能实现网络的连通。

但是,需要维护的是每个容器里面的 ARP 表项,因为最终通信的双方是容器。到每个容器里面(所有的 network namespace)去更新对应的 ARP 表,是件工作量很大的事情,而且容器的创建和删除还是动态的。linux 提供了一个解决方案,vtep 可以作为 arp 代理,回复 arp 请求,也就是说只要 vtep interface 知道对应的 IP - MAC 关系,在接收到容器发来的 ARP 请求时可以直接作出应答。这样的话,我们只需要更新 vtep interface 上 ARP 表项就行了。

[root@test-1 ~]# ip link add vxlan1 type vxlan id 2 dstport 4789 dev eth0 nolearning proxy
proxy表示 vtep 承担ARP代理的功能。手动添加表项

[root@test-1 ~]# bridge fdb append 00:00:00:00:00:00 dev vxlan1 dst 10.10.10.9
[root@test-1 ~]# bridge fdb append 4e:e9:90:34:2e:b5 dev vxlan1 dst 10.10.10.9

添加 IP-MAC对应关系

[root@test-1 ~]# ip neigh add 192.168.1.4 lladdr 4e:e9:90:34:2e:b5 dev vxlan0

转载于:https://blog.51cto.com/14146751/2334560

相关文章:

  • Mysql优化
  • 3.1Python的判断选择语句
  • 深度解析ES6通过WeakMap解决内存泄漏问题
  • Redis 和 memcache 简单比较
  • verilog语法实例学习(1)
  • Docker三剑客之docker-machine
  • 正者表达式exec和match
  • Linux操作系统有什么吸引力,在程序员中这么受欢迎!
  • Oracle常用语句
  • Ubuntu Vscode安装
  • wx2tt 微信小程序转头条小程序工具
  • Min_25筛
  • spring-boot切面编程-日志记录
  • 从0到1学C++ 第2篇 认识C++面向过程编程的特点
  • Java01
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Fabric架构演变之路
  • JavaScript类型识别
  • Koa2 之文件上传下载
  • Redux系列x:源码分析
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • ucore操作系统实验笔记 - 重新理解中断
  • 分布式熔断降级平台aegis
  • 检测对象或数组
  • 聊聊flink的TableFactory
  • 实现简单的正则表达式引擎
  • 一份游戏开发学习路线
  • No resource identifier found for attribute,RxJava之zip操作符
  • 仓管云——企业云erp功能有哪些?
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $(selector).each()和$.each()的区别
  • (2)Java 简介
  • (C++)八皇后问题
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (层次遍历)104. 二叉树的最大深度
  • (分布式缓存)Redis分片集群
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (三)终结任务
  • (一)Java算法:二分查找
  • (转)JAVA中的堆栈
  • (轉貼) UML中文FAQ (OO) (UML)
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET MVC之AOP
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET下ASPX编程的几个小问题
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具