Lorsque j'ai enquêté lors du dépannage du titre, j'ai décidé de l'écrire car il y avait peu d'articles qui mentionnaient de manière inattendue cette question comme critique.
Lorsque j'ai créé un pont Linux sur CentOS7, attribué un conteneur Docker sous celui-ci et confirmé la communication, la communication n'a pas pu être effectuée.
Linux Bridge fonctionne en utilisant un module de noyau appelé bridge, mais sa sécurité est gérée par un module de noyau appelé br_netfilter (dépendance avec bridge), et br_netfilter contrôle la communication en regardant les paramètres iptales. .. Par conséquent, la communication peut être effectuée en effectuant l'une des opérations suivantes.
① Désactiver Bridge Netfilter ② Définir l'autorisation pour iptables
OS:CentOS 7.5 Kernel Ver:3.10.0-862.14.4.el7.x86_64 docker Ver:18.06.1-ce
Tout d'abord, assurez-vous que les conteneurs peuvent communiquer entre eux via docker0, qui est généralement attribué au conteneur docker lorsqu'il est déployé.
Exécutez docker et déployez deux conteneurs.
docker run -d --name cent1 centos/tools:latest /sbin/init
docker run -d --name cent2 centos/tools:latest /sbin/init
Confirmez que le conteneur a démarré normalement avec la commande docker ps.
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
Commencez par vérifier l'association entre la carte réseau du conteneur déployé et la carte réseau de l'hôte docker. La vérification de chaque carte réseau du conteneur Docker est la suivante. eth0 de cent1 est l'index9 de l'hôte docker eth0 de cent2 est l'index11 de l'hôte docker Vous pouvez voir qu'il est lié à.
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
La vérification de la carte réseau de l'hôte docker est la suivante.
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
De plus, si vous vérifiez les informations de Linux Bridge, vous pouvez voir que veth du côté hôte de cent1 et 2 est affecté à docker0 comme indiqué ci-dessous.
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421cc26dd0 no vethc59a2d1
vethfee6857
Ce qui précède peut être résumé comme indiqué dans l'image ci-dessous.
Si vous ignorez le ping de cent1 à cent2 via docker0 et vérifiez la communication, vous pouvez communiquer normalement comme suit.
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
Voici le problème principal. Ensuite, lorsque vous créez un nouveau pont Linux et attribuez un conteneur docker, vérifiez si vous pouvez communiquer comme docker0.
Créez un pont nommé new-bridge1 comme nouveau pont.
brctl addbr new-bridge1
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421cc26dd0 no vethc59a2d1
vethfee6857
new-bridge1 8000.000000000000 no
Après l'avoir créé, démarrez Bridge comme suit.
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
Le NIC du conteneur déployé par docker (pour être exact, le veth correspondant au NIC du conteneur du côté hôte du docker) est dans l'état affecté à docker0. Excluez ces cartes réseau de conteneur du docker 0 pour vérification.
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
Affectez la carte réseau du conteneur au nouveau-pont1 nouvellement créé.
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
En effectuant les opérations jusqu'à ce point, l'état sera comme indiqué dans l'image ci-dessous.
Via le new-bridge1 nouvellement créé, essayez d'envoyer un ping de cent1 à cent2 de la même manière que docker0 plus tôt pour vérifier la communication.
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
Ensuite, contrairement au cas via docker0 précédemment, vous pouvez voir qu'il n'y a pas de communication entre cent1 et cent2.
Tout d'abord, essayez d'obtenir tcpdump sur chaque carte réseau. Deux choses peuvent être vues à partir des résultats ci-dessous. (1) La demande ARP est arrivée normalement de cent1 à cent2, et cent1 a reçu la réponse. ② Le ping a atteint le pont Linux (new-bridge1) mais pas le cent2
NIC de 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 de 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
En ce qui concerne ①, je vérifierai le cache ARP dans chaque conteneur au cas où. Vous pouvez voir que l'adresse MAC du partenaire de communication est écrite normalement.
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 fonctionne en utilisant un module de noyau appelé bridge, mais sa sécurité est gérée par un module de noyau appelé br_netfilter (dépendance avec bridge), et br_netfilter contrôle la communication en regardant les paramètres iptables. Il semble. Par conséquent, la communication via Bridge n'est pas autorisée par défaut, et cela se produit.
$ lsmod | grep br_netfilter
br_netfilter 24576 0
bridge 155648 1 br_netfilter
La communication entre les conteneurs sera possible en prenant l'une des mesures suivantes.
Netfilter, qui contrôle normalement la communication Linux Bridge, est activé, mais La communication peut être réalisée en désactivant intentionnellement cela. De plus, l'activation / la désactivation de Bridge Netfilter est le paramètre de noyau net.bridge.bridge-nf-call-iptables. Peut être défini par.
Vérifiez l'état du filtre Bridge Net Actuellement, 1 est défini et il est dans un état valide.
sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1
changement de réglage Définissez net.bridge.bridge-nf-call-iptables = 0 dans /etc/sysctl.conf et Reflétez les paramètres.
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 fait référence à iptables pour contrôler la communication. Par conséquent, en ajoutant la règle d'autorisation à iptables comme suit Vous pourrez communiquer via le pont Linux. Ici, lors de l'ajout d'une règle avec la commande iptables, en spécifiant un module d'appariement de paquets appelé physdev qui gère l'entrée et la sortie du pont avec -m, il est configuré pour autoriser toutes les communications via Brige.
iptables --Description des commandes de gestion système --Liste des commandes Linux 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
(Omis)
Dans kubernetes, il est spécifié que net.bridge.bridge-nf-call-iptables = 1. Parce que j'ai rencontré ce problème lors de la validation suivante avec kubernetes Ajout de la prise en charge des règles iptables.
Jouez avec Multus https://rheb.hatenablog.com/entry/multus_introduction
À ce stade, une question se pose: "Pourquoi docker0 peut communiquer même s'il s'agit en fait du même pont Linux?" La réponse réside dans les paramètres iptables. docker semble décrire les règles requises pour l'installation et la création de réseau docker dans iptables. Si vous vérifiez les informations de réglage iptables, vous pouvez voir que la communication de docker0 vers l'extérieur et la communication via docker0 sont ACCEPTÉES dans les chaînes FRWARD n ° 5 et 6. De plus, docker définit également NAT pour iptables.
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
Lors de l'utilisation de Linux Bridge, cela ne devrait fonctionner que sur la couche L2, alors j'ai pensé que je devrais pouvoir communiquer sans me soucier de quoi que ce soit, mais c'était une erreur. Linux Bridge fonctionne également comme L3, y compris la possibilité d'attribuer une adresse IP. Cette fois, j'ai expérimenté un conteneur, mais je suppose que cet exemple peut résoudre le même problème lors de l'attribution d'une machine virtuelle KVM. (Non vérifié)
Dans le cadre de cette enquête, nous avons reçu diverses coopérations d'enquête et consultations de la part des personnes qui nous entourent. Je voudrais prendre ce cas et merci.
Paramètres réseau du pont KVM 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. Réseau de pont utilisant libvirt https://docs.fedoraproject.org/ja-JP/Fedora/13/html/Virtualization_Guide/sect-Virtualization-Network_Configuration-Bridged_networking_with_libvirt.html