tripoli.cloud/tripoli-netctl/README.md

85 lines
3.3 KiB
Markdown
Raw Permalink Normal View History

# 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é
```