15

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

这是我们的场景:

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

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

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

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

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

坦率地说:

  • 容器中的 MAC 地址有多独特?
  • 如果不手动设置mac地址是如何生成的?
4

1 回答 1

8

根据我对generateMacAddr函数的阅读(编辑有关答案1.3.0-dev,但仍然正确17.05),生成的 MAC 地址docker本质上是网桥上容器接口IPv4的地址:它们保证与 IP 地址一致。docker0

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

然而,两台 CoreOS 主机(每台运行一台docker服务器)可能会选择相同的随机子网,从而导致不同主机上的容器的 MAC 重复。您可以通过为每个主机上的服务器设置固定 CIDR来规避这一点:docker

--fixed-cidr=CIDR— 使用标准 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 地址。

来源

如果您担心缺乏熵(IP 到 MAC 的映射大大减少了它),更好的选择可能是使用不同的 UUID 生成机制。UUID 版本 3、4 和 5不考虑 MAC 地址。或者,您可以在 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
}
于 2014-10-27T17:52:01.597 回答