Compare commits
No commits in common. "c47577db2109309147dbe450022118e09f63f514" and "26d580574738e920603748e58c8f5c6e241497ad" have entirely different histories.
c47577db21
...
26d5805747
2 changed files with 15 additions and 111 deletions
85
README.md
85
README.md
|
|
@ -1,80 +1,19 @@
|
||||||
# syonad/two
|
# syonad
|
||||||
|
|
||||||
Orchestrateur réseau et machines virtuelles mono-nœud, pensé pour être piloté par un logiciel
|
A simple but powerful orchestrator, designed to be easy to use and API-first.
|
||||||
plutôt que par un humain.
|
|
||||||
|
|
||||||
Il expose une API HTTP qui crée des **VPC** — isolés par network namespace —, des **subnets** —
|
## deployer
|
||||||
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/
|
||||||
|
|
||||||
`deploy.sh` se met à jour lui-même depuis la branche, télécharge binaires, units systemd et
|
curl 'https://git.g3e.fr/syonad/two/raw/branch/main/systemd/agent.service' -o '/etc/systemd/system/agent.service'
|
||||||
scripts depuis la release, et les vérifie contre le manifeste `SHA256SUMS`. Le drapeau `-i`
|
curl 'https://git.g3e.fr/syonad/two/raw/branch/main/systemd/dnsmasq@.service' -o '/etc/systemd/system/dnsmasq@.service'
|
||||||
prépare l'host : paquets, module `br_netfilter`, `sysctl`, et bridges.
|
curl 'https://git.g3e.fr/syonad/two/raw/branch/main/systemd/metadata@.service' -o '/etc/systemd/system/metadata@.service'
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
Options utiles :
|
modprobe br_netfilter
|
||||||
|
echo br_netfilter > /etc/modules-load.d/br_netfilter.conf
|
||||||
| Option | Effet |
|
|
||||||
|---|---|
|
|
||||||
| `-t <tag>` | déployer une release donnée |
|
|
||||||
| `-b <branche>` | déployer depuis une branche au lieu d'une release |
|
|
||||||
| `-i` | préparer l'host (paquets, noyau, réseau) |
|
|
||||||
| `-u <iface>` | interface physique d'uplink, `eno1` par défaut |
|
|
||||||
| `-B <bridge>` | 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`.
|
|
||||||
|
|
|
||||||
|
|
@ -11,48 +11,23 @@ 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`
|
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
|
- 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
|
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**
|
**Réseau**
|
||||||
|
|
||||||
- VPC isolés par network namespace, subnets en mode `vxlan` ou `bridge`
|
- 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, fichier de baux propre
|
- DHCP par subnet via instances `dnsmasq@` dédiées, entrées ip→mac en base
|
||||||
à chaque instance
|
- Route par défaut et route du VPC distribuées par DHCP (`default_route` par subnet)
|
||||||
- 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
|
- Isolation du DHCP par ebtables, redirection du service de metadata par iptables
|
||||||
|
|
||||||
**Machines virtuelles**
|
**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
|
- Démarrage QEMU/KVM avec plusieurs disques et ordre de démarrage explicite
|
||||||
- Amorçage UEFI optionnel (OVMF), avec magasin de variables par VM
|
- 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
|
- 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`
|
- 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**
|
**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
|
- 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`
|
- `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`
|
- Units systemd et scripts publiés comme assets de release, avec manifeste `SHA256SUMS`
|
||||||
|
|
@ -64,17 +39,7 @@ 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
|
- Pas de rollback en cas d'échec partiel d'une création — les ressources réseau orphelines
|
||||||
ne sont pas nettoyées automatiquement
|
ne sont pas nettoyées automatiquement
|
||||||
- API destinée à un appelant logiciel : la validation de cohérence des entrées (CIDR, VXLAN
|
- API destinée à un appelant logiciel : la validation de cohérence des entrées (CIDR, VXLAN
|
||||||
ID, format des noms, joignabilité d'une `gateway`) est à la charge de l'appelant
|
ID, format des noms) 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/<name>/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
|
- Les packages `internal/netns`, `netif`, `qemu`, `vm`, `iptables` et `ebtables` ne
|
||||||
fonctionnent que sous Linux
|
fonctionnent que sous Linux
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue