Docker MAC 地址生成

Posted

技术标签:

【中文标题】Docker MAC 地址生成【英文标题】:Docker MAC Address Generation 【发布时间】:2014-12-10 16:33:49 【问题描述】:

我有一个关于在 Docker 容器中运行的应用程序和 UUID 生成的问题。

这是我们的场景:

目前我们的应用程序正在使用事件驱动框架。

对于我们根据 mac 地址、pid、生成 UUID 的事件 时间戳和计数器。

对于在像 CoreOS 这样的分布式系统上运行容器(虽然机会非常非常低),不能保证所有用于生成 UUID 的参数对于每个容器都是唯一的,因为一个容器在一台服务器上在集群中可以使用与集群上的另一个容器相同的 mac、pid、时间戳和计数器生成 UUID。

本质上,如果这两个 UUID 都生成一个事件并将其发送到我们的消息总线,那么显然会有冲突。

在我们的分析中,这种情况似乎归结为每个 Docker 容器上 mac 地址的唯一性。

坦率地说:

容器中的 MAC 地址的唯一性如何? 不手动设置mac地址是如何生成的?

【问题讨论】:

【参考方案1】:

根据我对generateMacAddr function 的阅读(编辑答案关注1.3.0-dev,但对于17.05 仍然正确), docker生成的MAC地址本质上就是container's interface在docker0桥上的IPv4地址:保证与IP地址一致。

您必须操作的docker0 网桥的子网,通常是255.255.0.0,根据172.17.42.1/16 的this example,有65,534 个可路由地址。这确实减少了 UUID 生成的熵,但 MAC 地址冲突是不可能的,因为 IP 必须是唯一的,并且同一 docker 服务器/CoreOS 主机上的两个容器中相同的 MAC、PID、时间和计数器的情况应该是不可能的.

但是,两台 CoreOS 主机(每台运行一个 docker 服务器)可能会选择相同的随机子网,从而导致不同主机上的容器的 MAC 重复的可能性。您可以通过为每个主机上的docker 服务器设置fixed CIDR 来避免这种情况:

--fixed-cidr=CIDR — 限制来自 docker0 子网的 IP 范围,使用标准 CIDR 表示法,如 172.167.1.0/28。此范围必须是固定 IP 的 IPv4 范围(例如:10.20.0.0/16),并且必须是网桥 IP 范围的子集(docker0 或使用--bridge 设置)。例如--fixed-cidr=192.168.1.0/25,容器的 IP 将从192.168.1.0/24 子网的前半部分中选择。

这应该确保整个集群的 MAC 地址是唯一的。

原始 IEEE 802 MAC 地址来自原始 Xerox 以太网寻址方案。这个 48 位地址空间可能包含 248 或 281,474,976,710,656 个可能的 MAC 地址。

source

如果您担心缺少熵(IP 到 MAC 的映射大大减少了它),更好的选择可能是使用不同的 UUID 生成机制。 UUID 版本 3、4 和 5 do not take MAC address 考虑在内。或者,您可以在 UUID 生成中包含主机的 MAC。

当然,这种“显着减少 MAC 空间”是否会对 UUID 生成产生任何影响,应该在更改任何代码之前进行测试。

以上链接来源:

// Generate a IEEE802 compliant MAC address from the given IP address.
//
// The generator is guaranteed to be consistent: the same IP will always yield the same
// MAC address. This is to avoid ARP cache issues.
func generateMacAddr(ip net.IP) net.HardwareAddr 
    hw := make(net.HardwareAddr, 6)

    // The first byte of the MAC address has to comply with these rules:
    // 1. Unicast: Set the least-significant bit to 0.
    // 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
    // 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
    hw[0] = 0x02

    // The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
    // Since this address is locally administered, we can do whatever we want as long as
    // it doesn't conflict with other addresses.
    hw[1] = 0x42

    // Insert the IP address into the last 32 bits of the MAC address.
    // This is a simple way to guarantee the address will be consistent and unique.
    copy(hw[2:], ip.To4())

    return hw

【讨论】:

感谢您的回答!这实际上证实了我们可能需要重新考虑我们的实现。 另外,您能否澄清一下它是容器的 IPv4 地址还是主机的 IPv4 地址? Docker IP 地址被 NAT 到主机的 IP 地址。理论上,两个不同主机上的 docker 容器可以在同一个子网中运行,这意味着在这种情况下确实可能发生 MAC 地址冲突。

以上是关于Docker MAC 地址生成的主要内容,如果未能解决你的问题,请参考以下文章

Mac 上装了Docker,但我的Docker服务怎么对外开放

pgdocker重启mac地址

Mac上安装docker

如何为 Docker LXC 容器设置 MAC 地址?

mac上安装docker

Docker for mac安装