Генерация MAC-адресов докеров

У меня возник вопрос о приложениях, работающих в контейнерах Docker и генерации UUID.

Вот наш сценарий:

  • В настоящее время наши приложения используют фреймворк, управляемый событиями.

  • Для событий мы генерируем UUID на основе MAC-адреса, pid,
    отметка времени и счетчик.

  • Для запуска контейнеров в распределенной системе, такой как CoreOS (при очень очень низкой вероятности), нет никакой гарантии, что все эти параметры, используемые для создания UUID, будут уникальны для каждого контейнера как один контейнер на одном сервере в кластере может сгенерировать UUID с использованием того же макроса, pid, метки времени и счетчика в качестве другого контейнера в кластере.

  • В сущности, если эти два UUID должны были генерировать событие и отправлять его на нашу шину обмена сообщениями, то, очевидно, был бы конфликт.

В нашем анализе этот сценарий, похоже, сводится к уникальности адресов mac в каждом контейнере Docker.

Итак, чтобы быть откровенным:

  • Насколько уникальны адреса mac в контейнерах?
  • Как создаются mac-адреса, если они не установлены вручную?

Ответ 1

Из моего чтения generateMacAddr функция (изменить): ответьте на вопрос 1.3.0-dev, но все еще корректно для 17.05), MAC-адреса, сгенерированные docker, являются, по существу, адресом IPv4 контейнерный интерфейс на мосте docker0: они гарантированно будут соответствовать IP-адресу.

Подсеть моста docker0, в которой вы должны работать, обычно 255.255.0.0 в соответствии с этот пример 172.17.42.1/16, имеет 65 534 маршрутизируемые адреса. Это уменьшает энтропию для генерации UUID, но столкновение MAC-адресов невозможно, поскольку IP-адреса должны быть уникальными, а сценарий идентичных MAC, PID, времени и счетчика в двух контейнерах на одном и том же сервере докеров /CoreOS не должен быть возможностью,

Однако два хоста CoreOS (каждый из которых запускает один сервер docker) могут потенциально выбирать одну и ту же случайную подсеть, что приводит к возможности дублирования MAC-адресов для контейнеров на разных хостах. Вы можете уклониться от этого, установив фиксированный CIDR для сервера docker на каждом хосте:

--fixed-cidr=CIDR - ограничить диапазон IP из подсети docker0, используя стандартную нотацию CIDR, например 172.167.1.0/28. Этот диапазон должен быть и IPv4 для фиксированных IP-адресов (например: 10.20.0.0/16) и должен быть подмножеством диапазона IP-мостов (docker0 или установить с помощью --bridge). Например, с --fixed-cidr=192.168.1.0/25, IP-адреса для ваших контейнеров будут выбраны из первой половины подсети 192.168.1.0/24.

Это должно обеспечить уникальные MAC-адреса в кластере.

Исходный MAC-адрес IEEE 802 исходит из исходной схемы адресации Ethernet Xerox. Это 48-битное адресное пространство содержит потенциально 248 или 281 474 976 710 656 возможных MAC-адресов.

источник

Если вас беспокоит отсутствие энтропии (сопоставление IP-MAC значительно снижает его), лучшим вариантом может быть использование другого механизма для генерации UUID. UUID версии 3, 4 и 5 не учитывают MAC-адрес. В качестве альтернативы вы можете включить 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
}