首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

IPv6与Docker(引擎) | IPv6 with Docker (Engine)

本节中的信息解释了 Docker 默认网桥的 IPv6。这是一个在安装 Docker 时自动创建名称为bridgebridge网络。

由于 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

代码语言:javascript
复制
{
  "ipv6": true,
  "fixed-cid4-v6": "2001:db8:1::/64"
}

Docker 容器的子网应该至少有一个大小/80,以便 IPv6地址可以以容器的 MAC 地址结束,并且可以防止 Docker 层中的 NDP 邻居缓存失效问题。

默认情况下,--fixed-cidr-v6参数使Docker为路由表添加一个新路由,方法是代表您运行以下三个命令。若要防止自动路由,请设置ip-forwardfalsedaemon.json文件或启动Docker守护进程--ip-forward=false旗子。然后,要获得Docker将自动为您创建的相同的路由表,请发出以下命令:

代码语言:javascript
复制
$ 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_ra2使用以下命令。否则,启用IPv 6的转发将导致拒绝路由器广告。 $sysctl net.ipv6.con.eth0.接受[医]Ra=2

二次

二次

每个新容器都将从定义的子网中获得一个IPv 6地址,并将添加一个默认路由。eth0通过守护进程选项指定的地址在容器中。--default-gateway-v6%28或default-gateway-v6daemon.json%29(如有)。默认网关默认为fe80::1...

此示例提供了一种检查运行容器中IPv 6网络设置的方法。

代码语言:javascript
复制
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/6429%。容器将创建与2001:db8:1::/64通过链路本地网关连接fe80::1eth0...

服务器或虚拟机通常会获得/64IPv 6子网分配%28例如。2001:db8:23:42::/6429%。在这种情况下,您可以进一步拆分它,并提供Docker a/80使用单独的子网。/80主机上其他应用程序的子网:

二次

二次

在此设置中,子网2001:db8:23:42::/642001:db8:23:42:0:0:0:02001: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:02001: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::/64IaaS提供商允许您配置IPv 6地址2001:db8::c0002001:db8::c00f,您的网络配置可能如下所示:

代码语言:javascript
复制
$ 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/1252001:db8::c008/125,使用以下方法daemon.json设置。第一个子网将由主机上的非码头进程使用,第二个子网将由Docker使用。

代码语言:javascript
复制
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8::c008/125"
}

Docker子网位于由路由器管理并连接到eth0所有由Docker分配地址的容器都将在路由器子网中找到,路由器可以直接与这些容器通信。

二次

二次

当路由器希望向第一个容器发送IPv 6数据包时,它将发送一个邻居请求问“谁有2001:db8::c009“但是,子网上没有一个主机有地址;带有地址的容器隐藏在Docker主机后面。因此,Docker主机必须侦听邻居的请求,并响应它是具有地址的设备。此功能称为NDP代理并由主机上的内核处理。要启用NDP代理,请执行以下命令:

代码语言:javascript
复制
$ sysctl net.ipv6.conf.eth0.proxy_ndp=1

接下来,将容器的IPv 6地址添加到NDP代理表中:

代码语言:javascript
复制
$ ip -6 neigh add proxy 2001:db8::c009 dev eth0

从现在开始,内核在设备上回答邻居请求地址。eth0.到此IPv 6地址的所有通信都通过Docker主机路由,Docker主机将根据其路由表通过docker0装置:

代码语言:javascript
复制
$ 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子网的所有路由信息。当您在此环境中添加或移除主机时,您只需更新路由器中的路由表--而不是在每个主机上。

二次

二次

在这种情况下,同一主机的容器可以直接通信。不同主机上的容器之间的通信将通过它们的主机和路由器进行路由。例如,从Container1-1Container2-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地址和容器上的路由。线上的配置由用户决定,可以适应个人环境。

扫码关注腾讯云开发者

领取腾讯云代金券