tuto4: done

This commit is contained in:
nemunaire 2017-11-09 01:30:41 +01:00
commit a476cd8b6d
14 changed files with 643 additions and 331 deletions

View file

@ -1,6 +1,6 @@
\newpage
Le *namespace* `network`
Le *namespace* `network` {#net-ns}
========================
## Introduction
@ -10,7 +10,7 @@ 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 :
environnement qui n'a plus qu'une interface de *loopback* :
<div lang="en-US">
```shell
@ -20,9 +20,13 @@ environnement qui n'a plus que l'interface de loopback :
```
</div>
Qui dit nouvelle pile réseau, dit également que les ports qui étaient assignés
Bien que portant le même nom que l'interface de *loopback* de notre
environnement principal, il s'agit bien de deux interfaces isolées l'une de
l'autre.
Qui dit nouvelle pile réseau, dit également que les ports qui sont 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
possible de lancer un serveur web sans qu'il n'entre en conflit avec celui d'un
autre espace de noms.
@ -31,45 +35,51 @@ autre espace de noms.
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 :
Nous pouvons tout d'abord créer un nouvel espace de nom :
<div lang="en-US">
```shell
42sh$ ip netns add virli
42sh# ip netns add virli
```
</div>
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.
celle que nous avons vue dans
[la première partie sur les *namespaces*](#ns-lifetime) : 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 :
Maintenant que notre *namespace* est créé, nous pouvons regarder s'il contient
des interfaces :
<div lang="en-US">
```sh
42sh$ ip netns exec virli ip link
42sh# ip netns exec virli ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
</div>
Cette commande ne devrait vous montrer que l'interface de *loopback*, car nous
n'avons pour l'instant pas encore attaché la moindre interface.
Cette commande ne nous montre 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 :
<div lang="en-US">
```shell
42sh$ ip netns exec virli ip link set dev lo up
42sh# ip netns exec virli ip link set dev lo up
```
</div>
Si tout se passe bien, vous devriez maintenant pouvoir lancer un `ping` sur
cette interface :
À ce stade, nous pouvons déjà commencer à lancer un `ping` sur cette interface:
<div lang="en-US">
```shell
42sh$ ip netns exec virli ping 127.0.0.1
42sh# ip netns exec virli ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.038 ms
...
```
</div>
@ -86,108 +96,135 @@ type `veth` :
<div lang="en-US">
```
ip link add veth0 type veth peer name veth1
42sh# ip link add veth0 type veth peer name veth1
```
</div>
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`.
donc reçus 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.
l'on place l'une des deux extrêmités dans un autre *namespace* `network`, il
devient alors possible de réaliser un échange de paquets entre les deux.
Pour déplacer `veth1` dans notre *namespace* `virli` :
<div lang="en-US">
```shell
42sh# ip link set veth1 netns virli
42sh# ip link set veth1 netns virli
```
</div>
Il ne reste plus maintenant qu'à assigner une IP à chacune des interfaces :
Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
<div lang="en-US">
```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
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
```
</div>
Testons maintenant que la communication entre les deux passe bient :
Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
[^linkdown]: Il peut être nécessaire d'activer chaque lien, via `ip link set
vethX up`.
<div lang="en-US">
```shell
42sh# ping 10.10.10.42
- et -
42sh# ip netns exec virli ping 10.10.10.41
42sh# ping 10.10.10.42
- et -
42sh# ip netns exec virli ping 10.10.10.41
```
</div>
Il ne reste donc pas grand chose à faire pour fournir Internet à notre
conteneur, via un peu de NAT ou grâce à un pont Ethernet.
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
couches du noyau. Utiliser les interfaces *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.
Il est possible d'attribuer juste une interface de VLAN, si l'on a switch
supportant la technologie [802.1q](https://fr.wikipedia.org/wiki/IEEE_802.1Q).
<div lang="en-US">
```
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
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
```
</div>
### 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
<!-- https://hicu.be/bridge-vs-macvlan -->
Lorsque l'on n'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*.
des quatre modes : *private*, VEPA, *bridge* ou *passthru*.
Quelque soit le mode choisi, les paquets en provenance d'autres machines et à
destination d'un MAC seront délivrés à l'interface possédant la MAC. Les
différences entre les modes se trouvent au niveau de la communication entre les
interfaces.
#### 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.
Dans ce mode, tous les paquets sortants sont directement envoyés sur
l'interface Ethernet de sortie, sans qu'aucun routage préalable n'ait été
effectué. Ainsi, si un paquet est à destination d'un des autres conteneurs de
la machine, c'est à l'équipement réseau derrière la machine de rerouter le
paquet vers la machine émettrice (par exemple un switch
[802.1Qbg](http://www.ieee802.org/1/pages/802.1bg.html)).
Pour construire une nouvelle interface de ce type :
<div lang="en-US">
```
ip link add link eth0 mac0 type macvlan mode vepa
42sh# ip link add link eth0 mac0 type macvlan mode vepa
```
</div>
#### *Private*
À la différence du mode *VEPA*, si un paquet émis par un conteneur à
destination d'un autre conteneur est réfléchi par un switch, le paquet ne sera
pas délivré.
Dans ce mode, on est donc assuré qu'aucun conteneur ne puisse parler à un
conteneur de la même machine.
<div lang="en-US">
```
42sh# ip link add link eth0 mac1 type macvlan mode private
```
</div>
#### *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.
À l'inverse des modes *VEPA* et *private*, les paquets sont routés selon leur
adresse MAC : si jamais une adresse MAC est connue, 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 :
<div lang="en-US">
```
ip link add link eth0 mac1 type macvlan mode bridge
42sh# ip link add link eth0 mac2 type macvlan mode bridge
```
</div>