В Docker обычно возникает вопрос: “Как мне подключить мои контейнеры непосредственно к локальной физической сети?”.
Это особенно актуально, когда вы используете приложения мониторинга, собирающие сетевую статистику, и хотите подключить контейнер к устаревшим приложениям.
Возможным решением этого вопроса является создание и внедрение типа сети macvlan.
Сети macvlan – это специальные виртуальные сети, которые позволяют создавать “клоны” физического сетевого интерфейса, подключенного к вашим Linux-серверам, и подключать контейнеры непосредственно к вашей локальной сети.
Чтобы это произошло, просто назначьте физический сетевой интерфейс на вашем сервере сети macvlan, которая имеет свою собственную подсеть и шлюз.
В этом руководстве мы продемонстрируем, как можно создавать и использовать сети mavlan в Docker.
Но прежде чем вы приступите к работе, вот несколько моментов, о которых вам следует помнить:
ПРИМЕЧАНИЕ:
- Сети macvlan обычно блокируются большинством поставщиков облачных услуг. Следовательно, вам необходим физический доступ к вашему серверу.
- Сетевой драйвер macvlan работает только на хостах Linux. Он не поддерживается на устройствах Windows или mac.
- Вы должны работать на Linux с ядром 4.0 и более поздней версии.
В качестве предварительного условия у нас установлен Docker.
Создание сети macvlan
Сеть macvlan может быть создана либо в режиме моста, либо в режиме транка 802.1q.
В режиме моста трафик macvlan направляется через физический интерфейс на хосте Linux.
В режиме trunk 802.1q трафик проходит через подинтерфейс 802.1q, который создается Docker.
Это позволяет контролировать маршрутизацию и фильтрацию.
С этим разобрались, теперь давайте посмотрим, как можно создать каждую из сетей macvlan.
1) Режим моста
В нашем примере мы имеем физический сетевой интерфейс enp0s3 в сети 192.168.2.0/24 и шлюз по умолчанию 192.168.2.1.
Шлюз по умолчанию – это IP-адрес маршрутизатора.
Теперь мы создадим сеть macvlan под названием demo-macvlan-net со следующей конфигурацией.
$ docker network create -d macvlan \ --subnet=192.168.2.0/24 \ --gateway=192.168.2.1 \ -o parent=enp0s3 \ demo-macvlan-net
ПРИМЕЧАНИЕ:
- Значения подсети и шлюза должны совпадать со значениями сетевого интерфейса хоста Docker. Проще говоря, подсеть и шлюз по умолчанию для вашей сети macvlan должны совпадать с подсетью и шлюзом хоста Docker. Здесь опция -subnet= указывает подсеть, а опция -gateway определяет шлюз, который является IP маршрутизатора. Измените эти значения в соответствии с вашим окружением.
- Параметр -d задает имя драйвера. В нашем случае опция -d указывает драйвер macvlan.
- Параметр -o parent указывает родительский интерфейс, который является интерфейсом вашей сетевой карты. В нашем случае родительским интерфейсом является enp0s3.
- Наконец, мы указали имя нашей сети macvlan – demo-macvlan-net.
Чтобы убедиться, что только что добавленная сеть macvlan существует, выполните команду:
$ docker network ls
Далее мы запустим образ контейнера и прикрепим его к сети macvlan с помощью опции -network.
Опция -itd позволяет запускать контейнер в фоновом режиме, а также присоединять его к сети.
Опция -rm удаляет контейнер после его остановки.
Мы также назначили IP 192.168.2.110 нашему контейнеру.
Обязательно укажите IP, который не входит в диапазон IP-адресов DHCP, чтобы избежать конфликта IP-адресов.
$ docker run --rm -itd \ --network=demo-macvlan-net \ --ip=192.168.2.110 \ alpine:latest \ /bin/sh
Чтобы убедиться, что контейнер запущен, выполните команду:
$ docker ps
Кроме того, вы можете просмотреть более подробную информацию о контейнере с помощью команды docker inspect следующим образом:
$ docker container inspect e9b71d094e48
Теперь создадим второй контейнер следующим образом.
В этом случае контейнер автоматически получит IP от Docker.
$ docker run --rm -itd \ --network=demo-macvlan-net \ alpine:latest \ /bin/sh
Еще раз подтвердим, что у нас есть два контейнера.
$ docker ps
Далее мы попытаемся установить, могут ли контейнеры пинговать друг друга.
В данном случае мы проверяем возможность соединения первого контейнера со вторым контейнером.
Этого можно добиться с помощью одной команды следующим образом.
$ docker exec -it daa09a330b36 ping 192.168.2.110 -4
В качестве альтернативы вы можете получить доступ к оболочке контейнера и выполнить команду ping.
$ docker exec -it daa09a330b36 /bin/sh
Попробуйте выполнить ту же команду из другого контейнера и вы увидите, что на данном этапе контейнеры могут взаимодействовать друг с другом.
Однако хост Docker не может взаимодействовать с контейнерами и наоборот.
Если вы попробуете пинговать хост с контейнера или наоборот, вы обнаружите, что хост и контейнеры не могут взаимодействовать друг с другом.
Из показанного результата видно, что мы не можем связаться с одним из контейнеров с помощью команды ping.
$ ping 192.168.2.110 -c 4
Точно так же мы не можем установить связь от контейнера к хосту.
$ docker exec -it e9b71d094e48 /bin/sh
$ ping 192.168.2.105
Чтобы контейнеры могли взаимодействовать с хостом, нам нужно создать интерфейс macvlan на хосте Docker и настроить маршрут к интерфейсу macvlan.
Создание нового интерфейса macvlan на хосте
Далее мы создадим интерфейс macvlan с помощью команды ip.
В этом примере мы создали интерфейс под названием mycool-net.
Не стесняйтесь дать ему любое имя, которое сочтете нужным.
$ sudo ip link add mycool-net link enp0s3 type macvlan mode bridge
Затем назначьте уникальный IP-адрес интерфейсу.
Убедитесь, что этот IP зарезервирован на маршрутизаторе.
$ sudo ip addr add 192.168.2.50/32 dev mycool-net
Подключите интерфейс macvlan.
$ sudo ip link set mycool-net up
Последним шагом будет указание нашему хосту Docker использовать этот интерфейс для связи с контейнерами.
Для этого мы добавим маршрут к сети macvlan.
$ sudo ip route add 192.168.2.0/24 dev mycool-net
Теперь, с установленным маршрутом, хост и контейнеры могут взаимодействовать друг с другом.
Вы можете проверить маршруты с помощью команды ip route.
$ ip route
2) Режим транк моста 802.1q
Когда речь идет о примере trunk моста 802.1q, трафик проходит через подинтерфейс enp0s3 под названием enp0s3.50 (интерфейс с меткой Vlan).
Docker будет направлять трафик к контейнеру, используя его MAC-адрес.
В этом примере мы создаем сеть 802.1q trunk macvlan под названием demo-macvlan50-net, подключенную к подинтерфейсу enp0s3.50.
Обязательно измените параметры подсети, шлюза и родителя в соответствии с вашей сетью.
$ docker network create -d macvlan \ --subnet=192.168.50.0/24 \ --gateway=192.168.50.1 \ -o parent=enp0s3.50 \ demo-macvlan50-net
Вы можете выполнить команды docker network ls и docker network inspect demo-macvlan50-net, чтобы убедиться, что сеть существует
$ docker network ls
$ docker network inspect demo-macvlan50-net
Отсюда можно запустить и присоединить контейнер к сети trunk bridge.
$ docker run --rm -itd \ --network=demo-macvlan50-net \ alpine:latest \ /bin/sh
Удаление сетей macvlan
Чтобы удалить сети macvlan, сначала остановите и удалите контейнеры, которые используют сети macvlan.
В наших примерах мы использовали опцию ‘-rm’ при запуске контейнера, поэтому, когда мы остановим их, они будут удалены автоматически.
$ docker network rm demo-macvlan-net $ docker network rm demo-macvlan50-net
Заключение
В этом руководстве мы продемонстрировали, как можно создавать сети macvlan – в частности, режим моста macvlan и транк моста 802.1q.
см. также:
- 🐳 Как защитить TCP-сокет Docker с помощью TLS
- 🐳 Как изменить конфигурацию запущенных контейнеров Docker
- 🐳 Как использовать Docker для проверки безопасности ПО
- 🐳 Как и зачем запускать Docker внутри Docker
- 🐳 Как опросить сокет Docker с помощью curl
- 🐳 Docker secret – как использовать в Docker Swarm и Docker Compose
- 🐳 Как запустить инструмент Netbox IPAM в контейнерах Docker