手工实现docker的vxlan
前几天了解了一下docker overlay的原理,然后一直想验证一下自己的理解是否正确,今天模仿docker手工搭建了一个overlay网络。先上拓扑图,其实和上次画的基本一样。我下面提到的另一台机器是和下面拓扑图配置方法一样的一台机器,我就不重复画了。
首先实现图上红线部分,这部分是访问本机的container,主要涉及负载均衡(sandbox_1)和一个交换机(sandbox_2),不涉及overlay网络。
- 创建各个namespace和必要的veth
ip netns add sandbox_1 ip netns add sandbox_2 ip netns add container ip link add pandora_bridge type bridge ip addr add 172.18.0.1/16 dev pandora_bridge ip link add veth100 type veth peer name veth101 ip link set veth100 master pandora_bridge ip link set veth101 netns sandbox_1 ip link set pandora_bridge up ip link set veth100 up ip link add veth102 type veth peer name veth103 ip link set veth102 netns sandbox_1 ip link set veth103 netns sandbox_2 ip link add veth104 type veth peer name veth105 ip link set veth104 netns sandbox_2 ip link set veth105 netns container
- 设置sandbox_1里的路由和负载均衡
ip netns exec sandbox_1 bash ip addr add 172.18.0.2/16 dev veth101 ip addr add 10.0.0.2/24 dev veth102 ip route add default via 172.18.0.1 ip link set veth101 up ip link set veth102 up ipvsadm -A -t 172.18.0.2:80 -s rr ipvsadm -a -t 172.18.0.2:80 -r 10.0.0.4 -m iptables -t nat -I POSTROUTING -d 10.0.0.0/24 -m ipvs --ipvs -j SNAT --to-source 10.0.0.2 echo 1 >/proc/sys/net/ipv4/vs/conntrack #这个地方困扰我很久
- 设置sandbox_2里的交换机
ip netns exec sandbox_2 bash ip link add edge_bridge type bridge ip link set veth103 master edge_bridge ip link set veth104 master edge_bridge ip addr add 10.0.0.1/24 dev edge_bridge ip link set edge_bridge up ip link set veth103 up ip link set veth104 up
- 启动容器
ip netns exec container bash ip addr add 10.0.0.4/24 dev veth105 ip link set veth105 up ip route add default via 10.0.0.1 /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
- 把外网口ens33的数据包转到这个处理流程
iptables -t nat -I PREROUTING -d 192.168.228.148 -p tcp --dport 80 -j DNAT --to-destination 172.18.0.2
上面这些步骤设置完整个红色的流程就能走通了。我在设置的时候负载均衡那里数据包始终不走POSTROUTING链,没法设置SNAT,浪费了不少时间,后来谷歌发现需要设置echo 1 >/proc/sys/net/ipv4/vs/conntrack,这个参数具体什么意思我还没去查。其他设置都很好理解。
然后处理绿线的部分,这个是overlay最关键的地方
- 创建vxlan并且加入交换机,注意这个vxlan一定要在namespace 1里创建然后挪到sandbox_2,而且这个proxy也很重要,因为我们需要vxlan的arp代理功能(和普通设备的arp代理不一样),因为在overlay网络里广播非常耗资源,我们使用静态arp和vxlan的arp代理处理arp请求。
ip link add vxlan0 type vxlan id 100 dstport 4789 proxy ip link set vxlan0 netns sandbox_2
- 在vxlan0设置静态arp,这两个mac地址是我另一台机器上container和sandbox_2里的设备
ip netns exec sandbox_2 bash ip link set vxlan0 master edge_bridge arp -i vxlan0 -s 10.0.0.12 1e:66:c0:a0:95:3f arp -i vxlan0 -s 10.0.0.14 3a:7f:72:5b:5d:dd
- 在vxlan0上设置转发,告诉vxlan0那些数据包需要发给overlay的其他节点,这两个mac地址和上面两个对应,ip地址是另一台机器的ip地址
ip netns exec sandbox_2 bash bridge fdb add 3a:7f:72:5b:5d:dd dev vxlan0 dst 192.168.228.149 bridge fdb add 1e:66:c0:a0:95:3f dev vxlan0 dst 192.168.228.149
- 配置负载均衡,把部分流量转到另一台机器
ipvsadm -a -t 172.18.0.2:80 -r 10.0.0.14:80 -m
到这里这台机器就配置好了。
另一台机器配置方法一样,我就直接把命令贴出来了
ip netns add sandbox_1 ip netns add sandbox_2 ip netns add container ip link add pandora_bridge type bridge ip addr add 172.18.0.1/16 dev pandora_bridge ip link add veth100 type veth peer name veth101 ip link set veth100 master pandora_bridge ip link set veth101 netns sandbox_1 ip link set pandora_bridge up ip link set veth100 up ip link add veth102 type veth peer name veth103 ip link set veth102 netns sandbox_1 ip link set veth103 netns sandbox_2 ip link add veth104 type veth peer name veth105 ip link set veth104 netns sandbox_2 ip link set veth105 netns container iptables -t nat -I PREROUTING -d 192.168.228.149 -p tcp --dport 80 -j DNAT --to-destination 172.18.0.2 ip link add vxlan0 type vxlan id 100 dstport 4789 proxy ip link set vxlan0 netns sandbox_2 ip netns exec sandbox_1 bash ip addr add 172.18.0.2/16 dev veth101 ip addr add 10.0.0.12/24 dev veth102 ip link set veth101 up ip link set veth102 up ip route add default via 172.18.0.1 ipvsadm -A -t 172.18.0.2:80 -s rr ipvsadm -a -t 172.18.0.2:80 -r 10.0.0.14 -m ipvsadm -a -t 172.18.0.2:80 -r 10.0.0.4 -m iptables -t nat -I POSTROUTING -d 10.0.0.0/24 -m ipvs --ipvs -j SNAT --to-source 10.0.0.12 echo 1 >/proc/sys/net/ipv4/vs/conntrack ip netns exec sandbox_2 bash ip link add edge_bridge type bridge ip link set veth103 master edge_bridge ip link set veth104 master edge_bridge ip addr add 10.0.0.11/24 dev edge_bridge ip link set edge_bridge up ip link set veth103 up ip link set veth104 up ip link set vxlan0 master edge_bridge ip link set vxlan0 up arp -i vxlan0 -s 10.0.0.4 2a:bb:1a:0f:2c:3a arp -i vxlan0 -s 10.0.0.2 0e:a8:06:71:ca:cc bridge fdb add 2a:bb:1a:0f:2c:3a dev vxlan0 dst 192.168.228.148 bridge fdb add 0e:a8:06:71:ca:cc dev vxlan0 dst 192.168.228.148 ip netns exec container bash ip addr add 10.0.0.14/24 dev veth105 ip link set veth105 up ip route add default via 10.0.0.11 /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf