2016-10-19 03:24:05 +00:00
|
|
|
\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 :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
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
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +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 :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
42sh$ ip netns add virli
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
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 :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```sh
|
|
|
|
42sh$ ip netns exec virli ip link
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
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 :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
42sh$ ip netns exec virli ip link set dev lo up
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
Si tout se passe bien, vous devriez maintenant pouvoir lancer un `ping` sur
|
|
|
|
cette interface :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
42sh$ ip netns exec virli ping 127.0.0.1
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
## *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` :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```
|
|
|
|
ip link add veth0 type veth peer name veth1
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
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` :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
42sh# ip link set veth1 netns virli
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
Il ne reste plus maintenant qu'à assigner une IP à chacune des interfaces :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
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
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
Testons maintenant que la communication entre les deux passe bient :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```shell
|
|
|
|
42sh# ping 10.10.10.42
|
|
|
|
- et -
|
|
|
|
42sh# ip netns exec virli ping 10.10.10.41
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```
|
|
|
|
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
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
### 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 :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```
|
|
|
|
ip link add link eth0 mac0 type macvlan mode vepa
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
#### *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 :
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
<div lang="en-US">
|
2016-10-19 03:24:05 +00:00
|
|
|
```
|
|
|
|
ip link add link eth0 mac1 type macvlan mode bridge
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
</div>
|
2016-10-19 03:24:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
## Aller plus loin
|
|
|
|
|
|
|
|
Pour approfondir les différentes techniques de routage, je vous
|
|
|
|
recommande cet article :
|
|
|
|
[Linux Containers and Networking](https://blog.flameeyes.eu/2010/09/linux-containers-and-networking).
|