[toc]

利用vxlan构建二层虚拟机网络

每台vm配置 vxlan 网卡以及 ip 地址且所有节点 vxlan 网卡的地址必须是同一个网段

node name node ip vxlan-test ip vxlan-test mac pod network
master1 10.211.55.5 179.17.1.21 c2:6a:9b:e5:39:8d 10.234.111.0/24
node1 10.211.55.6 179.17.1.31 7a:3a:fe:45:a3:76 10.234.118.0/24

pod-vxlan.png

方案

pod跨节点通信有flannel, calico等,通常采用vxlan,ipip等隧道技术。本文使用vxlan实现pod跨节点通信

整体步骤:

  1. 为所有节点创建 vxlan-test 虚拟网卡,并配置ip
  2. 在当前节点配置去往其他节点的 Pod 网段的路由信息且指定下一跳是目标节点的 vxlan-test 网卡ip
  3. 为每个节点的 vxlan-test 网卡配置 FDBarp 表, FDB表记录vxlan-test 网卡的 mac 地址以及其节点的 ip 地址映射

创建vxlan设备及配置ip

1
2
3
4
ip link add vxlan-test type vxlan id 10001 dstport 4899 local 10.211.55.5 dev enp0s5 nolearning
ip addr add 179.17.1.21/24 dev vxlan-test
ip link set dev vxlan-test address c2:6a:9b:e5:39:8d
ip link set vxlan-test up
1
2
3
4
ip link add vxlan-test type vxlan id 10001 dstport 4899 local 10.211.55.6 dev enp0s5  nolearning
ip link set dev vxlan-test address 7a:3a:fe:45:a3:76
ip addr add 179.17.1.31/24 dev vxlan-test
ip link set vxlan-test up

配置ARP表和FDB表

使得所有节点的vxlan-test网卡之间可以互通。

on master1

1
2
3
4
5
6
#配置ARP表, ip and mac of vxlan on other nodes 
arp -s 179.17.1.31 7a:3a:fe:45:a3:76

#配置FDB表, vxlan mac and node ip of other nodes
bridge fdb append 7a:3a:fe:45:a3:76 dst 10.211.55.6 dev vxlan-test

on node1

1
2
3
4
5
#配置ARP表, ip and mac of vxlan on other nodes
arp -s 179.17.1.21 c2:6a:9b:e5:39:8d

#配置FDB表, vxlan mac and node ip of other nodes
bridge fdb append c2:6a:9b:e5:39:8d dst 10.211.55.5 dev vxlan-test

创建pod netns

创建veth pair设备,连接nsroot ns
on master1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建ns, 并将一端放入ns中
ip netns add vxlan.ns1
ip link add veth1-vxlan-ns1 type veth peer name veth2-vxlan-ns1
ip link set veth1-vxlan-ns1 netns vxlan.ns1

// ns测配置ip, default route
ip -n vxlan.ns1 addr add 10.234.111.10/24 dev veth1-vxlan-ns1
ip -n vxlan.ns1 link set veth1-vxlan-ns1 up
ip netns exec vxlan.ns1 ip route add default via 10.234.111.1 dev veth1-vxlan-ns1
ip -n vxlan.ns1 link set veth1-vxlan-ns1 up

// host测配置ip
ip addr add 10.234.111.1/24 dev veth2-vxlan-ns1
ip link set veth2-vxlan-ns1 up

on node

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ip netns add vxlan.ns1

ip link add veth1-vxlan-ns1 type veth peer name veth2-vxlan-ns1

ip link set veth1-vxlan-ns1 netns vxlan.ns1

// ns测配置
ip -n vxlan.ns1 addr add 10.234.118.10/24 dev veth1-vxlan-ns1
ip -n vxlan.ns1 link set veth1-vxlan-ns1 up
ip netns exec vxlan.ns1 ip route add default via 10.234.118.1 dev veth1-vxlan-ns1
ip -n vxlan.ns1 link set veth1-vxlan-ns1 up

// host测配置
ip addr add 10.234.118.1/24 dev veth2-vxlan-ns1
ip link set veth2-vxlan-ns1 up
1
2
3
# ping 10.234.118.10
PING 10.234.118.10 (10.234.118.10) 56(84) bytes of data.
^C

此时master无法感知到node上pod网络,所以不通

配置路由规则打通跨节点跨pod网络

on master

1
route add -net 10.234.118.0/24 gw 179.17.1.31 dev vxlan-test

on node

1
route add -net 10.234.111.0/24 gw 179.17.1.21 dev vxlan-test

测试

on master

1
2
3
4
5
6
7
8
9
10
在host上ping node pod ip
# ping 10.234.118.10
PING 10.234.118.10 (10.234.118.10) 56(84) bytes of data.
64 bytes from 10.234.118.10: icmp_seq=1 ttl=63 time=0.810 ms

在master pod ns里ping node pod ip
# ip netns exec vxlan.ns1 ping 10.234.118.10
PING 10.234.118.10 (10.234.118.10) 56(84) bytes of data.
64 bytes from 10.234.118.10: icmp_seq=1 ttl=62 time=0.888 ms
64 bytes from 10.234.118.10: icmp_seq=2 ttl=62 time=1.15 ms

on node

1
2
3
4
5
6
7
# ping 10.234.111.10
PING 10.234.111.10 (10.234.111.10) 56(84) bytes of data.
64 bytes from 10.234.111.10: icmp_seq=1 ttl=63 time=0.957 ms

# ip netns exec vxlan.ns1 ping 10.234.111.10
PING 10.234.111.10 (10.234.111.10) 56(84) bytes of data.
64 bytes from 10.234.111.10: icmp_seq=1 ttl=62 time=0.716 ms
1
2
3
4
5
# ip netns exec vxlan.ns1 traceroute 10.234.118.10
traceroute to 10.234.118.10 (10.234.118.10), 30 hops max, 60 byte packets
1 _gateway (10.234.111.1) 1.124 ms 1.065 ms 1.052 ms
2 179.17.1.31 (179.17.1.31) 1.041 ms 18779.342 ms 18779.350 ms
3 10.234.118.10 (10.234.118.10) 1.706 ms 1.666 ms 1.568 ms

ether pair -> peer node vxlan -> pod ip
看不到宿主机设备

vxlan是如何工作的

当pod出来的包,访问目的pod ip是10.234.118.10,作为内层包的dst ip, pod自己的ip就是内层包src ip, 根据节点上的路由规则

1
10.234.118.0/24 via 179.17.1.31 dev vxlan-test

将会从本机的 vxlan-test 网卡出

vxlan-test设备进行封包

  1. 封装内层mac, 该包下一跳是179.17.1.31,即peer node vxlan-test 网卡的mac作为内层macdst mac

peer node vxlan-test 网卡的mac可从master上的arp表会查询到。

疑问:如何拿到其他节点的vxlan mac,毕竟是任意设置的网络?
在本实验中是自己手动配置的

1
2
3
# arp -n
Address HWtype HWaddress Flags Mask Iface
179.17.1.31 ether 7a:3a:fe:45:a3:76 CM vxlan-test
  1. 外层需要添加vxlan header, 其中有vni标记,表明包由哪个vxlan设备处理,也就用作二层网络隔离。该vni标记是在创建vxlan设备时设置。
  2. 再加一层udp header, udp的端口创建vxlan虚拟网卡时会设置。
  3. 然后封装外层包的ipmac层,通过内层dst mac查找 vxlan-test 网卡的 FDB 表, 找到peer node vxlan设备对应的宿主机ip, 且作为外层包dst ip,即设置为10.211.55.6(node宿主机的ip),src ip就是宿主机的ip
    1
    2
    # bridge fdb show dev vxlan-test
    7a:3a:fe:45:a3:76 dst 10.211.55.6 self permanent
  4. 最外层的mac根据master和node宿主机ip是否同网络而设置。如果不同网络,则是master 网关网口的mac地址。本环境恰好是同网络,dst mac就是node宿主机的网口mac
    6.vxlan包封装好后, 包经过master和node的宿主机网络最终到达node节点。node发现是一个vxlan包,内核将外层mac~udp剥掉后取出内部数据帧, 内核协议栈根据vxlan headervni值交给vxlan-test处理, vxlan-test网卡拆包,比对dst mac是自己的,则剥掉mac取出原始的ip包(dst ip是pod ip),经过宿主机的路由达到目标pod中。

总结

  1. pod包会从vxlan设备发且下一跳是peer node上的vxlan ip
  2. 在本地arp表中,可获取peer node vxlan设备的mac
  3. 在本机fdb表里记录peer node vxlan device mac和其所在节点的宿主机ip
  4. inner ip是两个pod的ip
  5. inner dst macpeer node vxlan device mac.
  6. outer ip是宿主机的物理网口
  7. 所有节点的vxlan必须在同一个网络,大二层
  8. 节点可以有多个打二层,通过vni区分