From 642a9c2f7ae3ff0470045b7503ca1b6a23f59c60 Mon Sep 17 00:00:00 2001 From: GnomeZworc Date: Tue, 25 Aug 2026 23:56:55 +0200 Subject: [PATCH 1/2] f-33: doc: update release note Signed-off-by: GnomeZworc --- release_notes/0.1.0.md | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/release_notes/0.1.0.md b/release_notes/0.1.0.md index be3d69c..d8b1bab 100644 --- a/release_notes/0.1.0.md +++ b/release_notes/0.1.0.md @@ -11,23 +11,48 @@ Première version stable de **syonad/two**, orchestrateur réseau et VM mono-nœ avec `error` en cas d'échec d'exécution ; suppression autorisée depuis `running` et `error` - Migration au démarrage de l'agent : toute ressource restée dans un état transitoire est basculée en `error`, la file de travail étant en mémoire +- Arrêt gracieux : serveurs HTTP, puis drainage des workers, puis fermeture de la base. Si le + budget d'arrêt est dépassé, la base n'est **pas** fermée — la rejouer au démarrage suivant vaut + mieux que de la fermer sous un écrivain concurrent **Réseau** - VPC isolés par network namespace, subnets en mode `vxlan` ou `bridge` -- DHCP par subnet via instances `dnsmasq@` dédiées, entrées ip→mac en base -- Route par défaut et route du VPC distribuées par DHCP (`default_route` par subnet) +- DHCP par subnet via instances `dnsmasq@` dédiées, entrées ip→mac en base, fichier de baux propre + à chaque instance +- Toutes les routes sont distribuées par l'option 121 : route vers le serveur de metadata, route du + VPC, et route par défaut. L'option 3 reste émise pour les clients qui n'implémentent pas la 121 +- `default_route` choisit le **next-hop** de la route par défaut : l'`interface_ip` du subnet par + défaut, sinon la `gateway` fournie ou celle déduite de l'host +- `gateway` optionnelle par subnet, non validée par l'agent - Isolation du DHCP par ebtables, redirection du service de metadata par iptables **Machines virtuelles** +- Plusieurs interfaces réseau par VM, dans un même VPC. La position de l'interface détermine son + slot PCI, donc son nom dans le guest ; **exactement une** interface est primaire et porte la route + par défaut et le serveur de metadata - Démarrage QEMU/KVM avec plusieurs disques et ordre de démarrage explicite - Amorçage UEFI optionnel (OVMF), avec magasin de variables par VM - Serveur de metadata cloud-init par VM (`metadata@`), sans base de données dans le processus - Les VMs survivent à l'arrêt de l'agent : QEMU est lancé hors de son cgroup via `systemd-run` +**Metadata cloud-init** + +- Objet `metadata` dans la création de VM : `password`, `sshkey`, `user_data` +- `user_data` transmis en base64, ce qui autorise les charges gzip+base64 ; un encodage invalide est + refusé en 400, jamais servi vide en silence +- Un document fourni est servi **verbatim**, un document absent retombe sur le modèle par défaut, et + un document explicitement vide est servi vide — les trois cas sont distincts +- Le compte `syonad` n'est créé que si un mot de passe ou une clé est fourni, et reste verrouillé + quand seule une clé l'est. L'agent n'impose aucune modification du compte root + **Exploitation** +- Watchdog de cohérence : vérifie périodiquement que les ressources `running` existent encore sur + le système et signale les écarts. Lecture seule, il ne répare jamais. Désactivé par défaut, + activé dans le fichier d'exemple +- API d'administration en lecture seule sur la boucle locale, pour inspecter la base - Métriques Prometheus : nombre de VPC, subnets et VMs par état - `deploy.sh` avec profils d'host (`kvm`), préparation système déléguée à `bootstrap_kvm.sh` - Units systemd et scripts publiés comme assets de release, avec manifeste `SHA256SUMS` @@ -39,7 +64,17 @@ Première version stable de **syonad/two**, orchestrateur réseau et VM mono-nœ - Pas de rollback en cas d'échec partiel d'une création — les ressources réseau orphelines ne sont pas nettoyées automatiquement - API destinée à un appelant logiciel : la validation de cohérence des entrées (CIDR, VXLAN - ID, format des noms) est à la charge de l'appelant + ID, format des noms, joignabilité d'une `gateway`) est à la charge de l'appelant +- Le mode de subnet `public_ip` est accepté par l'API et par la sélection des routes DHCP, mais sa + mise en place réseau n'existe pas : créer un tel subnet échoue explicitement +- Les interfaces multiples d'une VM doivent appartenir au même VPC +- Le réseau des guests est configuré par le DHCP seul ; le `network-config` cloud-init servi est + sans effet et ne doit pas être « corrigé » sans mesurer l'impact sur les VM existantes +- Modifier les routes d'une VM déjà démarrée ne prend effet qu'au renouvellement du bail, soit + jusqu'à six heures plus tard, ou à son redémarrage +- `vm//password` contient un **hash**, stocké en clair en base et restitué par l'API + d'administration ; celle-ci est désactivée par défaut et n'écoute que sur la boucle locale +- L'API de l'agent n'a pas d'authentification : son exposition réseau doit être restreinte - Les packages `internal/netns`, `netif`, `qemu`, `vm`, `iptables` et `ebtables` ne fonctionnent que sous Linux From c47577db2109309147dbe450022118e09f63f514 Mon Sep 17 00:00:00 2001 From: GnomeZworc Date: Tue, 25 Aug 2026 23:57:11 +0200 Subject: [PATCH 2/2] f-33: doc: update README Signed-off-by: GnomeZworc --- README.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0467392..c99eb4c 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,80 @@ -# syonad +# syonad/two -A simple but powerful orchestrator, designed to be easy to use and API-first. +Orchestrateur réseau et machines virtuelles mono-nœud, pensé pour être piloté par un logiciel +plutôt que par un humain. -## deployer +Il expose une API HTTP qui crée des **VPC** — isolés par network namespace —, des **subnets** — +en VXLAN ou attachés à un bridge existant — et des **VM** QEMU/KVM raccordées à ces subnets, avec +DHCP, routage et metadata cloud-init fournis automatiquement. +## Installation + +```bash +curl -O https://git.g3e.fr/syonad/two/raw/branch/main/scripts/deploy.sh +bash ./deploy.sh -t 0.1.0 -i ``` -curl 'https://git.g3e.fr/syonad/two/raw/branch/main/scripts/deploy.sh' -O -bash deploy.sh -mv deploy.sh /opt/two/bin/ -curl 'https://git.g3e.fr/syonad/two/raw/branch/main/systemd/agent.service' -o '/etc/systemd/system/agent.service' -curl 'https://git.g3e.fr/syonad/two/raw/branch/main/systemd/dnsmasq@.service' -o '/etc/systemd/system/dnsmasq@.service' -curl 'https://git.g3e.fr/syonad/two/raw/branch/main/systemd/metadata@.service' -o '/etc/systemd/system/metadata@.service' -systemctl daemon-reload +`deploy.sh` se met à jour lui-même depuis la branche, télécharge binaires, units systemd et +scripts depuis la release, et les vérifie contre le manifeste `SHA256SUMS`. Le drapeau `-i` +prépare l'host : paquets, module `br_netfilter`, `sysctl`, et bridges. -modprobe br_netfilter -echo br_netfilter > /etc/modules-load.d/br_netfilter.conf +Options utiles : + +| Option | Effet | +|---|---| +| `-t ` | déployer une release donnée | +| `-b ` | déployer depuis une branche au lieu d'une release | +| `-i` | préparer l'host (paquets, noyau, réseau) | +| `-u ` | interface physique d'uplink, `eno1` par défaut | +| `-B ` | bridge principal auquel l'uplink est rattaché | +| `-d` | dry-run : affiche les commandes sans les exécuter | +| `-V` | désactiver la vérification des sommes de contrôle | + +Un déploiement relève les instances `dnsmasq@` et `metadata@` actives **avant** l'arrêt des +services, et les redémarre ensuite — c'est la seule façon de savoir lesquelles relancer. + +## Configuration + +Un seul fichier, `/etc/two/agent.yml`, partagé par les trois binaires. Voir +[`conf/agent/config.exemple.yml`](conf/agent/config.exemple.yml) pour l'ensemble des options : +chemins de la base et des sockets QEMU, pool de workers, correspondance des types d'interface vers +les bridges physiques, watchdog, API d'administration, journalisation. + +## Prise en main + +```bash +# Un VPC, avec son CIDR interne +curl -X POST http://127.0.0.1:8080/vpcs \ + -d '{"name": "vp-admin", "cidr": "192.168.0.0/16"}' + +# Un subnet en VXLAN dans ce VPC +curl -X POST http://127.0.0.1:8080/subnets \ + -d '{"name": "sn-000001", "vpc": "vp-admin", "mode": "vxlan", "vxlan_id": 1, + "iface_type": "vms", "interface_ip": "10.1.1.1", "cidr": "10.1.0.0/23"}' + +# Une VM, avec une clé SSH et un user-data cloud-init en base64 +curl -X POST http://127.0.0.1:8080/vms \ + -d '{"name": "i-web", "memory": 2048, "cpus": 2, + "metadata": {"sshkey": "ssh-ed25519 AAAA…", + "user_data": "'"$(base64 -w0 < user-data.yml)"'"}, + "interfaces": [{"subnet": "sn-000001", "ip": "10.1.1.2", "primary": true}], + "storage": [{"path": "/data/disks/vms/i-web.qcow2", "dev": "vda"}]}' ``` + +Les créations sont **asynchrones** : l'API répond `202` et l'état de la ressource passe de +`creating` à `running` en base. `GET /vms/i-web` renvoie l'état courant. + +Une VM peut porter plusieurs interfaces, dans un même VPC ; exactement une doit être marquée +`primary` — elle porte la route par défaut et le serveur de metadata. + +La spécification complète est dans [`api/agent.yaml`](api/agent.yaml). + +## Composants + +| Binaire | Rôle | +|---|---| +| `agent` | processus principal : API, dispatcher, exécution, watchdog | +| `metadata` | serveur de metadata cloud-init, une instance par VM dans le netns du VPC | +| `db` | inspection de la base clé-valeur en ligne de commande | + +L'agent prend `-config`, les deux autres `-conf`.