IPvlan 网络驱动程序

IPvlan 驱动程序允许用户完全控制 IPv4 和 IPv6 地址。VLAN 驱动程序在此基础上构建,为运营商提供对 2 层 VLAN 标记甚至 IPvlan L3 路由的完全控制,适用于对底层网络集成感兴趣的用户。对于抽象化物理约束的覆盖网络部署,请参阅 多主机覆盖网络 驱动程序。

IPvlan 是对久经考验的网络虚拟化技术的全新诠释。Linux 实现非常轻量级,因为它们不是使用传统的 Linux 桥接进行隔离,而是与 Linux 以太网接口或子接口关联,以强制执行网络之间的隔离以及与物理网络的连接。

IPvlan 提供了许多独特的功能,并且在各种模式下还有很大的创新空间。这些方法的两个高级优势是:绕过 Linux 桥接的积极性能影响以及部件更少的简单性。移除传统上位于 Docker 主机网卡和容器接口之间的桥接,留下一个简单的设置,该设置由直接连接到 Docker 主机接口的容器接口组成。对于外部服务而言,此结果易于访问,因为在这些情况下不需要端口映射。

选项

下表描述了在使用 `ipvlan` 驱动程序创建网络时,可以传递给 `--option` 的驱动程序特定选项。

选项默认值描述
ipvlan_model2设置 IPvlan 操作模式。可以是以下之一:`l2`、`l3`、`l3s`
ipvlan_flagbridge设置 IPvlan 模式标志。可以是以下之一:`bridge`、`private`、`vepa`
parent指定要使用的父接口。

示例

先决条件

  • 此页面上的示例都是单主机的。
  • 所有示例都可以在运行 Docker 的单一主机上执行。任何使用子接口(例如 `eth0.10`)的示例都可以替换为 `eth0` 或 Docker 主机上的任何其他有效父接口。带有 `.` 的子接口会动态创建。也可以从 `docker network create` 中完全省略 `-o parent` 接口,驱动程序将创建一个 `dummy` 接口,该接口将启用本地主机连接以执行示例。
  • 内核要求
    • IPvlan Linux 内核 v4.2+(支持早期内核,但存在错误)。要检查您当前的内核版本,请使用 `uname -r`

IPvlan L2 模式示例用法

下图显示了 IPvlan `L2` 模式拓扑的示例。驱动程序使用 `-d driver_name` 选项指定。在本例中为 `-d ipvlan`。

Simple IPvlan L2 Mode Example

下一个示例 `-o parent=eth0` 中的父接口配置如下

$ ip addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.1.250/24 brd 192.168.1.255 scope global eth0

使用主机接口的网络作为 `docker network create` 中的 `--subnet`。容器将连接到与通过 `-o parent=` 选项设置的主机接口相同的网络。

创建 IPvlan 网络并运行连接到它的容器

# IPvlan  (-o ipvlan_mode= Defaults to L2 mode if not specified)
$ docker network create -d ipvlan \
    --subnet=192.168.1.0/24 \
    --gateway=192.168.1.1 \
    -o ipvlan_mode=l2 \
    -o parent=eth0 db_net

# Start a container on the db_net network
$ docker run --net=db_net -it --rm alpine /bin/sh

# NOTE: the containers can NOT ping the underlying host interfaces as
# they are intentionally filtered by Linux for additional isolation.

IPvlan 的默认模式为 `l2`。如果未指定 `-o ipvlan_mode=`,则将使用默认模式。类似地,如果 `--gateway` 为空,则网络上的第一个可用地址将被设置为网关。例如,如果在网络创建中提供的子网为 `--subnet=192.168.1.0/24`,则容器接收的网关为 `192.168.1.1`。

为了帮助理解此模式如何与其他主机交互,下图显示了两个 Docker 主机之间的相同 2 层段,这适用于 IPvlan L2 模式。

Multiple IPvlan hosts

以下操作将创建与前面创建的 `db_net` 网络完全相同的网络,并使用 `--gateway=192.168.1.1` 和 `-o ipvlan_mode=l2` 的驱动程序默认值。

# IPvlan  (-o ipvlan_mode= Defaults to L2 mode if not specified)
$ docker network create -d ipvlan \
    --subnet=192.168.1.0/24 \
    -o parent=eth0 db_net_ipv

# Start a container with an explicit name in daemon mode
$ docker run --net=db_net_ipv --name=ipv1 -itd alpine /bin/sh

# Start a second container and ping using the container name
# to see the docker included name resolution functionality
$ docker run --net=db_net_ipv --name=ipv2 -it --rm alpine /bin/sh
$ ping -c 4 ipv1

# NOTE: the containers can NOT ping the underlying host interfaces as
# they are intentionally filtered by Linux for additional isolation.

驱动程序还支持 `--internal` 标志,该标志将完全隔离网络上的容器与该网络外部的任何通信。由于网络隔离与网络的父接口紧密耦合,因此省略 `docker network create` 的 `-o parent=` 选项的结果与 `--internal` 选项完全相同。如果未指定父接口或使用 `--internal` 标志,则会为用户创建一个 netlink 类型 `dummy` 父接口并用作父接口,从而有效地完全隔离网络。

以下两个 `docker network create` 示例产生相同的网络,您可以将容器附加到这些网络

# Empty '-o parent=' creates an isolated network
$ docker network create -d ipvlan \
    --subnet=192.168.10.0/24 isolated1

# Explicit '--internal' flag is the same:
$ docker network create -d ipvlan \
    --subnet=192.168.11.0/24 --internal isolated2

# Even the '--subnet=' can be left empty and the default
# IPAM subnet of 172.18.0.0/16 will be assigned
$ docker network create -d ipvlan isolated3

$ docker run --net=isolated1 --name=cid1 -it --rm alpine /bin/sh
$ docker run --net=isolated2 --name=cid2 -it --rm alpine /bin/sh
$ docker run --net=isolated3 --name=cid3 -it --rm alpine /bin/sh

# To attach to any use `docker exec` and start a shell
$ docker exec -it cid1 /bin/sh
$ docker exec -it cid2 /bin/sh
$ docker exec -it cid3 /bin/sh

IPvlan 802.1Q trunk L2 模式示例用法

从架构上讲,IPvlan L2 模式中继与 Macvlan 在网关和 L2 路径隔离方面相同。存在可能对 ToR 交换机中的 CAM 表压力、每个端口一个 MAC 以及主机父网卡上的 MAC 耗尽等方面有利的细微差别。802.1Q 中继场景看起来相同。两种模式都遵守标记标准,并与物理网络无缝集成,用于底层集成和硬件厂商插件集成。

同一 VLAN 上的主机通常位于同一子网上,并且几乎总是根据其安全策略分组在一起。在大多数情况下,多层应用程序被分层到不同的子网中,因为每个进程的安全配置文件需要某种形式的隔离。例如,将您的信用卡处理与前端 Web 服务器托管在同一个虚拟网络上将是一个合规性问题,并且会绕过长期存在的纵深防御体系的最佳实践。VLAN 或使用覆盖网络驱动程序时的等效 VNI(虚拟网络标识符)是隔离租户流量的第一步。

Docker VLANs in-depth

带有 VLAN 标签的 Linux 子接口可以已经存在,也可以在调用 `docker network create` 时创建。`docker network rm` 将删除子接口。不会删除诸如 `eth0` 之类的父接口,只会删除 netlink 父索引 > 0 的子接口。

为了方便驱动程序添加/删除VLAN子接口,格式需要为interface_name.vlan_tag。可以使用其他子接口名称作为指定的父接口,但是当调用docker network rm时,链接不会自动删除。

可以使用现有的父VLAN子接口,也可以让Docker管理它们,这使得用户可以选择完全管理Linux接口和网络,或者让Docker创建和删除VLAN父子接口(netlink ip link),而无需用户费力。

例如:使用eth0.10表示带有VLAN ID 10eth0子接口。等效的ip link命令为ip link add link eth0 name eth0.10 type vlan id 10

此示例创建了带VLAN标记的网络,然后启动两个容器来测试容器之间的连接。不同的VLAN之间无法互相ping通,除非有一个路由器在两个网络之间进行路由。根据IPvlan的设计,默认命名空间不可访问,以隔离容器命名空间和底层主机。

VLAN ID 20

在Docker主机标记和隔离的第一个网络中,eth0.20是使用-o parent=eth0.20指定的,带有VLAN ID 20的父接口。可以使用其他命名格式,但是需要使用ip link或Linux配置文件手动添加和删除链接。只要存在-o parent,只要符合Linux netlink规范,任何名称都可以使用。

# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged
$ docker network create -d ipvlan \
    --subnet=192.168.20.0/24 \
    --gateway=192.168.20.1 \
    -o parent=eth0.20 ipvlan20

# in two separate terminals, start a Docker container and the containers can now ping one another.
$ docker run --net=ipvlan20 -it --name ivlan_test1 --rm alpine /bin/sh
$ docker run --net=ipvlan20 -it --name ivlan_test2 --rm alpine /bin/sh

VLAN ID 30

在Docker主机标记和隔离的第二个网络中,eth0.30是使用-o parent=eth0.30指定的,带有VLAN ID 30的父接口。ipvlan_mode=默认为L2模式ipvlan_mode=l2。也可以显式设置,结果与下一个示例相同。

# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged.
$ docker network create -d ipvlan \
    --subnet=192.168.30.0/24 \
    --gateway=192.168.30.1 \
    -o parent=eth0.30 \
    -o ipvlan_mode=l2 ipvlan30

# in two separate terminals, start a Docker container and the containers can now ping one another.
$ docker run --net=ipvlan30 -it --name ivlan_test3 --rm alpine /bin/sh
$ docker run --net=ipvlan30 -it --name ivlan_test4 --rm alpine /bin/sh

网关设置在容器内部作为默认网关。该网关通常是网络上的外部路由器。

$$ ip route
  default via 192.168.30.1 dev eth0
  192.168.30.0/24 dev eth0  src 192.168.30.2

示例:多子网IPvlan L2模式,在同一子网上启动两个容器并互相ping通。为了使192.168.114.0/24能够访问192.168.116.0/24,需要在L2模式下使用外部路由器。L3模式可以在共享公共-o parent=的子网之间进行路由。

当地址空间耗尽时,网络路由器上的辅助地址很常见,可以为L3 VLAN接口添加另一个辅助地址,通常称为“交换虚拟接口”(SVI)。

$ docker network create -d ipvlan \
    --subnet=192.168.114.0/24 --subnet=192.168.116.0/24 \
    --gateway=192.168.114.254 --gateway=192.168.116.254 \
    -o parent=eth0.114 \
    -o ipvlan_mode=l2 ipvlan114

$ docker run --net=ipvlan114 --ip=192.168.114.10 -it --rm alpine /bin/sh
$ docker run --net=ipvlan114 --ip=192.168.114.11 -it --rm alpine /bin/sh

关键在于,运营商能够将其物理网络映射到其虚拟网络中,从而无需进行运营大修即可将其容器集成到其环境中。NetOps将802.1Q trunk连接到Docker主机。该虚拟链接将是网络创建时传入的-o parent=。对于未标记(非VLAN)链接,只需-o parent=eth0,或者对于带有VLAN ID的802.1Q trunk,每个网络都将映射到网络中相应的VLAN/子网。

例如,NetOps提供VLAN ID和与通过以太网链路传递到Docker主机服务器的VLAN关联的子网。在配置Docker网络时,这些值将被插入到docker network create命令中。这些是每次Docker引擎启动时都应用的持久配置,从而避免了管理通常复杂的配置文件的需要。网络接口也可以通过预先创建来手动管理,Docker网络将永远不会修改它们,并将其用作父接口。NetOps到Docker网络命令的示例映射如下:

  • VLAN: 10,子网: 172.16.80.0/24,网关: 172.16.80.1
    • --subnet=172.16.80.0/24 --gateway=172.16.80.1 -o parent=eth0.10
  • VLAN: 20,IP子网: 172.16.50.0/22,网关: 172.16.50.1
    • --subnet=172.16.50.0/22 --gateway=172.16.50.1 -o parent=eth0.20
  • VLAN: 30,子网: 10.1.100.0/16,网关: 10.1.100.1
    • --subnet=10.1.100.0/16 --gateway=10.1.100.1 -o parent=eth0.30

IPvlan L3 模式示例

IPvlan需要将路由分发到每个端点。驱动程序仅构建IPvlan L3模式端口并将容器连接到接口。在该单主机范围驱动程序的初始实现中,集群中的路由分发超出了范围。在L3模式下,Docker主机非常类似于在容器中启动新网络的路由器。它们位于上游网络在没有路由分发的情况下不知道的网络上。对于那些好奇IPvlan L3如何适应容器网络的人,请参阅以下示例。

Docker IPvlan L2 mode

IPvlan L3模式丢弃所有广播和多播流量。仅此一点就使IPvlan L3模式成为寻求大规模和可预测网络集成的理想选择。它是可预测的,反过来将导致更高的正常运行时间,因为不涉及桥接。桥接循环导致了难以查明的重大中断,这取决于故障域的大小。这是由于在广播域(VLAN)中泛洪的BPDU(桥接端口数据单元)的级联性质导致的,用于查找和阻止拓扑循环。消除桥接域,或者至少将它们隔离到一对ToR(机架顶部交换机),将减少难以排除故障的桥接不稳定性。IPvlan L2模式非常适合仅连接到一对ToR的隔离VLAN,该对ToR可以提供无环路非阻塞结构。下一步是通过IPvlan L3模式在边缘进行路由,这将故障域减少到仅本地主机。

  • L3模式需要位于与默认命名空间不同的子网上,因为它需要在默认命名空间中指向IPvlan父接口的netlink路由。
  • 本示例中使用的父接口是eth0,它位于子网192.168.1.0/24上。请注意,docker networketh0不在同一子网上。
  • 与IPvlan L2模式不同,只要不同的子网/网络共享相同的父接口-o parent=,它们就可以互相ping通。
$$ ip a show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:39:45:2e brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.250/24 brd 192.168.1.255 scope global eth0
  • 传统的网关对L3模式IPvlan接口没有太大意义,因为不允许广播流量。因此,容器默认网关指向容器的eth0设备。请参见下面的容器内部ip routeip -6 route的CLI输出,了解详细信息。

必须显式指定模式-o ipvlan_mode=l3,因为默认的IPvlan模式是l2

以下示例未指定父接口。网络驱动程序将为用户创建一个虚拟类型链接,而不是拒绝网络创建并隔离容器只能互相通信。

# Create the IPvlan L3 network
$ docker network create -d ipvlan \
    --subnet=192.168.214.0/24 \
    --subnet=10.1.214.0/24 \
    -o ipvlan_mode=l3 ipnet210

# Test 192.168.214.0/24 connectivity
$ docker run --net=ipnet210 --ip=192.168.214.10 -itd alpine /bin/sh
$ docker run --net=ipnet210 --ip=10.1.214.10 -itd alpine /bin/sh

# Test L3 connectivity from 10.1.214.0/24 to 192.168.214.0/24
$ docker run --net=ipnet210 --ip=192.168.214.9 -it --rm alpine ping -c 2 10.1.214.10

# Test L3 connectivity from 192.168.214.0/24 to 10.1.214.0/24
$ docker run --net=ipnet210 --ip=10.1.214.9 -it --rm alpine ping -c 2 192.168.214.10

注意

请注意,docker network create中没有--gateway=选项。如果指定了l3模式,则会忽略该字段。请查看容器内部的容器路由表。

# Inside an L3 mode container
$$ ip route
 default dev eth0
  192.168.214.0/24 dev eth0  src 192.168.214.10

为了从远程Docker主机ping通容器,或者容器能够ping通远程主机,远程主机或两者之间的物理网络需要有一个指向容器的Docker主机eth接口的主机IP地址的路由。

双栈 IPv4 IPv6 IPvlan L2 模式

  • Libnetwork不仅可以让您完全控制IPv4寻址,还可以完全控制IPv6寻址以及这两个地址族之间的功能对等性。

  • 下一个示例将仅从IPv6开始。在相同的VLAN 139上启动两个容器并互相ping通。由于未指定IPv4子网,因此默认IPAM将配置默认IPv4子网。除非上游网络在VLAN 139上显式路由它,否则该子网是隔离的。

# Create a v6 network
$ docker network create -d ipvlan \
    --ipv6 --subnet=2001:db8:abc2::/64 --gateway=2001:db8:abc2::22 \
    -o parent=eth0.139 v6ipvlan139

# Start a container on the network
$ docker run --net=v6ipvlan139 -it --rm alpine /bin/sh

查看容器eth0接口和v6路由表。

# Inside the IPv6 container
$$ ip a show eth0
75: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc2::1/64 scope link nodad
       valid_lft forever preferred_lft forever

$$ ip -6 route
2001:db8:abc4::/64 dev eth0  proto kernel  metric 256
2001:db8:abc2::/64 dev eth0  proto kernel  metric 256
default via 2001:db8:abc2::22 dev eth0  metric 1024

启动第二个容器并ping第一个容器的v6地址。

# Test L2 connectivity over IPv6
$ docker run --net=v6ipvlan139 -it --rm alpine /bin/sh

# Inside the second IPv6 container
$$ ip a show eth0
75: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link tentative dadfailed
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc2::2/64 scope link nodad
       valid_lft forever preferred_lft forever

$$ ping6 2001:db8:abc2::1
PING 2001:db8:abc2::1 (2001:db8:abc2::1): 56 data bytes
64 bytes from 2001:db8:abc2::1%eth0: icmp_seq=0 ttl=64 time=0.044 ms
64 bytes from 2001:db8:abc2::1%eth0: icmp_seq=1 ttl=64 time=0.058 ms

2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.044/0.051/0.058/0.000 ms

下一个示例将设置一个双栈IPv4/IPv6网络,VLAN ID示例为140

接下来,创建一个具有两个IPv4子网和一个IPv6子网的网络,所有这些子网都有明确的网关。

$ docker network create -d ipvlan \
    --subnet=192.168.140.0/24 --subnet=192.168.142.0/24 \
    --gateway=192.168.140.1 --gateway=192.168.142.1 \
    --subnet=2001:db8:abc9::/64 --gateway=2001:db8:abc9::22 \
    -o parent=eth0.140 \
    -o ipvlan_mode=l2 ipvlan140

启动一个容器并查看eth0以及v4和v6路由表。

$ docker run --net=ipvlan140 --ip6=2001:db8:abc2::51 -it --rm alpine /bin/sh

$ ip a show eth0
78: eth0@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
    inet 192.168.140.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc9::1/64 scope link nodad
       valid_lft forever preferred_lft forever

$$ ip route
default via 192.168.140.1 dev eth0
192.168.140.0/24 dev eth0  proto kernel  scope link  src 192.168.140.2

$$ ip -6 route
2001:db8:abc4::/64 dev eth0  proto kernel  metric 256
2001:db8:abc9::/64 dev eth0  proto kernel  metric 256
default via 2001:db8:abc9::22 dev eth0  metric 1024

启动第二个容器并指定--ip4地址,然后使用IPv4数据包ping第一个主机。

$ docker run --net=ipvlan140 --ip=192.168.140.10 -it --rm alpine /bin/sh

注意

在IPvlan L2模式下,同一父接口上的不同子网无法互相ping通。这需要一个路由器使用辅助子网代理ARP请求。但是,IPvlan L3将路由不同子网之间的单播流量,只要它们共享相同的-o parent父链接。

双栈 IPv4 IPv6 IPvlan L3 模式

示例:IPvlan L3模式双栈IPv4/IPv6,多子网,带802.1Q VLAN标记:118

与所有示例一样,不必使用带标记的VLAN接口。子接口可以用eth0eth1bond0或主机上的任何其他有效接口(环回接口lo除外)交换。

您将看到的区别是,L3模式不会创建具有下一跳的默认路由,而是仅设置指向dev eth的默认路由,因为根据设计,Linux过滤了所有ARP/广播/多播。由于父接口基本上充当路由器,因此父接口IP和子网需要与容器网络不同。这与桥接和L2模式相反,桥接和L2模式需要位于同一子网(广播域)上才能转发广播和多播数据包。

# Create an IPv6+IPv4 Dual Stack IPvlan L3 network
# Gateways for both v4 and v6 are set to a dev e.g. 'default dev eth0'
$ docker network create -d ipvlan \
    --subnet=192.168.110.0/24 \
    --subnet=192.168.112.0/24 \
    --subnet=2001:db8:abc6::/64 \
    -o parent=eth0 \
    -o ipvlan_mode=l3 ipnet110


# Start a few of containers on the network (ipnet110)
# in separate terminals and check connectivity
$ docker run --net=ipnet110 -it --rm alpine /bin/sh
# Start a second container specifying the v6 address
$ docker run --net=ipnet110 --ip6=2001:db8:abc6::10 -it --rm alpine /bin/sh
# Start a third specifying the IPv4 address
$ docker run --net=ipnet110 --ip=192.168.112.30 -it --rm alpine /bin/sh
# Start a 4th specifying both the IPv4 and IPv6 addresses
$ docker run --net=ipnet110 --ip6=2001:db8:abc6::50 --ip=192.168.112.50 -it --rm alpine /bin/sh

接口和路由表输出如下所示。

$$ ip a show eth0
63: eth0@if59: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
    inet 192.168.112.2/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc6::10/64 scope link nodad
       valid_lft forever preferred_lft forever

# Note the default route is the eth device because ARPs are filtered.
$$ ip route
  default dev eth0  scope link
  192.168.112.0/24 dev eth0  proto kernel  scope link  src 192.168.112.2

$$ ip -6 route
2001:db8:abc4::/64 dev eth0  proto kernel  metric 256
2001:db8:abc6::/64 dev eth0  proto kernel  metric 256
default dev eth0  metric 1024

注意

指定--ip6=地址时可能存在一个bug,当您删除具有指定v6地址的容器,然后使用相同的v6地址启动一个新容器时,它会抛出以下错误,就像地址没有正确释放到v6池一样。它将无法卸载容器,并将保持失效状态。

docker: Error response from daemon: Address already in use.

VLAN ID 40

如果用户不希望驱动程序创建VLAN子接口,则需要在运行docker network create之前创建它。如果您的子接口名称不是interface.vlan_id,则在-o parent=选项中仍然会被接受,只要该接口存在并且处于启用状态。

手动创建的链接可以命名为任何名称,只要在创建网络时存在即可。手动创建的链接在使用docker network rm删除网络时,无论名称如何,都不会被删除。

# create a new sub-interface tied to dot1q vlan 40
$ ip link add link eth0 name eth0.40 type vlan id 40

# enable the new sub-interface
$ ip link set eth0.40 up

# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged
$ docker network create -d ipvlan \
    --subnet=192.168.40.0/24 \
    --gateway=192.168.40.1 \
    -o parent=eth0.40 ipvlan40

# in two separate terminals, start a Docker container and the containers can now ping one another.
$ docker run --net=ipvlan40 -it --name ivlan_test5 --rm alpine /bin/sh
$ docker run --net=ipvlan40 -it --name ivlan_test6 --rm alpine /bin/sh

示例:手动创建的VLAN子接口,可以使用任何名称。

# create a new sub interface tied to dot1q vlan 40
$ ip link add link eth0 name foo type vlan id 40

# enable the new sub-interface
$ ip link set foo up

# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged
$ docker network create -d ipvlan \
    --subnet=192.168.40.0/24 --gateway=192.168.40.1 \
    -o parent=foo ipvlan40

# in two separate terminals, start a Docker container and the containers can now ping one another.
$ docker run --net=ipvlan40 -it --name ivlan_test5 --rm alpine /bin/sh
$ docker run --net=ipvlan40 -it --name ivlan_test6 --rm alpine /bin/sh

手动创建的链接可以使用以下命令清除:

$ ip link del foo

与所有Libnetwork驱动程序一样,它们可以混合使用,甚至可以并行运行第三方生态系统驱动程序,以最大限度地提高Docker用户的灵活性。