Hintergrundinformation
Ich habe einen Server mit zwei Netzwerkschnittstellen, auf dem Docker ausgeführt wird. Docker erstellt wie einige Virtualisierungstools eine Linux-Bridge-Schnittstelle mit dem Namen docker0
. Diese Schnittstelle ist standardmäßig mit einer IP von konfiguriert, 172.17.42.1
und alle Docker-Container kommunizieren mit dieser Schnittstelle als Gateway und erhalten IP-Adressen im selben /16
Bereich. Soweit ich weiß, wird der gesamte Netzwerkverkehr zu / von Containern über ein NAT abgewickelt, so dass er anscheinend von einem NAT ausgeht 172.17.42.1
und an einen eingehenden Datenverkehr gesendet wird 172.17.42.1
.
Mein Setup sieht so aus:
+------------+ /
| | |
+-------------+ 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| |
+------------+
Das Problem
Ich möchte den gesamten Datenverkehr von / zu Docker-Containern aus der zweiten eth1
192.168.1.2
Schnittstelle an ein Standard-Gateway von leiten 192.168.1.1
, während der gesamte Datenverkehr vom / zum Host-Computer über die eth0
10.1.1.2
Schnittstelle an ein Standard-Gateway von leiten soll 10.1.1.1
. Ich habe eine Reihe von Dingen bisher erfolglos ausprobiert, aber das, was meiner Meinung nach am ehesten zu korrigieren ist, ist, iproute2 wie folgt zu verwenden:
# 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
Wenn ich einen Container aufbringe, kann ich danach gar nicht mehr herauspingen. Ich bin nicht sicher, ob Bridge-Schnittstellen genauso behandelt werden wie physische Schnittstellen für diese Art von Routing. Ich möchte lediglich eine Überprüfung der Integrität sowie Tipps, wie ich diese scheinbar einfache Aufgabe ausführen kann.
Antworten:
Möglicherweise müssen Sie auch mehr über das Setup von iptables nachdenken. Docker maskiert den gesamten Datenverkehr, der aus dem Container-Subnetz stammt, z. B. 172.17.0.0/16, auf 0.0.0.0. Wenn Sie ausführen
iptables -L -n -t nat
, können Sie die POSTROUTING-Kette unter der entsprechenden Tabelle sehen.Jetzt können Sie diese Regel entfernen und durch eine Regel ersetzen, die den gesamten Datenverkehr aus dem Subnetz der Container zur IP - 192.168.1.2 Ihrer zweiten Schnittstelle maskiert, wie Sie es wünschen. Die Löschregel lautet, sofern es sich um die erste Regel in der POSTROUTING-Kette handelt:
Dann fügen Sie diese benutzerdefinierte Regel hinzu -
quelle
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
. Dann habe ich versucht, einen Ping-out und eine Traceroute aus einem Container zu starten und konnte nichts erreichen.Ein Freund und ich hatten genau dieses Problem, bei dem wir wollten, dass Docker mehrere Netzwerkschnittstellen unterstützen, die Anfragen bearbeiten. Wir haben speziell mit dem AWS EC2-Service zusammengearbeitet, bei dem wir auch die zusätzlichen Schnittstellen angeschlossen / konfiguriert / aufgerufen haben. In diesem Projekt gibt es mehr als das, was Sie brauchen. Ich werde versuchen, nur das einzubeziehen, was Sie hier brauchen.
Zunächst haben wir eine separate Routentabelle erstellt für
eth1
:Als nächstes haben wir die Mangeltabelle so konfiguriert, dass einige Verbindungsmarkierungen gesetzt werden, die von kommen
eth1
:Schließlich fügen wir diese Regel hinzu, damit alle
fwmark
s die neu erstellte Tabelle verwenden können.Mit dem folgenden
iptables
Befehl wird die Verbindungsmarke wiederhergestellt, und die Routing-Regel kann die richtige Routing-Tabelle verwenden.Ich glaube, dies ist alles, was in unserem komplexeren Beispiel benötigt wird, in dem (wie gesagt) unser Projekt die
eth1
Schnittstelle beim Booten anhängt / konfiguriert / aufruft .Jetzt würde dieses Beispiel die Verbindungen nicht davon abhalten
eth0
, Anfragen zu bearbeiten,docker0
aber ich glaube, Sie könnten eine Routing-Regel hinzufügen, um dies zu verhindern.quelle
Die Maskerade ist nicht vom 172.17.42.1 sondern eher
Was bedeutet, dass diese Regel nicht richtig funktioniert.
Versuchen Sie es stattdessen
quelle
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
Aus dem Container lief ich eine Traceroute und der erste Sprung war 10.1.1.1, als es 192.168.1.1 gewesen sein sollte