通过 VXLAN 搭建 overlay 网络
date
Jul 31, 2022
updateDate
slug
overlay-network-with-vxlan
status
Published
tags
Kubernetes
Network
VXLAN
summary
手动模拟flannel vxlan 的组网原理
type
Post
VXLAN(Virtual eXtensible Local Area Network,虚拟扩展局域网),是对传统VLAN协议的一种扩展。VXLAN的特点是将L2的以太帧封装到UDP报文(即L2 over L4)中,并在L3网络中传输。
关于 vxlan 的原理网上有很多写的非常好的文章做解释,本文不过多说明,只是解释如何实践。
此文为了学习 flannel 中的 vxlan 网络,基本原理和 flannel 差不多。
目的
使 3 台 虚拟机的 docker 容器 之间网络互通。
原理以及数据流:
假设 01 节点上有一个容器 ip
192.168.230.2
需要访问 03 节点上的 192.168.231.2
- 容器到本地节点之间互通,这一部分由 容器和节点之间的 veth pair 实现。
- 数据包到达本地节点后,交由 本地 vxlan device 将这个 L2 数据包包装成 L4 的 udp 包发到往 目的节点的 vxlan device。
- 目的 vxlan 收到后拆包出 L2 数据包
- 此时进入本地节点和容器之间的互相通信。
整体规划:
Host | node ip | docker0 | VXLAN ip | VXLAN Mac (可以由linux自动生成) |
vxlan-01 | 10.0.0.230/24 | 192.168.230.1/24 | 192.168.230.0/32 | aa:bb:cc:dd:ee:00 |
vxlan-02 | 10.0.0.231/24 | 192.168.231.1/24 | 192.168.231.0/32 | aa:bb:cc:dd:ee:01 |
vxlan-03 | 10.0.0.232/24 | 192.168.232.1/24 | 192.168.232.0/32 | aa:bb:cc:dd:ee:02 |
在各个虚拟机上配置 vxlan device,(mac 地址建议用 linux 自动生成,这里为了测试提前规划好了一个随便的 mac 地址)
节点都在同一个子网中,直接加一条路由规则也可达到目的(即 flannel 中的 host-gw 模式)此文章仅为了学习 vxlan
ip route add 192.168.231.0/24 via 10.0.0.231 ip route add 192.168.232.0/24 via 10.0.0.232
- vxlan-01
VNI=99 PORT=4899 VXIP=192.168.230.0/32 VXMAC=aa:bb:cc:dd:ee:00 PREFIX=vxlan DEVNAME=$PREFIX.$VNI ip link add $DEVNAME type vxlan id $VNI dev ens18 dstport $PORT nolearning ip addr add $VXIP dev $DEVNAME ip link set dev $DEVNAME address $VXMAC ip link set $DEVNAME up
- vxlan-02
VNI=99 PORT=4899 VXIP=192.168.231.0/32 VXMAC=aa:bb:cc:dd:ee:01 PREFIX=vxlan DEVNAME=$PREFIX.$VNI ip link add $DEVNAME type vxlan id $VNI dev ens18 dstport $PORT nolearning ip addr add $VXIP dev $DEVNAME ip link set dev $DEVNAME address $VXMAC ip link set $DEVNAME up
- vxlan-03
VNI=99 PORT=4899 VXIP=192.168.232.0/32 VXMAC=aa:bb:cc:dd:ee:02 PREFIX=vxlan DEVNAME=$PREFIX.$VNI ip link add $DEVNAME type vxlan id $VNI dev ens18 dstport $PORT nolearning ip addr add $VXIP dev $DEVNAME ip link set dev $DEVNAME address $VXMAC ip link set $DEVNAME up
配置 route 表
命中 vxlan2, 和 vxlan3 的 子网通过 vxlan device 转发,并设置下一跳为对应的 vxlanip
vxlan1ip=192.168.230.0 vxlan2ip=192.168.231.0 vxlan3ip=192.168.232.0 vxlan1mac=aa:bb:cc:dd:ee:00 vxlan2mac=aa:bb:cc:dd:ee:01 vxlan3mac=aa:bb:cc:dd:ee:02 node1ip=10.0.0.230 node2ip=10.0.0.231 node3ip=10.0.0.232
- vxlan-01
ip route add $vxlan2ip/24 via $vxlan2ip dev $DEVNAME onlink ip route add $vxlan3ip/24 via $vxlan3ip dev $DEVNAME onlink
- vxlan-02
ip route add $vxlan1ip/24 via $vxlan1ip dev $DEVNAME onlink ip route add $vxlan3ip/24 via $vxlan3ip dev $DEVNAME onlink
- vxlan-03
ip route add $vxlan1ip/24 via $vxlan1ip dev $DEVNAME onlink ip route add $vxlan2ip/24 via $vxlan2ip dev $DEVNAME onlink
配置 ARP 表
这一步理论上不需要手动配置,可以通过 vxlan 的多播模式达到目的,但本篇没有使用 vxlan 的多播模式组网,需要手动配置
- vxlan-01
ip neighbor add $vxlan2ip lladdr $vxlan2mac dev $DEVNAME ip neighbor add $vxlan3ip lladdr $vxlan3mac dev $DEVNAME
- vxlan-02
ip neighbor add $vxlan1ip lladdr $vxlan1mac dev $DEVNAME ip neighbor add $vxlan2ip lladdr $vxlan2mac dev $DEVNAME
- vxlan-03
ip neighbor add $vxlan1ip lladdr $vxlan1mac dev $DEVNAME ip neighbor add $vxlan3ip lladdr $vxlan3mac dev $DEVNAME
配置 FDB 转发表
当我们配置号 arp 和 route 之后,拿到了需要访问的 ip 和mac地址,但是不知道哪里由这个 mac 地址,此时我们需要配置 fdb 转发表将其关联起来
- vxlan-01
bridge fdb add $vxlan2mac dev $DEVNAME dst $node2ip bridge fdb add $vxlan3mac dev $DEVNAME dst $node3ip
- vxlan-02
bridge fdb add $vxlan1mac dev $DEVNAME dst $node1ip bridge fdb add $vxlan3mac dev $DEVNAME dst $node3ip
- vxlan-03
bridge fdb add $vxlan2mac dev $DEVNAME dst $node2ip bridge fdb add $vxlan1mac dev $DEVNAME dst $node1ip
至此,网络应该互通,测试一下吧
root@vxlan-01:~# ping -c1 192.168.231.1 PING 192.168.231.1 (192.168.231.1) 56(84) bytes of data. 64 bytes from 192.168.231.1: icmp_seq=1 ttl=64 time=0.660 ms --- 192.168.231.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.660/0.660/0.660/0.000 ms root@vxlan-01:~# ping -c1 192.168.232.1 PING 192.168.232.1 (192.168.232.1) 56(84) bytes of data. 64 bytes from 192.168.232.1: icmp_seq=1 ttl=64 time=0.534 ms --- 192.168.232.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.534/0.534/0.534/0.000 ms root@vxlan-01:~# docker run -it --rm busybox sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 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 7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:c0:a8:e6:02 brd ff:ff:ff:ff:ff:ff inet 192.168.230.2/24 brd 192.168.230.255 scope global eth0 valid_lft forever preferred_lft forever / # ping 192.168.231.1 PING 192.168.231.1 (192.168.231.1): 56 data bytes 64 bytes from 192.168.231.1: seq=0 ttl=63 time=0.732 ms 64 bytes from 192.168.231.1: seq=1 ttl=63 time=0.461 ms
Tips: wireshark 可以直接对抓取的 udp 数据包进行 decode 成 vxlan 数据结构,如果需要排查会非常方便。