85 lines
3.3 KiB
Markdown
85 lines
3.3 KiB
Markdown
|
|
# tripoli-netctl
|
||
|
|
|
||
|
|
Labo pédagogique un-seul-poste sur les network namespaces Linux et la
|
||
|
|
crate `rtnetlink`. **Ne pilote aucun service de production** :
|
||
|
|
tripoli-edge et tripoli-api continuent de tourner nativement sur l'hôte,
|
||
|
|
dans le namespace racine. Ce n'est pas un CNI, pas un orchestrateur -
|
||
|
|
juste une démonstration, sur une seule machine, de ce qui se passe sous
|
||
|
|
le capot quand un outil comme Docker ou Kubernetes isole un service en
|
||
|
|
réseau.
|
||
|
|
|
||
|
|
## Ce que fait `create <name>`
|
||
|
|
|
||
|
|
1. Crée un network namespace nommé `<name>` (`rtnetlink::NetworkNamespace::add`,
|
||
|
|
équivalent de `ip netns add` - fork + `unshare(CLONE_NEWNET)` +
|
||
|
|
bind-mount de `/proc/self/ns/net` sur `/run/netns/<name>`).
|
||
|
|
2. Crée une paire veth (`tv-<name>h` / `tv-<name>p`, noms tronqués à 6
|
||
|
|
caractères alphanumériques pour respecter la limite de 15 caractères
|
||
|
|
des interfaces Linux).
|
||
|
|
3. Déplace `tv-<name>p` dans le namespace créé (`setns_by_fd`).
|
||
|
|
4. Adresse le côté hôte (`10.200.<subnet-id>.1/30`) et l'active.
|
||
|
|
5. Depuis un thread OS dédié qui fait `setns()` vers le namespace cible,
|
||
|
|
adresse le côté namespace (`10.200.<subnet-id>.2/30`), l'active, et
|
||
|
|
active `lo` (qui démarre toujours *down* dans un namespace neuf -
|
||
|
|
détail facile à oublier, source classique de "ça ne marche pas" dans
|
||
|
|
ce genre de labo).
|
||
|
|
|
||
|
|
Chaque étape est journalisée en JSON sur stderr et dans
|
||
|
|
`/var/log/tripoli-netctl/audit.log`.
|
||
|
|
|
||
|
|
## Pourquoi un thread dédié, pas `tokio::task::spawn_blocking`
|
||
|
|
|
||
|
|
`setns()` change la namespace réseau du **thread appelant**, pour toute
|
||
|
|
sa durée de vie. Les threads de `spawn_blocking` sont mis en pool et
|
||
|
|
réutilisés par tokio pour d'autres tâches bloquantes : y laisser un
|
||
|
|
thread « coincé » dans un namespace réseau casserait silencieusement
|
||
|
|
n'importe quelle tâche bloquante ultérieure qui tomberait dessus. Un
|
||
|
|
`std::thread::spawn` dédié, jamais réutilisé, élimine le risque.
|
||
|
|
|
||
|
|
## `destroy <name>`
|
||
|
|
|
||
|
|
Supprime le côté hôte de la veth - le noyau supprime automatiquement le
|
||
|
|
pair, même déplacé dans un autre namespace, dès qu'un des deux bouts
|
||
|
|
disparaît - puis démonte/supprime le fichier de namespace.
|
||
|
|
|
||
|
|
## `list`
|
||
|
|
|
||
|
|
Énumère `/run/netns` et vérifie, pour chacun, la présence de la veth
|
||
|
|
hôte associée.
|
||
|
|
|
||
|
|
## Utilisation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
sudo ./tripoli-netctl create demo --subnet-id 5
|
||
|
|
sudo ./tripoli-netctl list
|
||
|
|
sudo ./tripoli-netctl destroy demo
|
||
|
|
```
|
||
|
|
|
||
|
|
Root est requis (namespaces + netlink privilégié) - vérifié explicitement
|
||
|
|
au démarrage plutôt que de laisser échouer la première opération avec un
|
||
|
|
message obscur.
|
||
|
|
|
||
|
|
## Limites assumées (v1)
|
||
|
|
|
||
|
|
- Pas d'allocation automatique de sous-réseau : `--subnet-id` est
|
||
|
|
explicite, une collision entre deux services donnerait une erreur
|
||
|
|
claire plutôt qu'une allocation silencieuse qui la masquerait.
|
||
|
|
- IPv4 uniquement.
|
||
|
|
- Un seul veth par service - pas de topologie plus complexe (bridge,
|
||
|
|
plusieurs interfaces).
|
||
|
|
|
||
|
|
## Vérifié
|
||
|
|
|
||
|
|
```
|
||
|
|
$ sudo tripoli-netctl create demo1 --subnet-id 5
|
||
|
|
service 'demo1' prêt :
|
||
|
|
hôte : tv-demo1h 10.200.5.1/30 (namespace racine)
|
||
|
|
ns : tv-demo1p 10.200.5.2/30 (namespace demo1, /run/netns/demo1)
|
||
|
|
|
||
|
|
$ ping -c 2 10.200.5.2 # depuis la racine, vers le namespace
|
||
|
|
2 packets transmitted, 2 received, 0% packet loss
|
||
|
|
|
||
|
|
$ sudo tripoli-netctl destroy demo1
|
||
|
|
service 'demo1' détruit # veth et namespace bien supprimés, vérifié
|
||
|
|
```
|