virli/tutorial/4/networkns.md

5.3 KiB

\newpage

Le namespace network

Introduction

L'espace de noms network, comme son nom l'indique permet de virtualiser tout ce qui est en lien avec le réseau : les interfaces, les ports, les routes, les règles de filtrage, etc.

En entrant dans un nouvel espace de nom network, on se retrouve dans un environnement qui n'a plus que l'interface de loopback :

42sh# unshare -n ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Qui dit nouvelle pile réseau, dit également que les ports qui étaient assignés dans l'espace principal, ne le sont plus dans le conteneur : il est donc possible de lancer un serveur web sans qu'il entre en conflit avec celui d'un autre espace de noms.

Premiers pas avec ip netns

La suite d'outils iproute2 propose une interface simplifiée pour utiliser le namespace network : ip netns.

Tout d'abord, nous allons créer un nouvel espace de nom :

42sh$ ip netns add virli

La technique utilisée ici pour avoir des namespaces nommés est la même que celle que nous avons vu dans la première partie sur les namespaces : via un mount --bind dans le dossier /var/run/netns/. Cela permet de faire persister le namespace malgré le fait que plus aucun processus ne s'y exécute.

Maintenant que notre namespace est créé, voyons s'il contient des interfaces :

42sh$ ip netns exec virli ip link

Cette commande ne devrait vous montrer que l'interface de loopback, car nous n'avons pour l'instant pas encore attaché la moindre interface.

D'ailleurs, cette interface est rapportée comme étant désactivée, activons-là via la commande :

42sh$ ip netns exec virli ip link set dev lo up

Si tout se passe bien, vous devriez maintenant pouvoir lancer un ping sur cette interface :

42sh$ ip netns exec virli ping 127.0.0.1

Virtual Ethernet

Étant donné qu'une interface réseau ne peut être présente que dans un seul espace de noms à la fois, il n'est pas bien pratique d'imposer d'avoir une interface physique par conteneur, d'autant plus si l'on a plusieurs centaines de conteneurs à gérer.

Une technique couramment employée consiste à créer une interface virtuelle de type veth :

ip link add veth0 type veth peer name veth1

Une interface veth se comporte comme un tube bidirectionnel : tout ce qui entre d'un côté sort de l'autre et inversement. La commande précédente a donc créé deux interfaces veth0 et veth1 : les paquets envoyés sur veth0 sont donc reçu par veth1 et les paquets envoyés à veth1 sont reçus par veth0.

Dans cette configuration, ces deux interfaces ne sont pas très utiles, mais si l'on place l'une des deux extrêmité dans une autre namespace network, il devient alors possible de réaliser un échange de paquet entre les deux.

Pour déplacer veth1 dans notre namespace virli :

42sh# ip link set veth1 netns virli

Il ne reste plus maintenant qu'à assigner une IP à chacune des interfaces :

42sh# ip netns exec virli ip a add 10.10.10.42/24 dev veth1
42sh# ip a add 10.10.10.41/24 dev veth0

Testons maintenant que la communication entre les deux passe bient :

42sh# ping 10.10.10.42
- et -
42sh# ip netns exec virli ping 10.10.10.41

Il ne reste donc pas grand chose à faire pour fournir Internet à notre conteneur, via un peu de NAT ou grâce à un pont Ethernet.

Les autres types d'interfaces

Le bridge ou le NAT obligera tous les paquets à passer à travers de nombreuses couches du noyau. Utiliser les interface veth est plutôt simple et disponible partout, mais c'est loin d'être la technique la plus rapide ou la moins gourmande.

VLAN

Il est possible d'attribuer juste une interface de VLAN, si l'on a switch les supportant.

42sh# ip link add link eth0 name eth0.100 type vlan id 100
42sh# ip link set dev eth0.100 up
42sh# ip link set eth0.100 netns virli

MACVLAN

Lorsque l'on a pas assez de carte ethernet et que le switch ne supporte pas les VLAN, le noyau met à disposition un routage basé sur les adresses MAC : le MACVLAN. S'il est activé dans votre noyau, vous allez avoir le choix entre l'un des deux modes : VEPA ou bridge.

VEPA

Dans ce mode, tous les paquets sortant sont directement envoyé sur l'interface ethernet de sortie, sans qu'aucun routage préalable n'est été effectué. Ainsi, si un paquet est à destination d'un des autres conteneur de la machine, c'est à l'équipement réseau derrière la machine de rerouter le paquet vers la machine émetrice.

Pour construire une nouvelle interface de ce type :

ip link add link eth0 mac0 type macvlan mode vepa

Bridge

À l'inverse du mode VEPA, les paquets sont routés selon leur adresse MAC : si jamais une adresse MAC est connuee, le paquet est délivré à l'interface MACVLAN correspondante ; dans le cas contraire, le paquet est envoyé sur l'interface de sortie.

Pour construire une nouvelle interface de ce type :

ip link add link eth0 mac1 type macvlan mode bridge

Aller plus loin

Pour approfondir les différentes techniques de routage, je vous recommande cet article : Linux Containers and Networking.