Systemd-nspawn / config interface virtuelle ethernet avec IP statique

Bonsoir les amis,

Voilà je suis entrain d’expérimenter depuis quelque temps la solution de containerisation native à systemd, systemd-nspawn, et j’ai donc crée un container qui me sert au quotidien comme serveur DNS, ainsi qu’un autre container dans lequel j’ai basardé skype.

Le problème se situe au niveau de la configuration des adresses IP respectives de ces containers en IP fixes. Jusqu’à présent les containers fonctionnaient avec une config DHCP, puis j’ai décidé de me pencher dessus et de mettre tout ça en IP fixe.
Mon pc est un portable, la connexion à la box se fait donc en wifi, et je n’ai pas configuré de bridge (délicat à configurer avec une connexion wifi). Les containers eux, que ce soit en DHCP ou IP fixe, sont connectés par l’intermédiaire d’interfaces ethernet virtuelles (–network-veth), dont une partie se trouve à l’extérieur du container, donc côté hôte, et l’autre partie se trouve dans le container. Jusque là pas de problème…

Le problème vient lorsque je place le tout en adresses IP fixes, alors seul le 1er container démarré a un ping vers la passerelle (ma box) et donc vers l’extérieur, en gros il capte la connexion pour lui tout seul et les autres containers ne sont pas capables de communiquer avec l’extérieur…
Donc en fait je ne sais pas trop s’il s’agit d’un bug inhérent à systemd-nspawn, ou bien d’un problème de configuration de ma part… (Ça ressemble au problème qui existe/existait avec les jails sous BSD et l’option “veth” pour ceux qui connaissent).

Exemple fichier config côté hôte :

gogi@blabla:~$ cat /etc/systemd/network/80*
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This network file matches the host-side of the virtual Ethernet link
# created by systemd-nspawn's --network-veth switch. See systemd-nspawn(1) for
# details.

[Match]
Name=ve-bind9
Driver=veth

[Network]
# Default to using a /28 prefix, giving up to 13 addresses per container.
Address=192.168.1.101/24
#Gateway=192.168.0.254
#LinkLocalAddressing=yes
IPMasquerade=yes
LLDP=yes
EmitLLDP=customer-bridge
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This network file matches the host-side of the virtual Ethernet link
# created by systemd-nspawn's --network-veth switch. See systemd-nspawn(1) for
# details.

Exemple fichier config côté container :

 bind9@bind9:~$ cat /etc/systemd/network/80*
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This network file matches the container-side of the virtual Ethernet link
# created by systemd-nspawn's --network-veth switch. See systemd-nspawn(1) for
# details.

[Match]
Virtualization=container
Name=host0

[Network]
Address=192.168.1.1/24
Gateway=192.168.1.101
LinkLocalAddressing=yes
LLDP=yes
EmitLLDP=customer-bridge

Ça commence à me taper sur le système sérieusement cette histoire, alors avant d’écrire à L. Poettering, je suis preneur de toute suggestion :smiley:

Je ne connais rien aux containers de systemd, mais as-tu vérifié la cohérence des adresses et des tables de routage de l’hôte et de chaque container ?

Ce dispositif crée-t-il sur l’hôte une seule interface virtuelle pour communiquer avec tous les containers ou bien une interface distincte pour communiquer avec chaque container ? Dans le second cas, si ces interfaces ne sont pas pontées ensemble, chaque paire d’interfaces hôte-container constitue un réseau séparé et doit avoir un sous-réseau IP distinct.

C’est à dire? :frowning:
En fait je ne suis pas un expert en matière de réseau.

Alors lorsqu’on utilise l’option “–network-veth”, au lancement du container systemd crée une paire d’interfaces virtuelles dont l’une sera côté hôte (et elle sera nommée “ve-*”) et l’autre côté container (nommée systématiquement “host0”).
Pour donner un exemple, chez moi ça se présente comme ça :

  • couple “ve-bind9 / host0” pour le container DNS
  • couple “ve-skype / host0” pour le container skype

avec les fichiers de config “*.network” correspondants selon les modèles dans mon 1er post.

Bon alors en fait, il semblerait que j’ai réussi à faire fonctionner le schmilblick, et ce en les faisant fonctionner sur des réseaux distincts, par exemple :

  • réseau 192.168.1.0/24 pour le container bind9
  • réseau 192.168.2.0/24 pour le container skype

Mais j’aimerai comprendre pourquoi ça ne peut pas fonctionner simplement sur le même réseau? Par exemple mon pc hôte, mon imprimante et d’autres appareils sont eux sur le même réseau (192.168.0.0/24).
Est-ce que je pourrai eventuellement placer les containers sur ce dernier réseau mais en changeant le masque?

Parce que chaque paire d’interfaces virtuelles est un réseau distinct, comme je l’ai expliqué. Tu peux transposer cela a des interfaces et des liens réseau point à point physiques, ou à des VPN. C’est la base du routage IP.
L’examen des adresses et tables de routage (ip addr ; ip route) l’aurait mis en évidence.

ve-bind9 = 192.0.2.1/24 signifie que ve-bind9 a l’adresse 192.0.2.1 et tout le reste du réseau 192.0.2.0/24 est joignable par ve-bind9.
Si tu ajoutes ensuite
ve-skype = 192.0.2.2/24 cela signifie que ve-skype a l’adresse 192.0.2.2 et tout le reste du réseau 192.0.2.0/24 est joignable par ve-skype.
Hein ? Quoi ? Alors 192.0.2.3 est joignable par ve-bind9 ou par ve-skype ? Le noyau n’a aucun moyen de le savoir, il a une chance sur deux de se tromper.

Si tu veux que tous ces segments soient dans un même réseau, il faut ponter les interfaces ve-* ensemble sur l’hôte et attribuer une configuration IP au pont et non à ces interfaces.

J’ai du mal à comprendre cette notion de réseau distinct dans ce cas. En fait ce que je ne comprends pas c’est pourquoi ça fonctionne dans le cas de mes appareils domestiques qui sont sur le même réseau et pas dans le cas de ces couples.

En fait ce que moi je vois, l’image que je me fais, c’est que par exemple et en reprenant ton exemple :

  • mon pc hôte est connecté via l’interface wifi, son IP est 192.168.0.2/24, donc tout le reste du réseau 192.168.0.0/24 est joignable par cette interface?
  • mon imprimante est connectée en ethernet à ma box, son IP est 192.168.0.250/24, donc tout le reste du réseau 192.168.0.0/24 est joignable par cette interface également?

en fait je ne saisis pas quelle est la différence entre ces interfaces et les interfaces ve-* qui fait que ça marche pour celles-ci et pas pour les interfaces ve-*

Imagine que tu as plusieurs box, et ton PC a plusieurs interfaces ethernet ou wifi, chacune étant connectée à une box différente. L’imprimante est connectée à une des box. Si tu configures chaque box, chaque interface de ton PC et l’imprimante avec le même sous-réseau IP, que crois-tu qu’il va se passer ?

Aucune idée, je n’arrive pas à faire l’analogie dans ma tête, c’est complètement confus pour moi.

J’essaie toujours de faire l’analogie entre réseau informatique et adresses postales pour comprendre le fonctionnement. Par exemple je m’imagine le réseau comme étant une ville, le sous-réseau étant une rue, la box ou les box comme étant une maison ou un appartement de cette rue, et enfin les différentes pièces comme etant les interfaces derriere la box…

Dans ton analogie les interfaces seraient plutôt les portes d’entrée des maisons (qui seraient des hôtes), faisant le lien entre les maisons et les rues.

Chaque segment réseau, donc chaque paire d’interfaces hôte-container équivaut à une rue, de même que le LAN de la box. Et le sous-réseau IP d’un segment réseau équivaut au nom de la rue.

Maintenant imagine que plusieurs rues de la ville portent le même nom (plusieurs segments réseau ayant le même sous-réseau IP). Cela serait un beau bazar pour s’orienter ou distribuer le courrier, n’est-ce pas ?

Punaise je saisis toujours pas l’analogie… :angry:
De plus mon analogie n’est pas bonne, je reprends…

Supposons que j’ai une grande propriété et que ma box soit le portail de cette propriété :

  • Tout ce qui est à l’extérieur de ce portail est dans le domaine public
  • Tout ce qui est sur ma propriété est mon “réseau local”.
  • La box faisant donc le lien entre le monde extérieur et ce dernier.
  • Ce portail (la box) a une adresse vue de l’extérieur (83.x.x.x), ce qui correspondrait à mon adresse postale ; et une adresse “intérieure” (par ex. 192.168.0.254/24).

Maintenant supposons que sur cette propriété il y ait plusieurs maisons…, et plusieurs allées/chemins qui font les liens maison-maison et maison-portail :

  • les allées qui font la liaison maison-maison et maison-portail correspondraient globalement au réseau entier (192.168.0.0/24) puisque tout ce monde est “sur le même réseau”, c’est en quelque sorte la toile locale…
  • chaque maison a une porte d’entrée, qui correspondrait à l’interface réseau, avec son adresse (192.168.0.X/24)
  • l’une des maisons est mon pc hôte, sa porte d’entrée/sortie principale (interface wifi) a donc pour adresse par exemple 192.168.0.2/24.
  • on peut rajouter un autre exemple de maison qui serait l’équivalent de mon imprimante, dont la porte d’entrée/sortie aurait pour adresse 192.168.0.10/24

Ensuite, et c’est là que ça se corse : à l’intérieur de la maison qui correspond à mon pc hôte, il y a plusieurs pièces. On peut imaginer que la pièce principale représente mon système hôte, et que les pièces adjacentes (on va dire les chambres) correspondent à mes containers…

  • la pièce principale a accès à internet directement via la porte d’entrée principale dénommée ci-dessus.
  • les chambres n’ont pas directement accès ni au réseau local, ni au réseau extérieur, il leur faut d’abord passer par la porte d’entrée? (puisque de toute façon si pas de connexion wifi alors les containers n’auront pas non plus d’accès réseau tout autant que le système hôte…)
  • les portes des chambres seraient donc la paire ve-/host0, avec l’interface ve- côté pièce principale, et host0 côté intérieur à la chambre?

C’est là que je ne comprends pas, si la connexion sort de toute façon par l’interface wifi qui elle est adressée sur le sous-réseau 192.168.0.0/24 et que les containers se trouvent sur ma machine qui est derrière cette interface, comment ça peut fonctionner si j’adresse ces machines avec des sous-réseaux totalement différents (192.168.x.0/24 par exemple, ça pourrait très bien être en 10.x.x.x aussi…), mais ça ne fonctionne pas si j’adresse ces machine sur le même sous-réseau que l’interface wifi…
En quelque sorte mon interface wifi devrait être la passerelle entre la box et les interfaces ve-* de mes containers, non?
Pareil je ne comprends pas pourquoi ça marche alors quand j’adresse plusieurs appareils (pc, imprimante, …) sur le même sous-réseau, en l’occurrence le LAN de la box. En fait je me fais l’idée que la box est en amont de tout ce monde, et que donc toutes les interfaces devraient être sur le même sous-réseau que la box.

Il doit y avoir quelque chose qui m’échappe terriblement dans cette notion d’interface virtuelle veth…

Bonjour Gogi, Pascal,

Gogi, au cas où cela pourrait t’aider, j’ai peut-être un autre exemple plus simple.
Ce problème n’est pas strictement équivalent au tien. Mais il va te donner une idée de “l’aide” en terme de configuration, qu’il faut apporter au système afin qu’il sache comment lever le doute.

J’ai une fois hébergé quatre sites web sur un serveur physique (web public) dont j’avais l’administration.
C’était une première pour moi. Il y avait 4 noms de domaines différents. Ils avaient tous une carte réseau hardware dédiée, chacune avec une IP publique. Les 4 IP étaient du même pool. Disons arbitrairement que je voulais que les sites répondent ainsi :
www.toto.com 68.2.4.251 - 255.255.255.248 (ou 29 bits)
www.tata.com 68.2.4.252 - 255.255.255.248 (ou 29 bits)
www.titi.com 68.2.4.253 - 255.255.255.248 (ou 29 bits)
www.tutu.com 68.2.4.254 - 255.255.255.248 (ou 29 bits)

Et bien lorsque je lançais une page web vers tata.com, titi.com ou tutu.com, j’avais invariablement le site toto.com qui apparaissait. Gênant… car les noms de domaines en provenance des DNS renvoyaient les bonnes IP pour chaque domaine. Mais le kernel traitait toutes les requêtes, quelle que soit la carte réseau visée, et renvoyait invariablement la page du premier site web.

Il m’a suffi de renseigner le fichier host en faisant correspondre chaque domaine avec l’IP de la carte réseau que je souhaitais affecter à chacun et tout est rentré dans l’ordre.
En renseignant le host, j’ai simplement indiqué au système quoi faire en cas de requête vers les IP supplémentaires.

Pour systemd-nspawn, je vais faire une hypothèse qui vient de ma ‘modeste’ expérience de la virtualisation sur VMWare et VirtualBox.

Dans un réseau, tu l’as dit (et tu as raison), il y a plusieurs machines qui se partagent son utilisation. Chaque machine est physique. Elle accède à ce réseau en direct. Donc il n’y a aucun bridge implémenté ou NAT effectué par le système pour que les paquets entrent ou sortent. (J’ai bien dit au niveau unique de la machine.)

Je suppute avec assez de certitude que tes containers systemd créent une véritable interface virtuelle et non un alias IP. Cela semble logique puisque un container peut être assimilé à un mini système, n’est-ce pas ?

D’un point de vue “graphique”, imagine que chaque container contient SA carte réseau et SON propre pont avec sa propre définition de réseau. Imagine le container comme un PC complet avec son réseau INCLUS et non comme un simple container applicatif. Imagine que chaque container est autonome, relié à systemd.
Si systemd constate que deux containers utilisent le même réseau, il va prendre par défaut le premier ?, le premier lancé ?, celui qui a éventuellement une priorité sur l’autre ?.. mais les deux ne marcheront jamais ensemble.

Tu l’as prouvé en séparant complètement les deux réseaux pour chaque container :wink:
Au début, tes containers revendiquaient la même “passerelle d’interface virtuelle”.
Vu par le gestionnaire du système (en l’occurrence systemd) c’est un peu comme à l’image d’un conflit d’IP sur un réseau classique. Les paquets s’éparpillent, se perdent et ça fonctionne mal.

Voila, c’était ma modeste (et trop longue analyse) :wink:

Pour une meilleure analogie il faudrait ajouter des couloirs reliant la pièce principale et les chambres. Dans ton cas chaque chambre est au bout d’un couloir différent.

Mais cette analogie reste limitée car elle ne décrit qu’un environnement figé alors que car la clé pour comprendre, c’es le routage IP qui est un processus actif. Donne-moi la table de routage de l’hôte, de deux containers et de la box ou de l’imprimante, et je t’explique comment ça marche.

Une passerelle est une machine, pas une interface.

Non, le fait que les interfaces sont virtuelles ne change strictement rien à l’affaire. Tu peux transposer à des machines, des interfaces et des liaisons physiques et ça fonctionnera de la même façon.

Tu utilises un container systemd. Tu oublies la “couche” systemd au milieu. Je pense qu’il agit comme un gestionnaire de VM. C’est systemd qui gère le trafic vers et en provenance de ton interface réseau et non chaque container applicatif qui fait sa vie et se permet l’accès direct aux ressources physiques.

Je ne vois pas bien en quoi c’est censé l’aider à comprendre. Systemd n’a rien à voir là-dedans. C’est du pur routage IP.

@speedstream,
Tout d’abord merci pour ton intervention :wink:

Ça c’est une solution lorsque ta connexion internet fonctionne, ou que tu arrives à ping-er tes machines, chez moi comme le dit Pascal c’est nu problème de routage IP pur, c’est à dire que même en renseignant le fichier host ça ne marcherait pas.
Et puis bon là tu as 4 machines, je te vois mal faire ça avec un parc de plusieurs machines, et qui plus est si tu es un jour amené à changer les IP bonjour le boulot :smiley:

Non mais c’est sûr, je dois louper quelque chose dans le fonctionnement des interfaces virtuelles, ou bien je ne me schématise pas leur fonctionnement comme il faudrait dans ma tête ce qui fait que je ne comprends pas…

Table de routage de l’hôte :

gogi@blabla:~$ netstat -arn
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
0.0.0.0         192.168.0.254   0.0.0.0         UG        0 0          0 wlp2s0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 wlp2s0
192.168.0.0     0.0.0.0         255.255.255.0   U         0 0          0 wlp2s0
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 ve-bind9

gogi@blabla:~$ ip route
default via 192.168.0.254 dev wlp2s0 proto static metric 600 
169.254.0.0/16 dev wlp2s0 scope link metric 1000 
192.168.0.0/24 dev wlp2s0 proto kernel scope link src 192.168.0.2 metric 600 
192.168.1.0/24 dev ve-bind9 proto kernel scope link src 192.168.1.101 

Table de routage du container bind :

bind9@bind9:~$ netstat -arn
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
0.0.0.0         192.168.1.101   0.0.0.0         UG        0 0          0 host0
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 host0

bind9@bind9:~$ ip route
default via 192.168.1.101 dev host0 proto static 
192.168.1.0/24 dev host0 proto kernel scope link src 192.168.1.1 

Table de routage du container skype :

gogi@skype:~$ netstat -arn
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
0.0.0.0         192.168.2.101   0.0.0.0         UG        0 0          0 host0
192.168.2.0     0.0.0.0         255.255.255.0   U         0 0          0 host0

gogi@skype:~$ ip route
default via 192.168.2.101 dev host0 proto static 
192.168.2.0/24 dev host0 proto kernel scope link src 192.168.2.1 

Table de routage du container “image” à partir duquel je fais les clones pour mes machines :

gogi@sidtemp:~$ netstat -arn
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
0.0.0.0         192.168.251.101 0.0.0.0         UG        0 0          0 host0
192.168.251.0   0.0.0.0         255.255.255.0   U         0 0          0 host0

gogi@sidtemp:~$ ip route
default via 192.168.251.101 dev host0 proto static 
192.168.251.0/24 dev host0 proto kernel scope link src 192.168.251.1 

Par contre je ne sais pas comment faire pour obtenir la table de route de la box ou de l’imprimante… :confused:

@PascalHambourg tu m’as oublié :stuck_out_tongue:

Non, mais expliquer le fonctionnement du routage IP demande d’y consacrer un certain temps d’affilée qui me manque en ce moment. Je n’écris pas vite, et je n’ai que des bribes de temps libre par ci par là pour faire des réponses courtes.

Ah ok pas de soucis :wink: Je me suis dit qu 'avec toutes les réponses tu avais peut-être sauté le sujet, ça peut arriver.
C’est pas grave il n’y a pas le feu, à l’occasion quand tu pourras tu compléteras avec l’explication que tu voulais me donner, en attendant j’essaie de lire des cours sur la toile pour y comprendre plus clair de mon côté.