Als ich bei der Fehlerbehebung des Titels nachforschte, entschied ich mich, ihn zu schreiben, da es nur wenige Artikel gab, in denen diese Angelegenheit unerwartet als kritisch erwähnt wurde.
Als ich unter CentOS7 eine Linux Bridge erstellte, einen Docker-Container darunter zuordnete und die Kommunikation bestätigte, konnte keine Kommunikation durchgeführt werden.
Linux Bridge arbeitet mit einem Kernelmodul namens Bridge, aber seine Sicherheit wird von einem Kernelmodul namens br_netfilter (Abhängigkeit von Bridge) verwaltet, und br_netfilter steuert die Kommunikation anhand der iptales-Einstellungen. .. Daher kann die Kommunikation durchgeführt werden, indem eine der folgenden Aktionen ausgeführt wird.
① Deaktivieren Sie Bridge Netfilter ② Legen Sie die Berechtigung für iptables fest
OS:CentOS 7.5 Kernel Ver:3.10.0-862.14.4.el7.x86_64 docker Ver:18.06.1-ce
Stellen Sie zunächst sicher, dass die Container über Docker0 miteinander kommunizieren können. Dies wird normalerweise zugewiesen, wenn der Docker-Container bereitgestellt wird.
Führen Sie Docker Run aus und stellen Sie zwei Container bereit.
docker run -d --name cent1 centos/tools:latest /sbin/init
docker run -d --name cent2 centos/tools:latest /sbin/init
Stellen Sie sicher, dass der Container mit dem Befehl docker ps normal gestartet wurde.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8126f9f72ee2 centos/tools:latest "/sbin/init" 6 seconds ago Up 3 seconds cent2
a957a097b6a5 centos/tools:latest "/sbin/init" About a minute ago Up About a minute cent1
Überprüfen Sie zunächst die Zuordnung zwischen der Netzwerkkarte des bereitgestellten Containers und der Netzwerkkarte des Docker-Hosts. Überprüfen Sie jede Netzwerkkarte des Docker-Containers wie folgt. eth0 von cent1 ist der Index9 des Docker-Hosts eth0 von cent2 ist index11 des Docker-Hosts Sie können sehen, dass es gebunden ist.
docker exec cent1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
docker exec cent2 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
Überprüfen Sie die Netzwerkkarte des Docker-Hosts wie folgt.
ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:b3:b5:18 brd ff:ff:ff:ff:ff:ff
3: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:b3:b5:22 brd ff:ff:ff:ff:ff:ff
4: vlan10@ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:b3:b5:22 brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:1c:c2:6d:d0 brd ff:ff:ff:ff:ff:ff
9: vethc59a2d1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether f6:1a:1b:00:b9:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
11: vethfee6857@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether 86:45:ea:11:db:35 brd ff:ff:ff:ff:ff:ff link-netnsid 1
Wenn Sie die Informationen von Linux Bridge überprüfen, können Sie außerdem sehen, dass veth auf der Hostseite von cent1 und 2 docker0 zugewiesen ist, wie unten gezeigt.
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421cc26dd0 no vethc59a2d1
vethfee6857
Das Obige kann wie im Bild unten gezeigt zusammengefasst werden.
Wenn Sie den Ping über docker0 von cent1 nach cent2 überspringen und die Kommunikation überprüfen, können Sie wie folgt normal kommunizieren.
docker exec cent2 ping -c 3 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=10.2 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.045 ms
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.045/3.448/10.252/4.811 ms
Hier ist das Hauptproblem. Wenn Sie als Nächstes eine neue Linux Bridge erstellen und einen Docker-Container zuweisen, prüfen Sie, ob Sie wie Docker0 kommunizieren können.
Erstellen Sie eine Brücke mit dem Namen new-bridge1 als neue Brücke.
brctl addbr new-bridge1
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421cc26dd0 no vethc59a2d1
vethfee6857
new-bridge1 8000.000000000000 no
Starten Sie Bridge nach dem Erstellen wie folgt.
ip l set dev new-bridge1 up
ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:b3:b5:18 brd ff:ff:ff:ff:ff:ff
3: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:b3:b5:22 brd ff:ff:ff:ff:ff:ff
4: vlan10@ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:b3:b5:22 brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:1c:c2:6d:d0 brd ff:ff:ff:ff:ff:ff
9: vethc59a2d1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master new-bridge1 state UP mode DEFAULT group default
link/ether f6:1a:1b:00:b9:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
11: vethfee6857@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master new-bridge1 state UP mode DEFAULT group default
link/ether 86:45:ea:11:db:35 brd ff:ff:ff:ff:ff:ff link-netnsid 1
12: new-bridge1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 86:45:ea:11:db:35 brd ff:ff:ff:ff:ff:ff
Die Netzwerkkarte des vom Docker bereitgestellten Containers (genauer gesagt die veth, die der Container-Netzwerkkarte auf der Docker-Hostseite entspricht) befindet sich in dem Status, der Docker0 zugewiesen ist. Schließen Sie diese Container-NICs zur Überprüfung von Docker 0 aus.
brctl delif docker0 vethc59a2d1
brctl delif docker0 vethfee6857
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421cc26dd0 no
new-bridge1 8000.000000000000 no
Weisen Sie die Container-NIC der neu erstellten new-bridge1 zu.
brctl addif new-bridge1 vethc59a2d1
brctl addif new-bridge1 vethfee6857
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421cc26dd0 no
new-bridge1 8000.8645ea11db35 no vethc59a2d1
vethfee6857
Wenn Sie die Operationen bis zu diesem Punkt ausführen, wird der Status wie in der Abbildung unten gezeigt angezeigt.
Versuchen Sie über die neu erstellte new-bridge1, wie zuvor docker0, von cent1 nach cent2 zu pingen, um die Kommunikation zu überprüfen.
docker exec cent1 ping -c 3 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 1999ms
Im Gegensatz zu Docker0 können Sie dann feststellen, dass zwischen cent1 und cent2 keine Kommunikation besteht.
Versuchen Sie zunächst, tcpdump auf jeder Netzwerkkarte abzurufen. Zwei Dinge können aus den Ergebnissen unten gesehen werden. (1) Die ARP-Anfrage ist normalerweise von Cent1 bis Cent2 eingegangen, und Cent1 hat die Antwort erhalten. ② Der Ping hat die Linux Bridge (new-bridge1) erreicht, nicht aber den cent2
NIC von cent1
tcpdump -i vethc59a2d1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vethc59a2d1, link-type EN10MB (Ethernet), capture size 262144 bytes
23:20:39.379638 IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 45, seq 1, length 64
23:20:40.378780 IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 45, seq 2, length 64
23:20:41.378785 IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 45, seq 3, length 64
23:20:44.383711 ARP, Request who-has 172.17.0.3 tell 172.17.0.2, length 28
23:20:44.383744 ARP, Reply 172.17.0.3 is-at 02:42:ac:11:00:03 (oui Unknown), length 28
NIC von cent2
tcpdump -i vethfee6857
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vethfee6857, link-type EN10MB (Ethernet), capture size 262144 bytes
23:20:44.383726 ARP, Request who-has 172.17.0.3 tell 172.17.0.2, length 28
23:20:44.383741 ARP, Reply 172.17.0.3 is-at 02:42:ac:11:00:03 (oui Unknown), length 28
new-bridge1
tcpdump -i new-bridge1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on new-bridge1, link-type EN10MB (Ethernet), capture size 262144 bytes
23:20:39.379638 IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 45, seq 1, length 64
23:20:40.378780 IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 45, seq 2, length 64
23:20:41.378785 IP 172.17.0.2 > 172.17.0.3: ICMP echo request, id 45, seq 3, length 64
23:20:44.383711 ARP, Request who-has 172.17.0.3 tell 172.17.0.2, length 28
23:20:44.383741 ARP, Reply 172.17.0.3 is-at 02:42:ac:11:00:03 (oui Unknown), length 28
In Bezug auf ① werde ich den ARP-Cache in jedem Container für alle Fälle überprüfen. Sie können sehen, dass die MAC-Adresse des Kommunikationspartners normal geschrieben ist.
docker exec cent1 arp -e
Address HWtype HWaddress Flags Mask Iface
172.17.0.3 ether 02:42:ac:11:00:03 C eth0
gateway (incomplete) eth0
docker exec cent2 arp -e
Address HWtype HWaddress Flags Mask Iface
172.17.0.2 ether 02:42:ac:11:00:02 C eth0
gateway (incomplete) eth0
Linux Bridge arbeitet mit einem Kernelmodul namens Bridge, aber seine Sicherheit wird von einem Kernelmodul namens br_netfilter (Abhängigkeit von Bridge) verwaltet, und br_netfilter steuert die Kommunikation anhand der iptables-Einstellungen. Es scheint, dass. Daher ist die Kommunikation über Bridge standardmäßig nicht zulässig, und dies geschieht.
$ lsmod | grep br_netfilter
br_netfilter 24576 0
bridge 155648 1 br_netfilter
Die Kommunikation zwischen Containern wird durch eine der folgenden Maßnahmen möglich.
Netfilter, das normalerweise die Linux Bridge-Kommunikation steuert, ist aktiviert. Die Kommunikation kann erreicht werden, indem dies absichtlich deaktiviert wird. Das Aktivieren / Deaktivieren von Bridge Netfilter ist der Kernelparameter net.bridge.bridge-nf-call-iptables. Kann von eingestellt werden.
Überprüfen Sie den Status des Bridge Net-Filters Derzeit ist 1 gesetzt und befindet sich in einem gültigen Zustand.
sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1
Einstellungsänderung Setzen Sie net.bridge.bridge-nf-call-iptables = 0 in /etc/sysctl.conf und Reflektieren Sie die Einstellungen.
cat /etc/sysctl.conf
sysctl settings are defined through files in
/usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
Vendors settings live in /usr/lib/sysctl.d/.
To override a whole file, create a new file with the same in
/etc/sysctl.d/ and put new settings there. To override
only specific settings, add a file with a lexically later
name in /etc/sysctl.d/ and put new settings there.
For more information, see sysctl.conf(5) and sysctl.d(5).
net.bridge.bridge-nf-call-iptables = 0
sysctl -p
net.bridge.bridge-nf-call-iptables = 0
sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 0
Bridge Netfilter bezieht sich auf iptables zur Steuerung der Kommunikation. Fügen Sie daher die Berechtigungsregel wie folgt zu iptables hinzu Sie können über die Linux Bridge kommunizieren. Wenn Sie mit dem Befehl iptables eine Regel hinzufügen, indem Sie ein Paketvergleichsmodul namens physdev angeben, das die Eingabe und Ausgabe der Bridge mit -m verwaltet, wird die gesamte Kommunikation über Brige zugelassen.
iptables - Beschreibung der Systemverwaltungsbefehle - Liste der Linux-Befehle https://kazmax.zpp.jp/cmd/i/iptables.8.html
iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
iptables -nvL --line-number
Chain INPUT (policy ACCEPT 52 packets, 3250 bytes)
num pkts bytes target prot opt in out source destination
Chain FORWARD (policy DROP 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 PHYSDEV match --physdev-is-bridged
2 2006 2508K DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
3 2006 2508K DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
4 1126 2451K ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
5 46 5840 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
6 834 51247 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
7 46 5840 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
(Weggelassen)
In kubernetes wird angegeben, dass net.bridge.bridge-nf-call-iptables = 1 ist. Weil ich bei der folgenden Validierung mit Kubernetes auf dieses Problem gestoßen bin Unterstützung für iptables-Regeln hinzugefügt.
Spielen Sie mit Multus https://rheb.hatenablog.com/entry/multus_introduction
An dieser Stelle stellt sich eine Frage: "Warum kann Docker0 kommunizieren, obwohl es sich tatsächlich um dieselbe Linux Bridge handelt?" Die Antwort liegt in den Einstellungen von iptables. Docker scheint die Regeln beschrieben zu haben, die für die Installation und die Erstellung des Docker-Netzwerks in iptables erforderlich sind. Wenn Sie die Einstellungsinformationen von iptables überprüfen, können Sie sehen, dass die Kommunikation von Docker0 nach außen und die Kommunikation über Docker0 in den FRWARD-Ketten Nr. 5 und 6 AKZEPTIERT sind. Darüber hinaus legt Docker auch NAT für iptables fest.
iptables -nvL --line-number
Chain INPUT (policy ACCEPT 228K packets, 579M bytes)
num pkts bytes target prot opt in out source destination
Chain FORWARD (policy DROP 12 packets, 1008 bytes)
num pkts bytes target prot opt in out source destination
1 9003 12M DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
2 9003 12M DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
3 5650 12M ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
4 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
5 3341 191K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
6 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 130K packets, 7700K bytes)
num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references)
num pkts bytes target prot opt in out source destination
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
num pkts bytes target prot opt in out source destination
1 3341 191K DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
2 9003 12M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
2 3341 191K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
num pkts bytes target prot opt in out source destination
1 9003 12M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Wenn Sie Linux Bridge verwenden, sollte es nur auf der L2-Ebene funktionieren, daher dachte ich, dass ich in der Lage sein sollte, zu kommunizieren, ohne mir um irgendetwas Sorgen zu machen, aber es war ein Fehler. Linux Bridge funktioniert auch wie L3, einschließlich der Möglichkeit, IP zuzuweisen. Dieses Mal habe ich mit einem Container experimentiert, aber ich gehe davon aus, dass dieses Beispiel das gleiche Problem beim Zuweisen einer virtuellen KVM-Maschine lösen kann. (Nicht verifiziert)
Bei der Durchführung dieser Umfrage erhielten wir verschiedene Umfragekooperationen und Konsultationen von den Menschen um uns herum. Ich möchte diesen Fall annehmen und mich bei Ihnen bedanken.
KVM-Bridge-Netzwerkeinstellungen https://qiita.com/TsutomuNakamura/items/e15d2c8c02586a7ae572#bridge-%E3%83%88%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%81%AEnetfilter-%E3%82%92%E7%84%A1%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B
11.2. Brückennetzwerk mit libvirt https://docs.fedoraproject.org/ja-JP/Fedora/13/html/Virtualization_Guide/sect-Virtualization-Network_Configuration-Bridged_networking_with_libvirt.html