我有一个关于在Docker容器和UUID生成中运行的应用程序的问题.
这是我们的场景:
>目前我们的应用程序正在使用一个事件驱动的框架.
>对于我们根据mac地址生成UUID的事件,pid,
时间戳和柜台.
>对于在像CoreOS这样的分布式系统上运行容器(非常非常低的几率),不能保证用于生成UUID的所有参数对于每个容器都是唯一的,因为集群中的一个服务器上的一个容器可以生成使用与集群上另一容器相同的mac,时间戳和计数器的UUID.
>实质上,如果这两个UUID都是生成事件并将其发送到我们的消息总线,那么显然会有冲突.
在我们的分析中,这种情况似乎归结为每个Docker容器上的mac地址的唯一性.
所以坦白说:
>容器中的mac地址的独特之处在哪里?
>如果没有手动设置,mac地址是如何生成的?
generateMacAddr
function读数,docker生成的MAC地址基本上是docker0网桥上的container’s interface的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
— restrict the IP range from the docker0 subnet,using the standard CIDR notation like172.167.1.0/28
. This range must be and IPv4 range for fixed IPs (ex:10.20.0.0/16
) and must be a subset of the bridge IP range (docker0
or set using--bridge
). For example with--fixed-cidr=192.168.1.0/25
,IPs for your containers will be chosen from the first half of192.168.1.0/24
subnet.
这应该确保集群中的唯一MAC地址.
The original IEEE 802 MAC address comes from the original Xerox Ethernet addressing scheme. This 48-bit address space contains potentially 248 or 281,474,976,710,656 possible MAC addresses.
如果您担心缺乏熵(IP到MAC映射会大大减少),更好的选择可能是使用不同的机制来生成UUID.考虑到UUID版本3,4和5 do not take MAC address.或者,您可以将主机的MAC包含在UUID生成中.
当然,这个“相当大的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
}