Docker网络模型(七)使用 IPvlan 网络

news2024/12/1 0:46:49

使用 IPvlan 网络

IPvlan 驱动为用户提供了全面控制 IPv4 和 IPv6 寻址的能力。 IPvlan 让操作者能完全操控二层(数据链路层)网络的 vlan 标签,甚至也提供了三层(网络传输层)路由控制给感兴趣的用户。对于抽象出物理限制的 overlay 部署,请看  多主机 overlay 驱动。

IPvlan 是久经考验的网络虚拟化技术的一个新变化。Linux 的实现是非常轻量级的,因为它们不是使用传统的 Linux 网桥进行隔离,而是与一个 Linux 接口或子接口相关联,以执行网络之间的分离和与物理网络的连接。

IPvlan 提供了许多独特的功能,并为各种模式的进一步创新提供了大量空间。这些方法的两个厉害之处在于,绕过 Linux 网桥后带来的对性能的正向影响、以及减少移动部件后带来的简易性。移除传统上位于 Docker 主机接口和容器接口之间的桥,留下一个由容器接口组成的简单设置,直接连接到 Docker 主机接口。这种结果很容易被外部服务所访问,因为在这些情况下不需要端口映射。

先决条件

  • 本页中的例子都针对单台主机。
  • 所有的例子都可以在运行 Docker 的单一主机上执行。任何使用子接口(如 eth0.10 )的例子都可以用 eth0 或 Docker 主机上任何其他有效的父接口代替。带有 . (下点号)的子接口是即时创建的。 -o parent 指定父接口的选项也可以不在 docker network create 命令里出现,此时驱动会创建一个 假的(dummy)  接口,使本地主机的连接能够执行文章的例子。
  • 内核需求:
    • 使用 uname -r 来检查当前的内核版本。
    • IPvlan Linux 内核 v4.2+ (早期的内核也能支持不过会有缺陷)

IPvlan 二层模式(L2 mode)用例

下图展示了一个 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= 如果没指定默认就是 L2 模式)
$ 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

# 在 db_net 网络上启动一个容器
$ docker run --net=db_net -it --rm alpine /bin/sh

# 注意:容器里面 ping 不通底层宿主机的网卡
# 它们被 Linux 有意地隔离了以获得额外的隔离性

IPvlan 的默认模式是 二层(l2). 如果 -o ipvlan_mode= 留空,默认的模式就会被采用。类似的,如果 --gateway 留空,网络上第一个可用的地址将被设置为网关。举例,如果网络创建时提供的子网是 --subnet=192.168.1.0/24 那么容器收到的网关就会是 192.168.1.1。

为了帮助理解这种模式是如何跟其他主机交互的,请参考下图。图里展示了两台主机同样采用的2层片段(layer 2 segment)以及 IPvlan L2 模式。

下面的指令会创建一个跟之前的 db_net 一样的网络,使用的是驱动的默认配置r --gateway=192.168.1.1 和 -o ipvlan_mode=l2。

# IPvlan  (-o ipvlan_mode= 如果没指定默认就是 L2 模式)
$ docker network create -d ipvlan \
    --subnet=192.168.1.0/24 \
    -o parent=eth0 db_net_ipv

# 用后台模式启动一个指定名字的容器
$ docker run --net=db_net_ipv --name=ipv1 -itd alpine /bin/sh

# 启动第二个容器,然后用容器名去ping第一个容器
# 来看一下docker自带的名字解析功能
$ docker run --net=db_net_ipv --name=ipv2 -it --rm alpine /bin/sh
$ ping -c 4 ipv1

# 注意:容器里面 ping 不通底层宿主机的网卡
# 它们被 Linux 有意地隔离了以获得额外的隔离性

驱动程序还支持 --internal 标志,它将完全隔离网络上的容器与该网络外部的任何通信。由于网络隔离与网络的父接口紧密相关,在 docker 网络创建中不使用 -o parent= 选项的结果与 --internal 选项完全相同。如果没有指定父接口或者使用了 --internal 标志,就会为用户创建一个netlink 类型的 假的(dummy) 父接口,并将其作为父接口使用,有效地隔离了网络。

下面两个 docker network create 例子会创建同样的网络,你可以附加容器上去:

# 留空 '-o parent=' 会创建一个隔离的网络
$ docker network create -d ipvlan \
    --subnet=192.168.10.0/24 isolated1

# 指明 '--internal' 标志同样:
$ docker network create -d ipvlan \
    --subnet=192.168.11.0/24 --internal isolated2

# 甚至 '--subnet=' 也可以留空
# 172.18.0.0/16的IPAM子网将被分配
$ 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

# 连接任意的容器,使用 `docker exec` 来开始一个 shell
$ docker exec -it cid1 /bin/sh
$ docker exec -it cid2 /bin/sh
$ docker exec -it cid3 /bin/sh

IPvlan 802.1q 中继(trunk)二层模式(L2 mode)用例

从结构上看,IPvlan 二层模式(L2 mode)中继与 Macvlan 在网关和 L2 路径隔离方面是一样的。有一些细微的差别,IPvlan 对 ToR 交换机的 CAM 表(MAC 交换表)压力、每个端口一个 MAC 和主机的父接口上的 MAC 耗尽都是有利的。在 802.1q 中继方案上,两者看起来是一样的。两种模式都执行了Tag标准,并与物理网络无缝集成,以实现底层集成和硬件供应商插件集成。

同一VLAN上的主机通常在同一个子网中,并且几乎总是根据其安全策略被分组在一起。在大多数情况下,一个多层应用程序被分层到不同的子网中,因为每个进程的安全配置文件需要某种形式的隔离。例如,如果你的信用卡处理与前端网络服务器被托管在同一个虚拟网络上,这将导致监管合规有关的问题,同时也绕过了长期以来分层防御深度架构的最佳实践。在使用 Overlay 驱动时,VLANs或等价的 VNI(虚拟网络标识符)是隔离租户流量(tenant traffic)的第一步。

带有 VLAN 标签的 Linux 子接口可以是已经存在的,也可以是在你调用 docker network create时创建的。docker network rm将删除该子接口。像 eth0 这样的父接口不会被删除,只有 netlink 父索引大于0的子接口会被删除。

对于驱动程序来说,添加/删除 VLAN 子接口的格式需要是 interface_name.vlan_tag。其他不是 VLAN 的子接口的命名可以用作指定的父接口,但是当调用 docker network rm 时,该链接不会被自动删除。(对这段话的理解参考文末的【手动创建 802.1q 链接】)

选择使用现有的父 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 是用 -o parent=eth0.20指定的 VLAN id 20 标记的父接口。可以使用其他命名格式,但需要使用 ip link 或Linux配置文件手动添加和删除链接。只要 -o parent 存在,任何东西都可以使用,只要它符合Linux netlink的要求。

# 现在,你可以正常将网络和主机添加到被标记的主(子)接口上。
$ docker network create -d ipvlan \
    --subnet=192.168.20.0/24 \
    --gateway=192.168.20.1 \
    -o parent=eth0.20 ipvlan20

# 在两个不同的终端中,各自启动一个Docker容器,现在这两个容器可以互相ping了。
$ 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= 默认为2层模式(L2 mode) ipvlan_mode=l2。也可以明确地设置它,结果与下面的例子所示相同。

# 现在,你可以正常将网络和主机添加到被标记的主(子)接口上。
$ 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

# 在两个不同的终端中,各自启动一个Docker容器,现在这两个容器可以互相ping了。
$ 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 二层模式在同一子网启动两个容器,并互相ping。为了让 192.168.114.0/24 到达 192.168.116.0/24,它需要一个二层模式的外部路由器。三层模式(L3 mode)则可以在用 -o parent=指定了同一个父接口的子网间进行路由。

网络路由器上的次选地址是很常见的,因为一个地址空间有可能有用完的情况,此时可以在三层的 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中继线,每个网络被映射到网络中相应的 VLAN/Subnet。

一个例子是,网络运维(NetOps)提供了用于 VLAN 在以太网链接上传递给Docker宿主机的 VLAN ID 和相关的子网。在配置 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, 子网: 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 mode)例子

IPvlan 将需要将路由分配到每个端点(endpoint)。驱动程序只建立了IPvlan 三层模式(L3 mode)的端口,并将容器连接到接口上。而整个集群的路由的分配,超出了这个单一主机范围的驱动程序的初始实现。在三层模式下,Docker 宿主机非常类似于一个在容器中启动新的网络的路由器。它们所处的网络,如果没有路由分配,上游网络是不会知道的。对于那些好奇三层 IPvlan 将如何融入容器网络的人,请看下面的例子。

IPvlan L3模式会丢弃所有广播和多播流量。仅仅是这个原因就使IPvlan 三层模式成为那些寻求大规模和可预测的网络整合的首选。它是可预测的,并且由于没有桥接,因此能够更长时间的正常运行。桥接环路是高调故障的罪魁祸首,而根据故障域的大小,这些故障往往很难定位。这是由于BPDU(桥接端口数据单元,生成树协议)的级联性质,它在整个广播域(VLAN)中泛滥,以寻找和阻止拓扑环。消除桥接域,或者至少把它们隔离在一对 ToR(架顶交换机)上,将减少难以排除的桥接不稳定性。IPvlan 二层模式非常适合仅隔离在一对可提供无环非阻塞结构的ToRs中的VLAN。更进一步的选择,是通过IPvlan 三层模式在边缘进行路由,从而将故障域仅限于本地主机。

  • 三层模式需要在一个单独的子网中作为默认命名空间,因为它需要在默认命名空间中有一个指向IPvlan父接口的 netlink 路由。
  • 本例中使用的父接口是 eth0 ,它位于 192.168.1.0/24子网。注意 docker 网络 与 eth0 不在同一个子网。
  • 与IPvlan 二层模式不同,不同的子网/网络只要共享同一个父接口 -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
  • 传统的网关对三层模式的IPvlan接口没有什么意义,因为不允许有广播流量。正因为如此,容器的默认网关指向了容器的eth0设备。详情请看下面L3容器内部的 ip route 或 ip -6 route 的CLI输出。

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

下面的例子没有指定一个父接口。网络驱动程序将为用户创建一个虚假(dummy)类型的链接,而不是拒绝网络的创建,并将容器隔离开来,只能相互通信。

# 创建 IPvlan 三层网络
$ docker network create -d ipvlan \
    --subnet=192.168.214.0/24 \
    --subnet=10.1.214.0/24 \
    -o ipvlan_mode=l3 ipnet210

# 测试 192.168.214.0/24 连通
$ 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

# 测试从 10.1.214.0/24 到 192.168.214.0/24 的三层连通
$ docker run --net=ipnet210 --ip=192.168.214.9 -it --rm alpine ping -c 2 10.1.214.10

# 测试从 192.168.214.0/24 到 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 二层模式

  • Libnetwork 不仅可以让你完全控制IPv4寻址,还可以让您完全控制IPv6寻址,并在这两个协议族之间提供对等的功能。

  • 接下来的例子将只从IPv6开始。在同一个VLAN 139 上启动两个容器,并互相ping。由于没有指定IPv4子网,默认的 IPAM 将提供一个默认的IPv4子网。该子网是隔离的,除非上游网络在VLAN  139上明确地对其进行路由。

# 创建一个 v6 网络
$ docker network create -d ipvlan \
    --ipv6 --subnet=2001:db8:abc2::/64 --gateway=2001:db8:abc2::22 \
    -o parent=eth0.139 v6ipvlan139

# 在网络中启动一个容器
$ docker run --net=v6ipvlan139 -it --rm alpine /bin/sh

查看容器的 eth0 网卡跟 v6 路由表:

# IPv6 容器内部
$$ 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 地址。

# 测试 IPv6 上的2层连通性
$ docker run --net=v6ipvlan139 -it --rm alpine /bin/sh

# 第二个 IPv6 容器的内部
$$ 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

下一个示例将设置具有示例VLAN ID 140的双栈IPv4/IPv6网络。

接着,创建一个同时有 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 二层模式下,位于同一父接口上的不同子网无法相互ping通。这需要路由器使用辅助子网代理 arp 请求。然而,IPvlan 三层模式将正常路由相同的 -o parent 父链接下的不同子网之间的单播流量。

双栈IPv4 IPv6 IPvlan 三层模式

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

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

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

# 创建一个 IPv6+IPv4 双栈 IPvlan 三层 network
# v4 跟 v6 的网关都被指定为到类似 '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


# 用不同的终端在网络(ipnet110)启动一些容器,并测试连通性
$ docker run --net=ipnet110 -it --rm alpine /bin/sh
# 启动第二个指定了 v6 地址的容器
$ docker run --net=ipnet110 --ip6=2001:db8:abc6::10 -it --rm alpine /bin/sh
# 启动第三个制定了 v4 地址的容器
$ docker run --net=ipnet110 --ip=192.168.112.30 -it --rm alpine /bin/sh
# 启动第四个同事指定了 v4 跟 v6 地址的容器
$ 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

# 注意默认的路由指向了 eth 设备,因为 arp 包被(eth)过滤了
$$ 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 删除,手动创建的链接都不会被删除。

# 创建一个绑定到 dot1q VLAN 40的新子接口: 
$ ip link add link eth0 name eth0.40 type vlan id 40

# 启用新的子接口
$ ip link set eth0.40 up

# 现在,可以像平常一样通过连接到标记的主(子)接口添加网络和主机。
$ docker network create -d ipvlan \
    --subnet=192.168.40.0/24 \
    --gateway=192.168.40.1 \
    -o parent=eth0.40 ipvlan40

# 在两个终端里,分别启动能互相ping通的容器
$ 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 子接口:

# 创建一个绑定到 dot1q VLAN 40的新子接口:
$ ip link add link eth0 name foo type vlan id 40

# 启动新的子接口
$ ip link set foo up

# 现在,可以像平常一样通过连接到标记的主(子)接口添加网络和主机。
$ docker network create -d ipvlan \
    --subnet=192.168.40.0/24 --gateway=192.168.40.1 \
    -o parent=foo ipvlan40


# 在两个终端里,分别启动能互相ping通的容器
$ 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用户的灵活性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/625684.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringSecurity】CSRF、环境配置、授权、认证功能、记住我功能实现

SpringSecurity 文章目录 SpringSecurityCSRF跨站请求伪造攻击开发环境搭建认证直接认证使用数据库认证自定义登录界面 授权基于角色的授权基于权限的授权使用注解判断权限 记住我SecurityContext SpringSecurity是一个基于Spring开发的非常强大的权限验证框架&#xff0c;其核…

Java快速安装以及入门指南

安装 Java 环境教程 Java 是一种广泛应用于软件开发、Web 应用程序和移动应用程序等领域的编程语言。如果您要使用 Java 进行开发或运行需要 Java 程序&#xff0c;您需要先在计算机上安装 Java 环境。 本教程将向您介绍如何在 Windows 操作系统上安装和验证 Java 环境。还将…

第2章 可行性研究

文章目录 第2章 可行性研究2.1 可行性研究的任务2.2 可行性研究过程2.3 系统流程图2.3.1符号2.3.3 分层 2.4 数据流图2.4.1 符号1. 数据源点或终点2. 数据加工&#xff08;变换数据的处理&#xff09;3. 数据存储4.数据流数据流与数据加工之间的关系 2.4.2绘制数据流图的例子顶…

chatgpt赋能python:Python3.6.5到Python3.7.5:升级指南

Python 3.6.5到Python 3.7.5&#xff1a;升级指南 Python是一种广泛使用的编程语言&#xff0c;拥有强大的库和框架&#xff0c;能够开发各种类型的应用程序。在Python的发行版中&#xff0c;版本更新是常见的过程&#xff0c;以提供更好的性能和新的功能。 本文将介绍如何将…

手记系列之六 ----- 分享个人使用kafka经验

前言 本篇文章主要介绍的关于本人从刚工作到现在使用kafka的经验&#xff0c;内容非常多&#xff0c;包含了kafka的常用命令&#xff0c;在生产环境中遇到的一些场景处理&#xff0c;kafka的一些web工具推荐等等。由于kafka这块的记录以及经验是从我刚开始使用kafka&#xff0…

chatgpt赋能python:Python怎么一行一行读文本?

Python怎么一行一行读文本&#xff1f; 在Python中&#xff0c;要一行一行地读取文本文件&#xff0c;我们可以使用Python内置函数readline()。它每次读取一行文本&#xff0c;并且会自动把文本的换行符\n去掉。下面我们来详细了解如何使用readline()函数读取文本文件。 读取…

4.卡尔曼滤波原理及实战

欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 文章目录 0.关于卡尔曼1.卡尔曼滤波算法2.卡尔曼滤波算法的应用一个简单例子一个复杂的例子参考 0.关于卡尔曼 卡尔曼&#xff0c;匈牙利数学家&#xff0c;1930年出生于匈牙利首都布达佩斯…

chatgpt赋能python:Python数据分析:Vlookup函数在Python中的实现

Python数据分析&#xff1a;Vlookup函数在Python中的实现 简介 Vlookup是一种常见的数据分析函数&#xff0c;用于在两个数据表/数据集中查找并关联相应的数据。这个函数是在Excel中非常常见的&#xff0c;但是当我们进行大型数据分析时&#xff0c;我们可以使用Python来实现…

2023.6.8小记——嵌入式系统初识、什么是ARM架构?

今天还挺充实的&#xff0c;早上在图书馆本来想学一下notion&#xff0c;结果看李沐老师的动手深度学习看到十点半&#xff0c;在电脑上配置了李沐老师的d2l和jupyter&#xff0c;等后续有时间的时候再继续学。 下午看了一下notion的使用方法&#xff0c;这玩意初学者用起来是…

chatgpt赋能python:Python如何一行输出五个星号

Python如何一行输出五个星号 Python是一种流行的编程语言&#xff0c;它被广泛用于各种领域&#xff0c;包括Web开发&#xff0c;数据科学和机器学习。在这篇文章中&#xff0c;我们将探讨如何使用Python在一行中输出五个星号。 输出五个星号的方法 Python提供了几种方法来在…

牛客网语法刷题(C语言) — 输出格式化

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C语言—语法篇》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c;…

从字符串中读写的方法:c语言中的sscanf、sprintf函数,c++中的I/O流strstream、stringstream

一、sscanf、sprintf函数 众所周知&#xff0c;c语言中我们常使用的标准输入输出流函数为scanf()、printf()&#xff0c;默认从键盘上输入数据、向屏幕输出数据。此外&#xff0c;c语言中还提供了另一组库函数sscanf()、sprintf()函数&#xff0c;它们的功能与前者相同&#x…

spark复习重点

什么是大数据 大数据是指数据量巨大、类型繁多、处理速度快的数据集合。它不仅包括传统的结构化数据&#xff0c;还包括非结构化数据、半结构化数据等多种形式的数据。大数据的处理需要使用特殊的技术和工具&#xff0c;如分布式存储、分布式计算、数据挖掘、机器学习等。 大…

软考A计划-系统架构师-官方考试指定教程-(7/15)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

uniapp主题切换功能的第二种实现方式(scss变量+require)

在上一篇 “uniapp主题切换功能的第一种实现方式&#xff08;scss变量vuex&#xff09;” 中介绍了第一种如何切换主题&#xff0c;但我们总结出一些不好的地方&#xff0c;例如扩展性不强&#xff0c;维护起来也困难等等&#xff0c;那么接下我再给大家介绍另外一种切换主题的…

聊聊那些奇葩的代码规范 —— 滥用静态导入

因为有些要求感觉实是太过奇葩&#xff0c;收集下来娱乐下大家。 代码规范要求 要求如果代码可以静态导入的话&#xff0c;就必须要静态导入。 所有的代码如果不静态导入&#xff0c;就直接 PR 拒绝合并。 举例&#xff1a;equalsAnyIgnoreCase("test","tes…

总结894

学习目标&#xff1a; 月目标&#xff1a;6月&#xff08;线性代数强化9讲遍&#xff0c;背诵15篇短文&#xff0c;考研核心词过三遍&#xff09; 周目标&#xff1a;线性代数强化3讲&#xff0c;英语背3篇文章并回诵&#xff0c;检测 每日必复习&#xff08;5分钟&#xff0…

chatgpt赋能python:Python怎么Import自己写的SEO文章

Python怎么Import自己写的SEO文章 如果你是一位Python开发人员&#xff0c;并且正在为SEO优化而努力编写文章&#xff0c;那么你可能会想知道如何将自己编写的SEO文章导入您的程序中以便更好的利用。 在这篇文章中&#xff0c;我们将介绍如何使用Python中的import语句将自己编…

UNIX网络编程卷一 学习笔记 第十九章 密钥管理套接字

随着IP安全体系结构&#xff08;IPsec&#xff09;的引入&#xff0c;密钥加密和认证密钥的管理越来越需要一套标准机制。RFC 2367介绍了一个通用密钥管理API&#xff0c;可用于IPsec和其他网络安全服务&#xff0c;该API创建了一个新协议族&#xff0c;即PF_KEY域&#xff0c;…

chatgpt赋能python:Python一行输入三个数:方便快捷,还能提高效率!

Python一行输入三个数&#xff1a;方便快捷&#xff0c;还能提高效率&#xff01; Python是一门非常流行的编程语言&#xff0c;不仅仅因为它简单易用&#xff0c;更因为它拥有丰富的生态系统和强大的库支持。但是&#xff0c;Python的输入方式却是许多人常常感到头疼的部分。…