Informacje podstawowe
Mam serwer z dwoma interfejsami sieciowymi, na którym działa Docker. Docker, podobnie jak niektóre narzędzia do wirtualizacji, tworzy interfejs mostu linuksowego o nazwie docker0
. Interfejs ten jest domyślnie skonfigurowany z 172.17.42.1
adresem IP i wszystkie kontenery Docker komunikują się z tym interfejsem jako bramą i mają przypisane adresy IP z tego samego /16
zakresu. Jak rozumiem, cały ruch sieciowy do / z kontenerów przechodzi przez NAT, więc wydaje się, że przychodzi z 172.17.42.1
, a przychodzące są wysyłane 172.17.42.1
.
Moja konfiguracja wygląda następująco:
+------------+ /
| | |
+-------------+ 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| |
+------------+
Problem
Chcę skierować cały ruch z / do dowolnych kontenerów Docker z drugiego eth1
192.168.1.2
interfejsu do domyślnej bramy 192.168.1.1
, podczas gdy cały ruch z / do hosta wychodzi z eth0
10.1.1.2
interfejsu do domyślnej bramy 10.1.1.1
. Do tej pory próbowałem różnych rzeczy, ale bezskutecznie, ale jedyną rzeczą, którą uważam za najbliższą do poprawienia, jest użycie iproute2 w następujący sposób:
# 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
Kiedy podnoszę pojemnik, nie mogę z niego pingować po wykonaniu tej czynności. Nie jestem pewien, czy interfejsy mostkowe są obsługiwane w taki sam sposób, jak interfejsy fizyczne dla tego rodzaju routingu, i po prostu chcę kontroli poczytalności, a także wszelkich wskazówek, jak mogę wykonać to z pozoru proste zadanie.
Odpowiedzi:
Być może będziesz musiał zajrzeć także do konfiguracji iptables. Docker maskuje cały ruch pochodzący z podsieci kontenera, powiedzmy 172.17.0.0/16, na 0.0.0.0. Jeśli uruchomisz
iptables -L -n -t nat
, zobaczysz łańcuch POSTROUTING pod tabelą nat, która to robi -Teraz możesz usunąć tę regułę i zastąpić ją regułą, która zamaskuje cały ruch pochodzący z podsieci kontenerów do adresu IP drugiego interfejsu - 192.168.1.2, ponieważ tego właśnie pragniesz. Reguła usuwania będzie, zakładając, że jest to pierwsza reguła w łańcuchu POSTROUTING -
Następnie dodajesz tę niestandardową regułę -
źródło
ip rule add from 172.17.0.0/16 table docker
ip route add default via 192.168.1.2 dev eth1 table docker
ip route flush cache
iptables -t nat -D POSTROUTING 1
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT --to-source 192.168.1.2
/etc/init.d/docker restart
. Potem próbowałem uruchomić ping i traceroute z kontenera i nie byłem w stanie nic osiągnąć.Wpadłem z przyjacielem na ten właśnie problem, w którym chcieliśmy, aby doker obsługiwał wiele interfejsów sieciowych obsługujących żądania. W szczególności pracowaliśmy z usługą AWS EC2, w której także podłączaliśmy / konfigurowaliśmy / przywoływaliśmy dodatkowe interfejsy. W tym projekcie jest coś więcej niż potrzebujesz, dlatego postaram się uwzględnić tylko to, czego potrzebujesz.
Po pierwsze, stworzyliśmy osobną tabelę tras dla
eth1
:Następnie skonfigurowaliśmy tabelę mangle, aby ustawić niektóre znaki połączenia przychodzące z
eth1
:Na koniec dodajemy tę regułę, aby wszyscy
fwmark
mogli korzystać z nowej tabeli, którą utworzyliśmy.Poniższe
iptables
polecenie przywróci znak połączenia, a następnie pozwoli regule routingu korzystać z właściwej tabeli routingu.Wierzę, że to wszystko, co jest potrzebne z naszego bardziej złożonego przykładu, w którym (jak powiedziałem) nasz projekt podłączał / konfigurował / uruchamiał
eth1
interfejs w czasie rozruchu.Teraz ten przykład nie powstrzyma połączeń od
eth0
obsługi zgłoszeń,docker0
ale uważam, że możesz dodać regułę routingu, aby temu zapobiec.źródło
Maskarada nie pochodzi z 172.17.42.1, ale raczej
Co oznacza, że ta reguła nie będzie działać poprawnie.
Spróbuj zamiast tego
źródło
ip rule add from 172.17.0.0/16 table docker
ip route add default via 192.168.1.2 dev eth1 table docker
ip route flush cache
/etc/init.d/docker restart
Z kontenera uruchomiłem traceroute, a pierwszy skok to 10.1.1.1, kiedy powinien to być 192.168.1.1