【问题标题】:docker network through a specific physical interface通过特定物理接口的 docker 网络
【发布时间】:2018-12-24 15:21:48
【问题描述】:

所以我正在尝试创建一个网络 (docker network create),以便其流量将通过特定的物理网络接口 (NIC);我有两个:<iface1>(内部)和<iface2>(外部)。

我需要将两个 NIC 的流量进行物理分离。


方法一

我认为macvlan 是用于创建此类网络的驱动程序。 对于我在互联网上找到的大部分内容,解决方案是指 Pipework(现已弃用)和临时 docker-plugins(也已弃用)。 最能帮助我的是this1

docker network create -d macvlan \
    --subnet 192.168.0.0/16 \
    --ip-range 192.168.2.0/24 \
    -o parent=wlp8s0.1 \
    -o macvlan_mode=bridge \
    macvlan0

然后,为了让容器从主机可见,我需要在主机中执行此操作:

sudo ip link add macvlan0 link wlp8s0.1 type macvlan mode bridge
sudo ip addr add 192.168.2.10/16 dev macvlan0
sudo ifconfig macvlan0 up

现在容器和主机互相看到了:) 但是容器无法访问本地网络。 这个想法是容器可以访问互联网。


方法2

因为我将手动使用<iface2>,所以如果默认情况下流量通过<iface1>,我没问题。 但无论我以哪种顺序启动 NIC(我也尝试暂时删除 <iface2> 的 LKM);整个流量总是被外部网卡<iface2> 取代。 我发现它发生是因为路由表会在某个“随机”时间自动更新。 为了强制流量通过<iface1>,我必须(在主机中):

sudo route del -net <net> gw 0.0.0.0 netmask 255.0.0.0 dev <iface2>
sudo route del default <iface2>

现在,我可以(通过多种方式)验证流量是否刚刚通过&lt;iface1&gt;。 但是路由表更新(自动)的那一刻,所有流量都移动到&lt;iface2&gt;。该死! 我确信有一种方法可以使路由表“静态”或“持久”。


编辑(2018 年 7 月 18 日): 主要思想是能够通过 docker 容器使用 仅一个 两个可用的物理网络接口访问互联网。

【问题讨论】:

    标签: docker networking docker-networking nic macvlan


    【解决方案1】:

    我的环境:

    在为 vm virbr0 网桥创建的主机上,IP 地址为 192.168.122.1,并在 vm 实例上使用接口 ens3 和 IP 地址 192.168.122.152。

    192.168.122.1 - 是 192.168.122.0/24 网络的网关。

    进入虚拟机:

    创建网络:

     # docker network create --subnet 192.168.122.0/24 --gateway 192.168.122.1 --driver macvlan -o parent=ens3 vmnet
    

    创建 docker 容器:

    # docker run -ti --network vmnet alpine ash
    

    检查:

    / # ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
    12: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
        link/ether 02:42:c0:a8:7a:02 brd ff:ff:ff:ff:ff:ff
        inet 192.168.122.2/24 brd 192.168.122.255 scope global eth0
           valid_lft forever preferred_lft forever
    / # ping 192.168.122.152
    PING 192.168.122.152 (192.168.122.152): 56 data bytes
    ^C
    --- 192.168.122.152 ping statistics ---
    2 packets transmitted, 0 packets received, 100% packet loss
    / # ping 192.168.122.1
    PING 192.168.122.1 (192.168.122.1): 56 data bytes
    64 bytes from 192.168.122.1: seq=0 ttl=64 time=0.471 ms
    ^C
    --- 192.168.122.1 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.471/0.471/0.471 ms
    

    好的,我启动另一个 ip 地址为 192.168.122.73 的虚拟机并从 docker 检查:

    / # ping 192.168.122.73 -c2
    PING 192.168.122.73 (192.168.122.73): 56 data bytes
    64 bytes from 192.168.122.73: seq=0 ttl=64 time=1.630 ms
    64 bytes from 192.168.122.73: seq=1 ttl=64 time=0.984 ms
    
    --- 192.168.122.73 ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
    round-trip min/avg/max = 0.984/1.307/1.630 ms
    

    从 docker 实例我无法 ping 虚拟机上的接口,但我可以访问本地网络。

    / # ip n|grep 192.168.122.152
    192.168.122.152 dev eth0  used 0/0/0 probes 6 FAILED
    

    在 vm 上我添加 macvlan0 nic:

    # ip link add macvlan0 link ens3 type macvlan mode bridge
    # ip addr add 192.168.122.100/24 dev macvlan0
    # ip l set macvlan0 up
    

    我可以从 docker ping 192.168.122.100:

    / # ping 192.168.122.100 -c2
    PING 192.168.122.100 (192.168.122.100): 56 data bytes
    64 bytes from 192.168.122.100: seq=0 ttl=64 time=0.087 ms
    64 bytes from 192.168.122.100: seq=1 ttl=64 time=0.132 ms
    
    --- 192.168.122.100 ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
    round-trip min/avg/max = 0.087/0.109/0.132 ms
    

    【讨论】:

      最近更新 更多