Маршрутизация из Docker-контейнеров с использованием другого физического сетевого интерфейса и шлюза по умолчанию

Исходная информация

У меня есть сервер с двумя сетевыми интерфейсами, на котором работает Docker. Docker, как и некоторые инструменты виртуализации, создает интерфейс моста Linux под названием docker0, Этот интерфейс по умолчанию настроен с IP-адресом 172.17.42.1 и все контейнеры Docker взаимодействуют с этим интерфейсом в качестве своего шлюза, и им назначаются IP-адреса в одном и том же /16 спектр. Насколько я понимаю, весь сетевой трафик в / из контейнеров проходит через NAT, поэтому исходящий он, кажется, приходит 172.17.42.1и входящий отправляется 172.17.42.1,

Моя настройка выглядит так:

                                          +------------+        /
                                          |            |       |
                            +-------------+ Gateway 1  +-------
                            |             | 10.1.1.1   |     /
                     +------+-------+     +------------+    |
                     |     eth0     |                      /
                     |   10.1.1.2   |                      |
                     |              |                      |
                     | DOCKER HOST  |                      |
                     |              |                      | Internet
                     |   docker0    |                      |
                     |   (bridge)   |                      |
                     |  172.17.42.1 |                      |
                     |              |                      |
                     |     eth1     |                      |
                     |  192.168.1.2 |                      \
                     +------+-------+     +------------+    |
                            |             |            |     \
                            +-------------+ Gateway 2  +-------
                                          | 192.168.1.1|       |
                                          +------------+            

Эта проблема

Я хочу направить весь трафик из / в любые контейнеры Docker из второго eth1192.168.1.2 интерфейс к шлюзу по умолчанию 192.168.1.1в то время как весь трафик с / на хост-компьютер выходит из eth010.1.1.2 интерфейс к шлюзу по умолчанию 10.1.1.1, До сих пор я пробовал разные вещи, но безрезультатно, но единственное, что мне кажется наиболее близким к исправлению, - это использовать iproute2 следующим образом:

# Create a new routing table just for docker
echo "1 docker" >> /etc/iproute2/rt_tables

# Add a rule stating any traffic from the docker0 bridge interface should use 
# the newly added docker routing table
ip rule add from 172.17.42.1 table docker

# Add a route to the newly added docker routing table that dictates all traffic
# go out the 192.168.1.2 interface on eth1
ip route add default via 192.168.1.2 dev eth1 table docker

# Flush the route cache
ip route flush cache

# Restart the Docker daemon so it uses the correct network settings
# Note, I do this as I found Docker containers often won't be able
# to connect out if any changes to the network are made while it's     
# running
/etc/init.d/docker restart

Когда я поднимаю контейнер, я вообще не могу выскочить из него после этого. Я не уверен, что мостовые интерфейсы обрабатываются так же, как физические интерфейсы для такого рода маршрутизации, и просто хочу проверить работоспособность, а также какие-либо советы о том, как я могу выполнить эту, казалось бы, простую задачу.

3 ответа

Мы с другом столкнулись с этой проблемой, когда нам хотелось, чтобы докер поддерживал несколько запросов на обслуживание сетевых интерфейсов. Мы специально работали со службой AWS EC2, где мы также подключали / настраивали / вызывали дополнительные интерфейсы. В этом проекте есть не только то, что вам нужно, поэтому я постараюсь включить сюда только то, что вам нужно.

Сначала мы создали отдельную таблицу маршрутов для eth1:

ip route add default via 192.168.1.2 dev eth1 table 1001

Затем мы настроили таблицу mangle, чтобы установить некоторые метки подключения, поступающие из eth1:

iptables -t mangle -A PREROUTING -i eth1 -j MARK --set-xmark 0x1001/0xffffffff
iptables -t mangle -A PREROUTING -i eth1 -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff

Наконец мы добавим это правило для всех fwmarks, чтобы использовать новую таблицу, которую мы создали.

ip rule add from all fwmark 0x1001 lookup 1001

Нижеприведенное iptables Команда восстановит метку соединения, а затем разрешит правилу маршрутизации использовать правильную таблицу маршрутизации.

iptables -w -t mangle -A PREROUTING -i docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff

Я считаю, что это все, что нужно из нашего более сложного примера, где (как я уже сказал) наш проект подключал / настраивал / вызывал eth1 интерфейс во время загрузки.

Теперь этот пример не остановит соединения от eth0 от обслуживания запросов до docker0 но я считаю, что вы могли бы добавить правило маршрутизации, чтобы предотвратить это.

Возможно, вам придется больше посмотреть на настройку iptables. Docker маскирует весь трафик, исходящий из подсети контейнера, скажем, 172.17.0.0/16, в 0.0.0.0. Если вы бежите iptables -L -n -t nat, вы можете увидеть цепочку POSTROUTING под таблицей nat, которая делает это -

Цепь РАЗМЕЩЕНИЯ (ПРИНЯТЬ ПОЛИТИКУ)
целевой источник назначения
MASQUERADE  all  - 172.17.0.0/16        0.0.0.0/0

Теперь вы можете удалить это правило и заменить его правилом, которое маскирует весь трафик, исходящий из подсети контейнеров, в IP -адрес вашего второго интерфейса - 192.168.1.2, поскольку это то, что вам нужно. Правило удаления будет, при условии, что это первое правило в цепочке POSTROUTING -

iptables -t nat -D POSTROUTING 1

Затем вы добавляете это пользовательское правило -

iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT - к источнику 192.168.1.2

Маскарад не из 172.17.42.1, а скорее

 -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

Это означает, что это правило не будет работать правильно.

ip rule add from 172.17.42.1 table docker

Попробуй вместо

ip rule add from 172.17.0.0/16 table docker
Другие вопросы по тегам