IPvlan 网络驱动程序
IPvlan 驱动程序让用户能够完全控制 IPv4 和 IPv6 寻址。VLAN 驱动程序在此基础上,允许运维人员完全控制第 2 层 VLAN 标记,甚至对于对底层网络集成感兴趣的用户,还可以控制 IPvlan L3 路由。对于抽象物理约束的叠加部署,请参阅多主机 Overlay 驱动程序。
IPvlan 是对久经考验的网络虚拟化技术的一种新变体。Linux 实现非常轻量级,因为它们不使用传统的 Linux 网桥进行隔离,而是关联到 Linux 以太网接口或子接口,以强制实现网络间的分离以及与物理网络的连接。
IPvlan 提供了许多独特的功能,并且在各种模式下仍有进一步创新的空间。这些方法有两个高级优势:绕过 Linux 网桥带来的积极性能影响,以及更少的活动部件带来的简洁性。移除传统上位于 Docker 主机网卡和容器接口之间的网桥,留下了一个由容器接口直接连接到 Docker 主机接口的简单设置。这使得外部服务易于访问,因为在这些场景下无需端口映射。
选项
下表描述了在使用 ipvlan
驱动程序创建网络时,可以传递给 --opt
的驱动程序特定选项。
选项 | 默认值 | 描述 |
---|---|---|
ipvlan_mode | l2 | 设置 IPvlan 操作模式。可以是以下之一:l2 、l3 、l3s |
ipvlan_flag | bridge | 设置 IPvlan 模式标志。可以是以下之一:bridge 、private 、vepa |
parent | 指定要使用的父接口。 |
示例
先决条件
- 此页上的示例都是单主机示例。
- 所有示例都可以在运行 Docker 的单个主机上执行。任何使用诸如
eth0.10
之类的子接口的示例,都可以替换为eth0
或 Docker 主机上的任何其他有效父接口。带.
的子接口是动态创建的。在docker network create
命令中也可以完全省略-o parent
接口,驱动程序将创建一个dummy
接口,从而启用本地主机连接以执行示例。 - 内核要求
- IPvlan Linux 内核 v4.2+(早期内核支持存在但有 bug)。要检查当前内核版本,请使用
uname -r
- IPvlan Linux 内核 v4.2+(早期内核支持存在但有 bug)。要检查当前内核版本,请使用
IPvlan L2 模式示例用法
IPvlan L2
模式拓扑的一个示例如下图所示。驱动程序通过 -d driver_name
选项指定。在此例中为 -d ipvlan
。


下例中的父接口 -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 模式。


以下命令将创建与之前创建的网络 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 模式示例用法
在网关和 L2 路径隔离方面,IPvlan L2 模式 Trunking 与 Macvlan 相同。有一些细微之处对 ToR 交换机中的 CAM 表压力、每个端口一个 MAC 以及主机父网卡上的 MAC 耗尽等方面可能有利。802.1Q Trunk 场景看起来相同。这两种模式都遵循标记标准,并与物理网络无缝集成,以实现底层集成和硬件供应商插件集成。
同一 VLAN 上的主机通常位于同一子网中,并且几乎总是根据其安全策略分组在一起。在大多数场景中,多层应用程序被分层到不同的子网中,因为每个进程的安全配置文件需要某种形式的隔离。例如,将信用卡处理托管在与前端 Web 服务器相同的虚拟网络上将是一个法规遵从性问题,同时也绕过了长期以来最佳实践的深度防御分层架构。VLAN 或使用 Overlay 驱动程序时的等价 VNI(虚拟网络标识符),是隔离租户流量的第一步。


用 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
表示 eth0
的子接口,该子接口标记了 VLAN ID 10
。等价的 ip link
命令是 ip link add link eth0 name eth0.10 type vlan id 10
。
该示例创建了 VLAN 标记的网络,然后启动两个容器来测试容器之间的连通性。不同的 VLAN 之间无法互相 ping 通,除非有路由器在两个网络之间进行路由。根据 IPvlan 的设计,默认命名空间不可达,以隔离容器命名空间与底层主机。
VLAN ID 20
在第一个由 Docker 主机标记和隔离的网络中,eth0.20
是带有 VLAN ID 20
的父接口,通过 -o parent=eth0.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
是带有 VLAN ID 30
的父接口,通过 -o parent=eth0.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
一个关键点是,运维人员能够将他们的物理网络映射到他们的虚拟网络中,以便将容器集成到他们的环境中,而无需进行操作上的大改动。网络运维人员将 802.1Q Trunk 端口接入 Docker 主机。这个虚拟链接将是网络创建时传入的 -o parent=
。对于未标记(非 VLAN)的链接,就像 -o parent=eth0
一样简单,或者对于带有 VLAN ID 的 802.1Q Trunk 端口,每个网络都映射到网络中相应的 VLAN/子网。
例如,网络运维人员提供通过以太网链接到 Docker 主机服务器的 VLAN ID 和关联的子网。这些值在配置 Docker 网络时被填入 docker network create
命令。这些是持久性配置,每次 Docker Engine 启动时都会应用,从而无需管理通常很复杂的配置文件。网络接口也可以通过预先创建并手动管理,Docker 网络将不会修改它们,并将其用作父接口。以下是网络运维人员映射到 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 如何融入容器网络的人,请参阅以下示例。


IPvlan L3 模式会丢弃所有广播和组播流量。仅凭这一点,IPvlan L3 模式就成为那些寻求大规模和可预测网络集成者的首选方案。它是可预测的,因此会带来更高的正常运行时间,因为它不涉及桥接。桥接环路是造成一些备受关注的服务中断的原因,而且根据故障域的大小,这些中断可能很难查明。这是由于 BPDU(桥接端口数据单元)的级联特性,它们在整个广播域(VLAN)中泛洪以查找并阻止拓扑环路。消除桥接域,或者至少将它们隔离到一对 ToR(架顶式交换机),将减少难以排除故障的桥接不稳定问题。IPvlan L2 模式非常适合仅中继到一对 ToR 的隔离 VLAN,这对 ToR 可以提供无环路、无阻塞的 fabric。更进一步的是通过 IPvlan L3 模式在边缘进行路由,这将故障域缩小到仅限于本地主机。
- L3 模式需要与默认命名空间位于不同的子网,因为它需要在默认命名空间中有一个指向 IPvlan 父接口的 netlink 路由。
- 此示例中使用的父接口是
eth0
,它位于子网192.168.1.0/24
上。注意docker network
不与eth0
位于同一子网。 - 与 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
设备。有关详细信息,请参阅下面在 L3 容器内运行ip route
或ip -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
注意
注意在网络创建时没有
--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 子网。除非上游网络在 VLAN139
上明确路由该子网,否则它是隔离的。
# 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 通。这需要路由器通过二次子网来 proxy-arp 请求。然而,只要 IPvlanL3
模式的容器共享相同的-o parent
父链接,它就能在不同的子网之间路由单播流量。
双栈 IPv4 IPv6 IPvlan L3 模式
示例:IPvlan L3 模式 双栈 IPv4/IPv6,多子网带 802.1Q VLAN 标签:118
如所有示例所示,不必使用带标签的 VLAN 接口。子接口可以替换为 eth0
、eth1
、bond0
或主机上除 lo
回环接口外的任何其他有效接口。
您将看到的主要区别在于,L3 模式不会创建带有下一跳的默认路由,而是设置一个指向 dev eth
的默认路由,因为根据设计,ARP/广播/组播都已被 Linux 过滤。由于父接口实际上充当了路由器,因此父接口的 IP 地址和子网需要与容器网络不同。这与 bridge 和 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.
手动创建 802.1Q 链接
VLAN ID 40
如果用户不希望驱动程序创建 VLAN 子接口,则在运行 docker network create
之前需要确保该子接口已存在。如果您的子接口命名不是 interface.vlan_id
格式,只要接口存在且处于 UP 状态,-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 用户提供最大的灵活性。