Docker容器跨主机访问之macvlan网络

Docker跨主机访问

macvlan

创建macvlan网络

      打开网卡的混杂模式,并查看网卡状态up且promisc模式已经生效

      在两个主机上创建macvlan网络macvlan_net1 

      在另一台主机上执行相同的命令 

      -d macvlan指定driver为macvlan

      macvlan网络是local网络,为了保证跨主机能够通信,用户需要自己管理IP subnet

      与其他网络不同,docker不会为macvlan创建网关,这里的网关应该是真实存在的,否则容器无法路由

      -o parent指定使用的网络接口

 

      在第一台主机上运行容器test1并连接到macvlan_net1 

      由于两台主机中的macvlan_net1本质上是独立的,为了避免自动分配造成IP冲突,最好通过--ip指定test的地址

      在第二台主机上运行容器test2,指定IP为172.16.86.11 

      验证test1与test2的通信,由结果可以得出macvlan实现了跨主机访问的功能 

      test2可以ping到test1的IP 172.16.86.10,但无法解析test1主机名,可见docker没有为macvlan提供DNS服务 

 

macvlan的网络结构

      查看容器test1的网络设备 

      除了lo,容器只有一个eth0,eth0 后面的@if2表明该interface有一个对应的interface,其全局的编号为2。根据macvlan的原理,我们有理由猜测这个interface 就是主机的enp0s5,确认如下 

      可见,容器的eth0就是enp0s5通过macvlan虚拟出来的interface。容器的interface直接与主机的网卡连接,这种方案使得容器无需通过NAT和端口映射就能与外网直接通信(只要有网关),在网络上与其他独立主机没有区别

 

用sub-interface 实现多macvlan 网络

      macvlan会独占主机的网卡,也就是说一个网卡只能创建一个macvlan网络,否则会报错

      但主机的网卡数量是有限的,如何支持更多的macvlan网络呢?Linux 的网卡也能支持VLAN(apt-get install vlan),同一个interface可以收发多个VLAN的数据包,不过前提是要创建VLAN的sub-interface。比如希望enp0s5同时支持VLAN10和VLAN20,则需创建sub-interface enp0s5.10和enp0s5.20。

      下面演示如何在enp0s5.10和enp0s5.20上创建macvlan 网络。

            (1)首先编辑两台主机的/etc/network/interfaces,配置sub-

auto enp0s5
iface enp0s5 inet manual
auto enp0s5.10
iface enp0s5.10 inet manual
vlan-raw-device enp0s5
auto enp0s5.20
iface enp0s5.20 inet manual
vlan-raw-device enp0s5 

            (2)然后启用sub-interface

sudo ifup enp0s5.10
sudo ifup enp0s5.20 

             (3)创建macvlan 网络

sudo docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=enp0s5.10 mac_net10
sudo docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=enp0s5.20 mac_net20 

             (4)在第一台主机上中运行容器

sudo docker run -itd --name test5 --ip=172.16.10.10 --network mac_net10 busybox
sudo docker run -itd --name test6 --ip=172.16.20.10 --network mac_net20 busybox 

             (5)在第二台主机中运行容器

sudo docker run -itd --name test7 --ip=172.16.10.11 --network mac_net10 busybox
sudo docker run -itd --name test8 --ip=172.16.20.11 --network mac_net20 busybox 

 

验证macvlan之间的连通性

      为了方便验证网络的通信,先对所创建的容器进行相应的说明:test5与test7这两个容器处于mac_net10下,IP分别为172.16.10.10和172.16.10.11;test6与test8处于mac_net20下,IP分别为172.16.20.10和172.16.20.11

      让处于同一macvlan网络下的容器互ping,由结果可以看出同一macvlan网络下的容器之间是可以通信的 

      让处于不同macvlan网络下的容器互ping 

      由结果可以看出不同macvlan之间不能通信。准确的说是不同macvlan网络不能在二层上通信,在三层上可以通过网关将macvlan连通,下面我们就启用网关。我们将第三台主机配置成一个虚拟路由器,设置网关并转发VLAN10和VLAN20的流量,首先确保IP Forwarding已经启用 

      输出为1则表示启用,如果为0可通过如下命令启用

sudo sysctl -w net.ipv4.ip_forward=1

      在 /etc/network/interfaces中配置vlan sub-interface

auto enp0s5
iface enp0s5 inet manual
auto enp0s5.10
iface enp0s5.10 inet manual
vlan-raw-device enp0s5
auto enp0s52.20
iface enp0s5.20 inet manual
vlan-raw-device enp0s5 

      启用sub-interface

sudo ifup enp0s5.10
sudo ifup enp0s5.20 

      将网关IP配置到sub-interface

sudo ifconfig enp0s5.10 172.16.10.1 netmask 255.255.255.0 up
sudo ifconfig enp0s5.20 172.16.20.1 netmask 255.255.255.0 up 

      添加iptables规则,转发不同VLAN的数据包

iptables -t nat -A POSTROUTING -o enp0s5.10 -j MASQUERADE
iptables -t nat -A POSTROUTING -o enp0s5.20 -j MASQUERADE

iptables -A FORWARD -i enp0s5.10 -o enp0s5.20 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i enp0s5.20 -o enp0s5.10 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i enp0s5.10 -o enp0s5.20 -j ACCEPT
iptables -A FORWARD -i enp0s5.20 -o enp0s5.10 -j ACCEPT 

      现在第一台主机上位于mac_net10的test5已经可以与第二台主机上位于mac_net20的test8通信了 

 

下面分析数据包是如何从test5(172.16.10.10)到达test8(172.16.20.11)的

      (1)因为test5与test8在不同的IP网段,根据test5的路由表,数据包将发送到网段172.16.10.1 

      (2)路由器从enp0s5.10收到数据包,发现目的地址是172.16.20.11,查看自己的路由表,并将数据包从enp0s5.20转发出去 

      (3)通过ARP记录的信息,路由器能够得知172.16.20.11在第二台主机上,于是将数据包发送给第二台主机

      (4)第二台主机根据目的地址和VLAN信息将数据包发送给test8

      macvlan网络的连通性和隔离完全依赖VLAN、IP subnet和路由,docker本身不做任何限制,用户可以像管理传统VLAN网络那样管理macvlan

 

posted @ 2018-10-29 21:36  Chenjin2018  阅读(3366)  评论(1编辑  收藏  举报