Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker MAC Address Generation

I had a question about applications running within Docker containers and UUID generation.

Here’s our scenario:

  • Currently our applications are using an event driven framework.

  • For the events we generate the UUID’s based on mac address, pid,
    time-stamp and counter.

  • For running containers on a distributed system like CoreOS (while a very very very low chance), there is no guarantee that all those parameters used to generate a UUID would be unique for each container as one container on one server in the cluster could generate a UUID using the same mac, pid, time-stamp and counter as another container on the cluster.

  • In essence if these two UUID’s were both to generate an event and send it to our messaging bus, then obviously there would be a conflict.

In our analysis, this scenario seems to boil down to the uniqueness of mac addresses on each Docker container.

So to be frank:

  • How unique are the mac addresses within containers?
  • How are mac addresses generated if they are not manually set?
like image 353
Blanco Avatar asked Oct 15 '14 14:10

Blanco


People also ask

Do Docker containers have MAC address?

According to the v1. 7 documentation, all the Docker containers have the same prefix in their MAC addresses – '02:42:' if generated automatically. The remaining 4 octets of the MAC address is a container's IPv4 address printed in hex.

Can Docker run natively on Mac?

Docker Desktop currently supports macOS Catalina, macOS Big Sur, and macOS Monterey. At least 4 GB of RAM. VirtualBox prior to version 4.3.30 must not be installed as it is not compatible with Docker Desktop.

Is Mac good for Docker?

Docker image was built in only seven minutes on MacBook M1 Pro, which was even better than the build time on my new VPS. This is not surprising, I gave Docker quite a lot of resources. But it also shows that if there are not too many I/O disk operations, performance is quite good.


1 Answers

From my reading of generateMacAddr function (edit: answer concerned 1.3.0-dev, but is still correct for 17.05), MAC addresses generated by docker are essentially the IPv4 address of the container's interface on the docker0 bridge: they are guaranteed to be consistent with the IP address.

The docker0 bridge's subnet you have to operate in, usually 255.255.0.0 as per this example of 172.17.42.1/16, has 65,534 routable addresses. This does reduce entropy for UUID generation, but MAC address collision isn't possible as IPs must be unique, and the scenario of identical MAC, PID, time and counter in two containers on the same docker server/CoreOS host should not be a possibility.

However two CoreOS hosts (each running one docker server) could potentially choose the same random subnet, resulting in the possibility of duplicated MACs for containers on different hosts. You could evade this by setting a fixed CIDR for the docker server on each host:

--fixed-cidr=CIDR — restrict the IP range from the docker0 subnet, using the standard CIDR notation like 172.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 of 192.168.1.0/24 subnet.

This should ensure unique MAC addresses across the cluster.

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.

source

If you are concerned about lack of entropy (the IP to MAC mapping reduces it considerably), a better option may be to use a different mechanism for UUID generation. UUID versions 3, 4 and 5 do not take MAC address into account. Alternatively you could include the host machine's MAC in UUID generation.

Of course, whether this "considerable MAC space reduction" will have any impact of UUID generation should probably be tested before any code is changed.

Source linked to above:

// 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
}
like image 80
Andy Avatar answered Sep 18 '22 23:09

Andy