IPv6与Docker(引擎) | IPv6 with Docker (Engine)
本节中的信息解释了 Docker 默认网桥的 IPv6。这是一个在安装 Docker 时自动创建名称为bridge
的bridge
网络。
由于 IPv4 地址耗尽, IETF 已经在 RFC 2460中标准化了 IPv4后继,Internet 协议版本6。这两种协议(IPv4和 IPv6)都驻留在 OSI模型的第3层。
IPv6 如何在 Docker 上运行
默认情况下,Docker 守护程序(daemon)仅为IPv4配置容器网络。您可以通过运行带有--ipv6
标志的Docker 守护程序(daemon)来启用 IPv4 / IPv6 双栈支持。Docker 将docker0
使用 IPv6 链接本地地址fe80::1
设置网桥。
默认情况下,创建的容器只会获得链路本地 IPv6 地址。要将全局可路由的 IPv6 地址分配给您的容器,您必须指定一个 IPv6 子网来从中选择地址。启动 Docker 守护进程(daemon)时,通过--fixed-cidr-v6
参数设置 IPv6子网:
您可以直接运行dockerd
这些标志,但建议您将其设置在daemon.json
配置文件中。以下示例daemon.json
启用 IPv6并将 IPv6子网设置为2001:db8:1::/64
。
{
"ipv6": true,
"fixed-cid4-v6": "2001:db8:1::/64"
}
Docker 容器的子网应该至少有一个大小/80
,以便 IPv6地址可以以容器的 MAC 地址结束,并且可以防止 Docker 层中的 NDP 邻居缓存失效问题。
默认情况下,--fixed-cidr-v6
参数使Docker为路由表添加一个新路由,方法是代表您运行以下三个命令。若要防止自动路由,请设置ip-forward
到false
在daemon.json
文件或启动Docker守护进程--ip-forward=false
旗子。然后,要获得Docker将自动为您创建的相同的路由表,请发出以下命令:
$ ip -6 route add 2001:db8:1::/64 dev docker0
$ sysctl net.ipv6.conf.default.forwarding=1
$ sysctl net.ipv6.conf.all.forwarding=1
子网的所有通信量2001:db8:1::/64
将通过docker0
接口。
注:IPv 6转发可能会干扰现有的IPv 6配置:如果使用路由器广告为主机接口获取IPv 6设置,请设置
accept_ra
到2
使用以下命令。否则,启用IPv 6的转发将导致拒绝路由器广告。 $sysctl net.ipv6.con.eth0.接受[医]Ra=2
二次
二次
每个新容器都将从定义的子网中获得一个IPv 6地址,并将添加一个默认路由。eth0
通过守护进程选项指定的地址在容器中。--default-gateway-v6
%28或default-gateway-v6
在daemon.json
%29(如有)。默认网关默认为fe80::1
...
此示例提供了一种检查运行容器中IPv 6网络设置的方法。
docker run -it alpine ash -c "ip -6 addr show dev eth0; ip -6 route show"
15: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500
inet6 2001:db8:1:0:0:242:ac11:3/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:3/64 scope link
valid_lft forever preferred_lft forever
2001:db8:1::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
default via fe80::1 dev eth0 metric 1024
在这个例子中,容器被分配一个带有子网的链接本地地址。/64
%28fe80::42:acff:fe11:3/64
%29和全球可路由IPv 6地址%282001:db8:1:0:0:242:ac11:3/64
29%。容器将创建与2001:db8:1::/64
通过链路本地网关连接fe80::1
上eth0
...
服务器或虚拟机通常会获得/64
IPv 6子网分配%28例如。2001:db8:23:42::/64
29%。在这种情况下,您可以进一步拆分它,并提供Docker a/80
使用单独的子网。/80
主机上其他应用程序的子网:
二次
二次
在此设置中,子网2001:db8:23:42::/64
从2001:db8:23:42:0:0:0:0
到2001:db8:23:42:ffff:ffff:ffff:ffff
附在eth0
,主人正在收听2001:db8:23:42::1
.子网2001:db8:23:42:1::/80
的地址范围为2001:db8:23:42:1:0:0:0
到2001:db8:23:42:1:ffff:ffff:ffff
附在docker0
并将用于集装箱。
使用NDP代理
如果您的Docker主机是IPv 6子网的唯一部分,但没有分配IPv 6子网,则可以使用NDP代理通过IPv 6将容器连接到Internet。如果具有IPv 6地址的主机2001:db8::c001
是子网的一部分。2001:db8::/64
IaaS提供商允许您配置IPv 6地址2001:db8::c000
到2001:db8::c00f
,您的网络配置可能如下所示:
$ ip -6 addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
inet6 2001:db8::c001/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::601:3fff:fea1:9c01/64 scope link
valid_lft forever preferred_lft forever
将可配置地址范围划分为两个子网2001:db8::c000/125
和2001:db8::c008/125
,使用以下方法daemon.json
设置。第一个子网将由主机上的非码头进程使用,第二个子网将由Docker使用。
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8::c008/125"
}
Docker子网位于由路由器管理并连接到eth0
所有由Docker分配地址的容器都将在路由器子网中找到,路由器可以直接与这些容器通信。
二次
二次
当路由器希望向第一个容器发送IPv 6数据包时,它将发送一个邻居请求问“谁有2001:db8::c009
“但是,子网上没有一个主机有地址;带有地址的容器隐藏在Docker主机后面。因此,Docker主机必须侦听邻居的请求,并响应它是具有地址的设备。此功能称为NDP代理并由主机上的内核处理。要启用NDP代理,请执行以下命令:
$ sysctl net.ipv6.conf.eth0.proxy_ndp=1
接下来,将容器的IPv 6地址添加到NDP代理表中:
$ ip -6 neigh add proxy 2001:db8::c009 dev eth0
从现在开始,内核在设备上回答邻居请求地址。eth0
.到此IPv 6地址的所有通信都通过Docker主机路由,Docker主机将根据其路由表通过docker0
装置:
$ ip -6 route show
2001:db8::c008/125 dev docker0 metric 1
2001:db8::/64 dev eth0 proto kernel metric 256
您必须执行ip -6 neigh add proxy ...
命令对您的Docker子网中的每个IPv 6地址执行命令。不幸的是,没有通过执行一个命令来添加整个子网的功能。另一种方法是使用ndp代理守护进程,如ndppd...
码头IPv 6集群
交换网络环境
使用可路由IPv 6地址可以实现不同主机上容器之间的通信。让我们看看一个简单的DockerIPv 6集群示例:
二次
二次
码头主机在2001:db8:0::/64
子网。主机1被配置为从2001:db8:1::/64
子网到它的容器。它配置了三条路由:
- 将所有交通线路送至
2001:db8:0::/64
通孔eth0
- 将所有交通线路送至
2001:db8:1::/64
通孔docker0
- 将所有交通线路送至
2001:db8:2::/64
通过带有IP的主机22001:db8::2
Host 1还充当OSI第3层上的路由器。当其中一个网络客户端试图联系主机1的路由表中指定的目标时,Host 1将相应地转发通信量。它充当它所知道的所有网络的路由器:2001:db8::/64
,,,2001:db8:1::/64
,和2001:db8:2::/64
...
在主机2上,我们的配置几乎相同。主机2的容器将从2001:db8:2::/64
.2号旅馆配置了三条路线:
- 将所有交通线路送至
2001:db8:0::/64
通孔eth0
- 将所有交通线路送至
2001:db8:2::/64
通孔docker0
- 将所有交通线路送至
2001:db8:1::/64
通过带有IP的主机12001:db8:0::1
主机1的不同之处在于网络2001:db8:2::/64
通过其docker0
接口而Host 2到达2001:db8:1::/64
通过Host 1的IPv 6地址2001:db8::1
...
这样,每个容器都能联系到其他的容器。集装箱Container1-*
共享同一个子网,并直接联系对方。之间的交通Container1-*
和Container2-*
将通过Host 1和Host 2路由,因为这些容器不共享相同的子网。
在切换环境中,每个主机都必须知道到每个子网的所有路由。在向群集添加或删除主机后,始终必须更新主机的路由表。
在虚线下面显示的图表中的每个配置都由Docker处理:docker0
网桥IP地址配置、主机上到Docker子网的路由、容器IP地址和容器上的路由。线上的配置由用户决定,可以适应个人环境。
路由网络环境
在路由网络环境中,用第三层路由器替换第二层交换机。现在,主机只需知道它们的默认网关%28、路由器%29和到它们自己的容器的路由%28由Docker%29管理。路由器保存有关Docker子网的所有路由信息。当您在此环境中添加或移除主机时,您只需更新路由器中的路由表--而不是在每个主机上。
二次
![](https://ask.qcloudimg.com/http-save/devdocs/2tkrcusjjy.png)
二次
在这种情况下,同一主机的容器可以直接通信。不同主机上的容器之间的通信将通过它们的主机和路由器进行路由。例如,从Container1-1
到Container2-1
将通过Host1
,,,Router
,和Host2
直到它到达Container2-1
...
若要使IPv 6地址在本例中保持较短,请使用/48
网络分配给每个主机。主机使用/64
它的子网用于它自己的服务,一个子网用于Docker。当添加第三个主机时,您将为子网添加一个路由。2001:db8:3::/48
在路由器中并在主机3上配置Docker--fixed-cidr-v6=2001:db8:3:1::/64
...
请记住,码头集装箱的子网至少应该有/80
这样,IPv 6地址就可以以容器的MAC地址结束,从而防止了Docker层中NDP邻居缓存失效的问题。所以如果你有一个/64
为您的整个环境使用/76
主机和/80
为了容器。这样您就可以使用4096主机和16主机。/80
每个人都有。
在虚线下面可视化的图表中的每个配置都由Docker处理:docker0
网桥IP地址配置、主机上到Docker子网的路由、容器IP地址和容器上的路由。线上的配置由用户决定,可以适应个人环境。
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com