docs: premiere creation de documentation

Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
GnomeZworc 2026-08-26 22:59:49 +02:00
commit cb904c4744
Signed by: nicolas.boufideline
GPG key ID: 4406BBBF8845D632
34 changed files with 1896 additions and 30 deletions

View file

@ -0,0 +1,63 @@
Cycle de vie des ressources
===========================
VPC, subnets et VM partagent le même jeu d'états.
.. mermaid::
stateDiagram-v2
[*] --> creating
creating --> running
creating --> error
running --> deleting
running --> error
deleting --> deleted
deleting --> error
error --> deleting
deleted --> [*]
.. list-table::
:header-rows: 1
:widths: 15 85
* - État
- Signification
* - ``creating``
- la demande est acceptée et enregistrée ; ``Execute`` n'a pas encore abouti
* - ``running``
- la ressource existe sur le système
* - ``error``
- ``Execute`` a échoué ; état **terminal**, il n'y a pas de reprise automatique
* - ``deleting``
- suppression en cours
* - ``deleted``
- suppression terminée
Suppression
-----------
Elle n'est autorisée que depuis ``running`` ou ``error`` — sinon **409**. Depuis ``error``, elle
est **best-effort** : les ressources système peuvent n'avoir été créées que partiellement.
Un VPC ne peut être supprimé qu'une fois tous ses subnets supprimés.
Pas de rollback
---------------
En cas d'échec partiel pendant une création, les ressources réseau déjà créées **ne sont pas
nettoyées**. C'est un choix délibéré : le nettoyage est déclenché explicitement par une
suppression, qui est justement autorisée depuis ``error``.
Conséquence pour l'appelant : après un passage en ``error``, émettre un ``DELETE`` avant toute
tentative de recréation, faute de quoi la recréation butera sur des objets système résiduels.
États transitoires au redémarrage de l'agent
--------------------------------------------
La file d'attente des workers est **en mémoire**. Une ressource restée en ``creating`` ou
``deleting`` au moment d'un arrêt de l'agent est donc nécessairement orpheline : plus personne
ne la traite.
Au démarrage, une migration idempotente bascule ces ressources en ``error``, et traduit
l'ancien vocabulaire d'états. Une ressource retrouvée en ``error`` après un redémarrage n'a donc
pas forcément échoué techniquement — elle peut simplement avoir été interrompue.

14
docs/concepts/index.rst Normal file
View file

@ -0,0 +1,14 @@
Concepts
========
Le modèle de données, les modes réseau et le cycle de vie des ressources : comment les éléments
fonctionnent entre eux. Le contrat HTTP correspondant est dans
:doc:`/exploitation/api-agent/index`.
.. toctree::
:maxdepth: 1
vpc-subnet-vm
modes-reseau
cycle-de-vie
metadata-cloud-init

View file

@ -0,0 +1,71 @@
Metadata et cloud-init
======================
Chaque VM dispose d'un serveur de metadata NoCloud, servi sur ``169.254.169.254`` dans le netns
de son VPC, sous la forme d'une instance systemd ``metadata@<vm>``.
Chaîne de production
--------------------
.. mermaid::
graph LR
A["agent<br/>WriteNoCloudFiles"] -->|"/run/two/metadata/&lt;vm&gt;/"| M["binaire metadata"]
M -->|HTTP 169.254.169.254| G["guest<br/>cloud-init"]
L'agent écrit les fichiers cloud-init sur disque **avant** de démarrer le service ; le binaire
``metadata`` les lit et les sert. Le processus ``metadata`` n'ouvre **jamais** la base Badger :
deux processus ne doivent pas partager une même instance.
Documents servis
----------------
Chaque document suit la même règle :
* fourni par l'appelant → servi **verbatim**, l'agent n'interprète rien ;
* absent → le template par défaut est rendu ;
* fourni **vide** → servi vide.
Les deux derniers cas sont distincts, et c'est délibéré : fournir une chaîne vide est une façon
explicite de neutraliser un document.
Champs de ``metadata``
----------------------
``sshkey``
Clé publique ajoutée au compte ``syonad``. Transmise telle quelle, non encodée.
``password``
Un **hash**, tel qu'attendu par la clé ``passwd`` de cloud-config (``$6$…``) — jamais un mot
de passe en clair. Omis, le compte est créé verrouillé ; sans ``password`` ni ``sshkey``,
aucun compte n'est créé.
``user_data``
Le user-data cloud-init, **encodé en base64**. L'encodage évite l'échappement JSON des
documents multi-lignes et autorise les charges ``gzip+base64``. Un base64 invalide est rejeté
en 400 plutôt que servi vide.
``instance-id``
------------------
``instance-id`` vaut le **nom de la VM**. Recréer une VM du même nom sur le même disque fait que
cloud-init la reconnaît comme déjà provisionnée et **n'applique pas** le user-data. Pour rejouer
un provisionnement : changer de nom, repartir d'un disque neuf, ou exécuter
``cloud-init clean --logs`` dans le guest avant l'extinction.
Configuration réseau
--------------------
.. warning::
``network-config.tmpl`` cible ``eth0`` alors que les guests utilisent ``ens3`` : il ne
s'applique donc à rien, et le réseau des VM vient du DHCP. **Ne pas le « corriger » ni le
supprimer.** Le rendre opérant ferait remplacer par cloud-init la configuration réseau de
l'image, sur toutes les VM.
Sécurité
--------
``/run/two/metadata/<vm>/vendor-data`` est en ``0644`` et contient le hash de mot de passe. Tout
compte local du host peut le lire. C'est une exposition connue et acceptée en l'état ; elle
disqualifie l'usage de hashs faibles ou réutilisés.

View file

@ -0,0 +1,99 @@
Modes réseau
============
Le champ ``mode`` d'un subnet détermine la façon dont il est raccordé à l'host, et les routes
annoncées aux VM.
.. list-table::
:header-rows: 1
:widths: 15 45 40
* - Mode
- Raccordement
- État
* - ``vxlan``
- tunnel VXLAN (``vxlan_id``) + bridge dans le netns du VPC
- défaut
* - ``bridge``
- rattachement direct à un bridge existant de l'host, résolu depuis ``iface_type``
- disponible
* - ``public_ip``
- routé comme ``vxlan`` côté DHCP
- **mise en place host non implémentée** — la création échoue à l'exécution
* - ``vlan``
- —
- réservé, non implémenté
.. warning::
``public_ip`` est accepté par l'API et traité comme ``vxlan`` pour le DHCP, mais sa
configuration réseau côté host n'existe pas encore : la création part en ``error`` dans
``Execute``. Ne pas s'appuyer dessus en production.
vxlan
-----
.. mermaid::
graph LR
VM --- TAP[tap] --- BR["br-&lt;subnet&gt;<br/>interface_ip"]
BR --- VX["vxlan&lt;vni&gt;"] --- HBR["bridge host<br/>(iface_type)"] --- UP[uplink]
Le subnet vit dans le netns du VPC. La VM n'est donc **pas joignable depuis l'host** sans route
explicite — point à connaître avant de câbler un outil externe dessus.
bridge
------
Le subnet est rattaché directement à un bridge existant de l'host. Pas de tunnel, pas de route
VPC : le trafic sort par le bridge, et la VM est joignable depuis l'host.
Routes annoncées aux VM
-----------------------
Les routes sont poussées par DHCP, dans l'**option 121** (routes statiques sans classe,
RFC 3442). Trois entrées y figurent :
#. la route ``/32`` vers ``169.254.169.254``, le serveur de metadata ;
#. la route vers le CIDR du VPC ;
#. la route par défaut ``0.0.0.0/0``.
.. important::
**Un client qui lit l'option 121 ignore l'option 3.** Toute route par défaut doit donc figurer
dans l'option 121 ; l'option 3 ne sert que les clients qui n'implémentent pas la 121.
Route par défaut : ``default_route`` et ``gateway``
----------------------------------------------------------
Une route par défaut est **toujours** annoncée. Le champ ``default_route`` ne choisit que son
next-hop :
``default_route: false`` (défaut)
next-hop = ``interface_ip`` du subnet.
``default_route: true``
next-hop = le champ ``gateway`` s'il est fourni, sinon la gateway lue dans la table de routage
de l'host.
``gateway`` n'est **pas validé** par l'agent : sa joignabilité et sa cohérence avec le CIDR du
subnet relèvent de l'appelant. Fourni avec ``default_route: false``, il est ignoré.
Dans tous les modes sauf ``bridge``, la route vers le CIDR du VPC garde ``interface_ip`` comme
next-hop : sur un subnet à IP publique, le trafic interne ne doit pas sortir par la gateway
publique.
Pourquoi la route ``/32`` vers le serveur de metadata est indispensable
----------------------------------------------------------------------------
Elle paraît redondante avec la route par défaut. Elle ne l'est pas.
La DNAT vers le serveur de metadata est posée dans le netns du VPC, en ``PREROUTING``. Le paquet
n'y est traité en L3 que si son next-hop est ``interface_ip``, portée par le bridge du netns.
Avec un autre next-hop, la trame est commutée en **L2** sans traverser ``PREROUTING`` : le
serveur de metadata devient injoignable et tout le provisionnement cloud-init échoue,
silencieusement.
.. danger::
Ne jamais retirer cette route de l'option 121, quelle que soit l'apparence de redondance.

View file

@ -0,0 +1,63 @@
VPC, subnet et VM
=================
Trois types de ressources, une hiérarchie stricte.
.. mermaid::
graph TD
VPC["VPC<br/><i>network namespace</i><br/>cidr"] --> SN1["Subnet<br/><i>bridge + VXLAN</i><br/>interface_ip, cidr"]
VPC --> SN2["Subnet"]
SN1 --> VM1["VM<br/><i>QEMU/KVM</i>"]
SN1 --> VM2["VM"]
SN2 --> VM2
VPC
---
Un VPC est un **network namespace** portant un espace d'adressage (``cidr``). C'est l'unité
d'isolation : deux VPC ne se voient pas, et peuvent réutiliser les mêmes plages d'adresses.
Un VPC ne peut être supprimé que si tous ses subnets le sont déjà — sinon 409.
Subnet
------
Un subnet appartient à un VPC et pose, dans son netns, un bridge qui porte ``interface_ip`` — la
gateway vue par les VM. Il fournit aussi le DHCP (dnsmasq) et les routes annoncées aux guests.
``iface_type`` est une clé **logique** (``vms``, ``internet``, ``admin``…), traduite en nom de
bridge physique par la configuration de l'agent. Une clé absente ou inconnue retombe sur
``default_interface``. Ce niveau d'indirection permet au même appel d'API de fonctionner sur des
hosts dont le nommage réseau diffère.
Le comportement réseau dépend du :doc:`mode </concepts/modes-reseau>`.
VM
--
Une VM est un processus QEMU/KVM raccordé à un ou plusieurs subnets par des taps.
**Interfaces.** L'ordre du tableau ``interfaces`` détermine le slot PCI (``0x03 + index``), donc
le nom de l'interface dans le guest. Exactement une interface doit être ``primary`` : elle porte
la route par défaut et le serveur de metadata. Tous les subnets d'une VM doivent appartenir au
**même VPC**.
**Stockage.** Un seul disque ``vdX`` (virtio-blk) par VM ; les disques supplémentaires passent
par le contrôleur SCSI (``sdX``). Cette contrainte vient de la carte PCI figée — voir
:doc:`/architecture/contraintes`.
Ce qui est stocké, et où
------------------------
Une ressource ne porte en base que ce qui lui est propre. Une VM stocke le **lien** vers son
subnet (``vm/<name>/subnet``), pas le VPC ni le bridge ni la gateway : ces valeurs sont lues
depuis le subnet, leur source canonique. Le schéma complet des clés est dans
:doc:`/architecture/stockage`.
Nommage
-------
L'API est machine-to-machine : elle **ne valide pas** les conventions de nommage, à l'exception
du motif documenté pour les VPC (``vp-…``). Les exemples de cette documentation suivent la
convention ``vp-`` / ``sn-`` / ``i-``, mais c'est à l'appelant de la faire respecter.