Référence
Standards cloud native, couche par couche
Avant de lire : Introduction au cloud native (comment le moteur utilise chaque mécanisme) et Architecture (les crates nommés ci-dessous). C'est une page de référence : lisez la section du standard qui vous concerne.
Un moteur de containers et de microVMs n'est pas une spécification unique. C'est un empilement de couches, et la plupart des couches ont un standard ouvert : certains viennent de l'OCI (Open Container Initiative), d'autres des SIG Kubernetes et de la CNCF (Cloud Native Computing Foundation), d'autres du noyau Linux, et quelques-uns sont des interfaces de facto sans organisme de normalisation derrière elles.
Cette page est organisée par standard et par couche. Pour chacun, elle répond à quatre questions : ce qu'est le standard, ce qu'il exige d'une implémentation, comment Delonix l'implémente aujourd'hui (crate, fichier, symbole), et ce que disent les éléments de preuve sur la conformité, lacunes comprises. Si vous cherchez « OCI, CRI, CNI, CSI, CDI », c'est cette page. Une fois la section dont vous avez besoin lue, vous pouvez dire ce qu'un standard demande, où le moteur le satisfait, et quelle preuve de conformité existe — avec sa date et sa version.
Lisez d'abord Fondations Linux et Introduction au cloud native si les namespaces, les cgroups, overlayfs ou le kubelet sont nouveaux pour vous. Cette page suppose ces bases acquises et ne les répète pas : le primitif est enseigné dans la première, la façon dont le moteur l'utilise dans la deuxième, et le standard et sa conformité ici.
Trois règles pour lire cette page :
- « Compatible » n'apparaît jamais sans un nombre, une date et une version. Une affirmation de conformité que personne ne remesure cesse d'être une mesure et devient une citation.
- « Non implémenté » est une réponse à part entière. Lorsque le moteur n'implémente pas un standard, la section le dit et renvoie à la décision (ADR) qui explique pourquoi.
- Les chemins sont relatifs à la racine du dépôt, et chaque symbole nommé ici a été lu dans le code. Si un symbole a bougé au moment où vous lisez ceci, faites confiance au code et corrigez la page.
13.0 La carte des couches#
graph TB
subgraph supply["Supply chain"]
SBOM["SBOM — SPDX 2.3<br/>scripts/sbom.py"]
SIGN["Signatures — cosign-compatible,<br/>minisign SHA256SUMS"]
SLSA["SLSA provenance<br/>release.yml"]
end
subgraph obs["Observability"]
OTEL["OpenTelemetry (OTLP traces)<br/>delonix-telemetry"]
PROM["Prometheus / OpenMetrics exposition<br/>/metrics"]
end
subgraph api["Workload API and interfaces"]
KINDS["Own Kinds + node contract<br/>delonix-stack, proto/delonix/node/v1"]
CRI["CRI runtime.v1<br/>delonix-cri"]
DOCKER["Docker Engine API subset (de-facto)<br/>cmd/dockerapi.rs"]
COMPOSE["Compose Spec (de-facto)<br/>cmd/compose.rs"]
MCP["Model Context Protocol (not CNCF)<br/>delonix-mcp"]
end
subgraph exec["Execution"]
IMG["OCI image + distribution<br/>delonix-oci"]
RT["OCI runtime (bundle export)<br/>delonix-linux, cmd/image.rs"]
NET["CNI<br/>delonix-sdn::cni"]
STO["Storage: volumes (no CSI)<br/>delonix-volume"]
DEV["CDI<br/>delonix-linux::cdi"]
VM["VMs: KVM, virtio, UEFI,<br/>cloud-init NoCloud — delonix-vm"]
end
KERNEL["Linux kernel: namespaces, cgroup v2 + systemd delegation,<br/>seccomp, nftables, overlayfs, KVM"]
supply --> api
obs --> api
api --> exec
exec --> KERNEL
Chaque flèche signifie « est construit sur ». La couche noyau n'est pas un standard CNCF ; elle est traitée en 13.15 parce que toutes les autres couches en dépendent.
13.1 OCI Runtime Specification#
Ce qu'est le standard. L'OCI Runtime Specification
définit un filesystem bundle (un système de fichiers racine plus un config.json) et le cycle de vie
d'un container créé à partir de celui-ci (create, start, kill, delete, state). C'est ce
qu'implémentent runc, crun et youki, et ce que pilotent containerd et CRI-O.
Ce qu'une implémentation doit faire.
- Lire un bundle :
config.jsonavecociVersion,process,root,mounts,linux(namespaces, capabilities, cgroups, chemins masqués et en lecture seule, seccomp). - Exposer les opérations du cycle de vie et le document
state, et exécuter les hooks que la configuration déclare (prestart,createRuntime,poststop, …).
Comment Delonix l'implémente. Delonix n'est pas un binaire de runtime OCI au sens de runc :
il ne lit pas de bundle et n'expose pas la ligne de commande create/start/state. C'est son propre
runtime, et il se rapporte à la spécification de deux manières :
- Il produit des bundles pour les runtimes OCI.
delonix image export <image> <dir>écrit<dir>/rootfset<dir>/config.jsonafin querunc run -b <dir>puisse exécuter l'image. -bins/delonix-runtime-bin/src/cmd/image.rs:cmd_exportdécompresse le rootfs viaImageStore::export_rootfs(crates/adapters/delonix-oci/src/overlay.rs) et construit la configuration avecbuild_runtime_spec. -build_runtime_specconstruit la configuration à partir des typesoci_spec::runtime(le crateoci-spec, épinglé dans leCargo.tomlracine) au lieu de JSON écrit à la main. Son commentaire de documentation liste ce qui manquait à un bundle antérieur écrit à la main (montages standard, capabilities effectives, chemins masqués/en lecture seule). - Il implémente nativement les mêmes mécanismes.
fn spawnetcontainer_initdanscrates/adapters/delonix-linux/src/lib.rsfont ce qu'un runtime OCI fait à partir d'unconfig.json: namespaces,pivot_root, capabilities, seccomp, chemins masqués. La spécification d'exécution qu'ils consomment n'est pasconfig.jsonmaisRunOpts(crates/contexts/delonix-compute/src/run_opts.rs), que produit chaque frontal (CLI, Kinds, compose, API Docker, CRI).
État de conformité / lacunes.
- Aucune suite de conformité runtime-spec n'a été exécutée contre Delonix. Ce n'était pas possible : il n'existe aucun point d'entrée consommant un bundle contre lequel l'exécuter.
- Les hooks OCI ne sont pas implémentés. L'ADR-0033
(Proposed) consigne pourquoi : aucun consommateur concret, et exécuter un binaire de l'hôte nommé par
une spécification de container est la classe de sécurité que le projet conditionne déjà à un spike.
La closure en processus
StartedHookdedelonix-linuxy ressemble, mais ce n'est pas le protocole OCI. - Le bundle exporté est minimal (commande, environnement et répertoire de travail par défaut, issus de l'image). Traitez-le comme un format de passage de relais, pas comme une traduction de la configuration complète d'un container.
Par où commencer la lecture. cmd_export et build_runtime_spec dans
bins/delonix-runtime-bin/src/cmd/image.rs → export_rootfs dans
crates/adapters/delonix-oci/src/overlay.rs → spawn dans crates/adapters/delonix-linux/src/lib.rs.
13.2 OCI Image Specification#
Ce qu'est le standard. L'OCI Image Specification
définit comment une image est décrite : un manifest listant un blob config et des blobs layer
ordonnés, un image index pour plusieurs plateformes, adressés par contenu via leur digest, et le
format de répertoire image layout (oci-layout, index.json, blobs/sha256/…).
Ce qu'une implémentation doit faire.
- Adresser tout le contenu par digest et le vérifier.
- Comprendre les manifests, les index (sélectionner la bonne plateforme) et les media types de layers (tar, gzip, zstd), et appliquer les layers dans l'ordre, whiteouts compris.
- Lire et écrire l'image layout lors d'échanges d'images sans registre.
Comment Delonix l'implémente. Tout se trouve dans crates/adapters/delonix-oci :
- Store adressé par contenu :
src/cas.rs(Cas), avecImageStoredanssrc/image.rs. - Layers comme couches basses (lowers) d'overlay :
ImageStore::prepare_overlay(src/overlay.rs) écrit un fichieroverlay-lowersà côté dumerged/du container, et l'init du container lui-même le monte. Les layers sont partagées entre containers, pas copiées (voir les notes sur le partage des layers entre containers dansAGENTS.mdet l'ADR-0037 pour l'API de montage). - Media type de layer d'après le nombre magique : le helper à côté de
DOCKER_MANIFEST_MEDIA_TYPEdanssrc/registry.rsdétecte gzip, zstd ou tar brut. - Écriture de l'image layout :
write_oci_archive(src/save.rs), utilisé pardelonix image save. Il écritoci-layout,index.json, les blobs, et unmanifest.jsonhérité afin qu'une même archive se lise dansctr images import,podman load,docker loadetdelonix image load. Il définit à la foisorg.opencontainers.image.ref.nameetio.containerd.image.name; sans le second,ctrimporte les blobs mais n'enregistre aucun nom. - Lecture des archives :
load_docker_archive(src/load.rs).
État de conformité / lacunes.
- Les manifests poussés et archivés utilisent le media type Docker v2 schema 2
(
application/vnd.docker.distribution.manifest.v2+json,DOCKER_MANIFEST_MEDIA_TYPEdanssrc/registry.rs), et nonapplication/vnd.oci.image.manifest.v1+json. Les pulls acceptent les deux (ACCEPT_MANIFEST). C'est interopérable avec les registres et les outils d'import nommés ci-dessus, mais ce n'est pas « écrit des manifests d'image OCI ». - Aucune suite de conformité image-spec n'a été exécutée.
Par où commencer la lecture. src/image.rs → src/cas.rs → src/overlay.rs
(prepare_overlay, export_rootfs) → src/save.rs → src/load.rs.
13.3 OCI Distribution Specification#
Ce qu'est le standard. L'OCI Distribution Specification
définit l'API HTTP d'un registre : GET /v2/<name>/manifests/<reference>, récupération et envoi de
blobs, liste des tags, et le flux d'authentification par jeton qu'utilisent la plupart des registres.
Ce qu'une implémentation doit faire.
- Négocier les media types de manifest avec
Accept, suivre le flux401 → token → retry, récupérer les blobs et vérifier chacun contre son digest. - Pour une référence par digest (
repo@sha256:…), vérifier que le manifest lui-même a ce digest pour empreinte. - Pousser les blobs (avec vérification d'existence) puis le manifest.
Comment Delonix l'implémente. crates/adapters/delonix-oci/src/registry.rs :
parse_referencedécouperegistry/repo:tag@digest(y compris la forme combinéetag@digest).pull_from_registry_with_creds/pull_from_registry_with_creds_fulltirent une image multi-layers ; les blobs déjà présents dans le CAS ne sont pas retéléchargés.verify_manifest_digest: pour un pull épinglé par digest, les octets du manifest doivent avoir pour empreinte le digest épinglé, sinon le pull est refusé. Sans cela, un registre compromis pourrait servir un manifest différent et cohérent en interne, et l'épinglage serait décoratif. Pour une référence par tag, c'est sans effet ; TLS est la seule garantie d'intégrité, comme avecdocker pull.blob_with_progress_cappedreprend un téléchargement de blob interrompu avecRange:. Un206à un offset différent de celui demandé, ou un200qui a ignoré le range, recommence de zéro au lieu d'être recousu. C'est la vérification finale du digest qui rend le recousage sûr.push_to_registry,build_manifest,list_remote_tags.- Artefacts OCI (blob unique, config vide
application/vnd.oci.empty.v1+json, le modèle qu'utilisent ORAS et Helm) :push_oci_artifact*etpull_oci_artifact*. Les images de VM sont publiées ainsi (voir Construire des microVMs). Les annotations ne sont lues qu'après la vérification du digest. - Identifiants :
src/auth.rslit le formatauthsde Docker/Podman. - Un registre local jetable pour les builds de buildpacks :
src/internal_registry.rs.
État de conformité / lacunes.
- Aucune exécution de conformité distribution-spec n'existe pour le client.
list_remote_tagsne lit que la première page detags/list(pas de paginationLink). Les notes d'AGENTS.mdjugent cela sans importance pour la poignée de tags d'une image de VM ; cela compterait pour un gros dépôt.- Le moteur n'implémente pas le côté serveur du registre, à l'exception du registre local jetable ci-dessus.
Par où commencer la lecture. parse_reference → pull_from_registry_with_creds_full →
verify_manifest_digest → blob_with_progress_capped → pull_oci_artifact_with_meta, tous dans
src/registry.rs.
13.4 Kubernetes Container Runtime Interface (CRI)#
Ce qu'est le standard. Le CRI est l'API gRPC
(runtime.v1) que le kubelet utilise pour exécuter des pods : un RuntimeService (sandboxes de pod,
containers, exec/attach/port-forward, statistiques) et un ImageService. Le kubelet se connecte à un
runtime via --container-runtime-endpoint.
Ce qu'une implémentation doit faire.
- Servir les deux services sur un socket local ; signaler
RuntimeReadyetNetworkReadydansStatus. - Implémenter le modèle de sandbox de pod : namespace réseau partagé, parent de cgroup au niveau du pod, cycle de vie des containers à l'intérieur de la sandbox.
- Renvoyer des URL depuis
Exec/Attach/PortForwardet servir ces flux via le protocole remotecommand de Kubernetes (WebSocket ou SPDY). - Indiquer au kubelet son pilote de cgroup (
RuntimeConfig), respecter les limites de ressources, fournir des statistiques pour l'éviction, et écrire les logs au format de log CRI.
Comment Delonix l'implémente. crates/interfaces/delonix-cri, binaire delonix-cri
(également delonix serve cri) :
- Contrat :
proto/api.protodéclarepackage runtime.v1avecgo_package = "k8s.io/cri-api/pkg/apis/runtime/v1";Versionrépondruntime_api_version: "v1"(src/runtime_svc.rs). - Serveur :
serve_blockingdanssrc/lib.rs; socket issu de--addrou deDELONIX_CRI_ADDR, par défautunix:///run/delonix-cri.sock(src/bin/delonix-cri.rs). - Cycle de vie :
src/runtime_svc.rs(le trait gRPC) délègue àsrc/runtime_svc/lifecycle.rs. - Pilote de cgroup :
runtime_configrépondengine_cgroup_driver(), qui vautCgroupfs. Son commentaire de documentation consigne la mesure qui l'a imposé (2026-09-15, k8s 1.36.4) : ne rien répondre faisait adoptersystemdpar défaut au kubelet, systemd retiraitcpusetdes slices de pod vides, et le kubelet tuait les pods en boucle. - Modèle de ressources du kubelet : ADR-0038.
Le
cgroup_parentdu kubelet est validé parKubeCgroupParent::parse(crates/contexts/delonix-compute/src/record.rs) et consommé danscrates/contexts/delonix-compute/src/run.rs;delonix-linuxdispose detransient_scope_argvpour placer un container dans un scope systemd sous une slice de pod. - Plafond de capabilities :
CapCeiling(src/cap_ceiling.rs), configuré parDELONIX_CRI_CAP_CEILINGetDELONIX_CRI_CAP_CEILING_MODE, et visible danscrictl infosouscapabilityCeiling(inséré dansstatus). - Streaming :
src/streaming.rssert remotecommand via WebSocket (v5.channel.k8s.io), etsrc/spdy.rsvia SPDY/3.1 ;port_forwardrenvoie une URL de streaming. - Statistiques et métriques :
container_stats,list_pod_sandbox_stats,list_metric_descriptorsdanslifecycle.rs. - Réseau des pods : voir 13.5.
État de conformité / lacunes.
- Mesuré avec le
critestamont (docs/cri-conformance.md) : cri-toolscritestv1.36.0, moteurdelonix-criv0.63.1, rootless, 2026-08-25 : 79 réussis, 24 échoués, 19 ignorés, sur 103 specs exécutées (122 dans la suite). Échecs par domaine dans ce document : profils AppArmor par container, propagation des montages, parties du contexte de sécurité, gestionnaire d'images (pull par digest,Uid/Username), port-forward en streaming, OOM, et quelques specs isolées. Ce nombre est antérieur à plusieurs corrections du CRI consignées dansAGENTS.md; il n'a pas été remesuré depuis. Reproduisez-le avecscripts/critest.sh. - Exercé manuellement avec
crictlle 2026-09-11 (selonAGENTS.md) : version, info, images, et le cyclerunp → create → start → exec. - Validé contre un vrai kubelet (k8s 1.36.4, 2026-09-15, selon
AGENTS.mdet le commentaire de documentation deengine_cgroup_driver) : control plane à nœud unique stable, CoreDNS en marche avec le CNI en mode root. - RPC non implémentés (ils renvoient
UNIMPLEMENTED) :UpdateContainerResources,CheckpointContainer,GetContainerEvents(src/runtime_svc.rs). - Attention à un commentaire obsolète :
engine_cgroup_driverdit que la réponse honnêteSYSTEMD« needs the engine to place containers in a transient scope … until it does, this stays », alors quetransient_scope_argvexiste déjà dansdelonix-linux. La réponse du pilote est toujoursCgroupfs; ne la changez pas sans réexécuter la mesure avec le kubelet décrite dans le commentaire de documentation.
Par où commencer la lecture. src/bin/delonix-cri.rs → serve_blocking (src/lib.rs) →
src/runtime_svc.rs (status, runtime_config) → run_pod_sandbox dans
src/runtime_svc/lifecycle.rs → src/cap_ceiling.rs → src/streaming.rs.
13.5 Container Network Interface (CNI)#
Ce qu'est le standard. La spécification CNI définit comment un
runtime demande à des binaires de plugin de configurer un namespace réseau : une liste de
configuration réseau (/etc/cni/net.d/*.conflist), des binaires de plugin dans CNI_PATH
(habituellement /opt/cni/bin), et des opérations passées dans CNI_COMMAND avec la configuration
sur l'entrée standard.
Ce qu'une implémentation doit faire.
- Charger la liste de configuration, résoudre chaque plugin dans
CNI_PATH, et définirCNI_COMMAND,CNI_CONTAINERID,CNI_NETNS,CNI_IFNAME,CNI_PATH. - Pour
ADD, exécuter les plugins dans l'ordre, en passant à chacun le résultat précédent commeprevResult; pourDEL, les exécuter en ordre inverse. - Analyser les résultats et les erreurs structurées ; passer
runtimeConfig(par exempleportMappings) aux plugins qui déclarent la capacité. Les versions plus récentes de la spécification ajoutentCHECK,GCetSTATUS.
Comment Delonix l'implémente. Deux providers réseau existent, et CNI est l'un d'eux :
- SDN native (la valeur par défaut pour les containers) : le netns holder rootless, le bridge,
l'IPAM, le pare-feu nftables —
crates/adapters/delonix-sdn(voir 4.5 et Architecture). - Couche du protocole CNI :
crates/adapters/delonix-sdn/src/cni.rs, pure et testable.list_conf_files,parse_config,load_default,resolve_plugin,add(enchaîneprevResult),del,plugin_dirs(depuisCNI_PATH),readiness(la configuration s'analyse et chaque binaire,ipam.typecompris, est dansCNI_PATH),attach_named_netns,detach_named_netns,set_netns_sysctls. - Où CNI est utilisé :
- CRI, mode root : le réseau du pod est toujours la chaîne CNI du nœud, dans l'hôte, comme dans
containerd.
run_pod_sandbox(crates/interfaces/delonix-cri/src/runtime_svc/lifecycle.rs) crée/run/netns/cri-<id>et appelledelonix_sdn::cni::attach_named_netns.NetworkReadyprovient deroot_cni_readiness(src/runtime_svc.rs), le même fait sur lequel agit la sandbox. - CRI, rootless : optionnel avec
DELONIX_CNI=1plus une conflist (enabled_conf) ; les plugins s'exécutent à l'intérieur du holder qui possède le netns (delonix_sdn::infra::cni_attach_container). Sans ce flag, les pods rootless utilisent la SDN native.
État de conformité / lacunes.
cni.rsdocumente la prise en charge des versions de configuration 0.4.0 et 1.0.0.CHECKexiste comme variante deCommand_mais n'est jamais invoqué ;GCetSTATUSne sont pas implémentés.runtimeConfign'est pas passé aux plugins, donchostPortvia le pluginportmapne fonctionne pas sur une sandbox CNI en mode root (AGENTS.md, notes du 2026-09-15).- Mesuré avec une vraie chaîne bridge/host-local sur un nœud kubeadm (2026-09-15, k8s 1.36.4, selon
AGENTS.md) : nœudReady, CoreDNS qui sert, DNS de Service résolu depuis un autre pod. Non mesuré : plus d'un nœud, et le chemin CNI rootless après sa refactorisation pour partager le corps deADD. - Aucun outillage de conformité de plugin CNI n'a été exécuté contre le côté runtime.
Par où commencer la lecture. crates/adapters/delonix-sdn/src/cni.rs (commentaire de module,
add, readiness) → run_pod_sandbox dans crates/interfaces/delonix-cri/src/runtime_svc/lifecycle.rs
→ root_cni_readiness dans src/runtime_svc.rs.
13.6 Container Storage Interface (CSI)#
Ce qu'est le standard. La spécification CSI est une API gRPC entre un orchestrateur et un pilote de stockage : un service Identity, un service Controller (créer/supprimer/publier des volumes) et un service Node (préparer/publier dans le namespace de montage d'un pod), enregistrés auprès du kubelet.
Ce qu'une implémentation doit faire. Exécuter un plugin Node accessible sur chaque nœud pendant toute la durée de vie des volumes qu'il sert (habituellement un DaemonSet avec des sidecars d'enregistrement), et généralement un plugin Controller en tant que service de longue durée.
Comment Delonix l'implémente. Il n'implémente pas CSI. Le stockage est servi par le propre
kind: Volume du moteur :
crates/adapters/delonix-volume/src/lib.rs: volumes nommés (<root>/volumes/<name>/_data) et montages bind, tous deuxMS_BIND, syntaxe-vde Docker.HostVolumesimplémente le portStorageProviderdu contexte de calcul (crates/contexts/delonix-compute/src/ports.rs).- Stockage réseau (NFS, CIFS/SMB, WebDAV) monté comme volume, et un provisionneur de stockage contre
une API de NAS (ADR-0009, crate
crates/providers/delonix-truenas).
État de conformité / lacunes. Non implémenté, par décision : ADR-0034 (Proposed). Un plugin Node CSI est un service permanent, et le moteur est daemonless par conception. L'ADR ne se rouvre que lorsqu'un besoin concret nomme spécifiquement le protocole CSI et que la question du daemon a son propre ADR accepté. Il consigne aussi la voie pratique qui ne nécessite aucun code ici (un provisionneur NFS externe contre le même serveur).
Par où commencer la lecture. ADR-0034 →
crates/adapters/delonix-volume/src/lib.rs → StorageProvider dans
crates/contexts/delonix-compute/src/ports.rs.
13.7 Container Device Interface (CDI)#
Ce qu'est le standard. La Container Device Interface
décrit des périphériques (des GPU, par exemple) sous forme de specs JSON ou YAML dans /etc/cdi et
/var/run/cdi. Un nom pleinement qualifié comme nvidia.com/gpu=all se résout en modifications de
container : nœuds de périphérique, montages, variables d'environnement et hooks.
Ce qu'une implémentation doit faire. Charger les specs des deux répertoires selon la précédence
définie, résoudre les noms qualifiés, et appliquer à la fois les containerEdits de premier niveau
indépendants des périphériques et ceux propres à chaque périphérique, hooks compris.
Comment Delonix l'implémente. En tant que consommateur de specs générées par un outil
fournisseur (nvidia-ctk cdi generate), jamais en tant qu'outil de découverte de pilote :
crates/adapters/delonix-linux/src/cdi.rs:is_cdi_qualified,ensure_cdi_available,resolve_cdi_device,expand_gpu_devices; répertoires de specs/etc/cdipuis/var/run/cdi.HostDevicesimplémente le portDeviceResolver(crates/contexts/delonix-compute/src/ports.rs), transformant les modifications en les mêmes montages, liste de périphériques et environnement que produisent-vet--device. L'init du container lui-même les applique avantpivot_root; aucun second processus n'entre dans le container par PID.- Surface CLI :
container run --gpus nvidia|allet--device nvidia.com/gpu=<name|all>. Sans spec ninvidia-ctk, l'exécution est refusée avant que quoi que ce soit ne soit créé.
État de conformité / lacunes.
- Les hooks ne sont pas exécutés. Un
ldconfig -r <rootfs>au mieux remplace le hook habituelcreateContainer, et une spec qui déclare des hooks produit un avertissement visible. C'est le coût nommé de l'ADR-0033. - Le commentaire de module consigne une mesure contre une spec issue de
nvidia-ctk1.20.0 (cdiVersion0.7.0) : lescontainerEditsde premier niveau portent la plupart des nœuds de périphérique et tous les montages, donc ne lire que les modifications par périphérique casse CUDA. Le commentaire ne donne pas de date, et la mesure n'a pas été refaite pour cette page.AGENTS.mdliste la précédence exacte entre les deux répertoires et la suffisance deldconfig -rcomme « à confirmer sur un vrai hôte GPU ».
Par où commencer la lecture. crates/adapters/delonix-linux/src/cdi.rs (commentaire de module,
resolve_cdi_device, HostDevices) → DeviceResolver dans
crates/contexts/delonix-compute/src/ports.rs.
13.8 L'API de workload : Kinds propres et contrat de nœud#
Ce qu'est le standard. Il n'y a pas de standard externe ici, volontairement. Le moteur expose ses
propres Kinds déclaratifs dans ses propres groupes d'API (core, compute, networking,
gateway, storage, artifact, infrastructure ; listez-les avec delonix api-resources). La forme
suit les conventions de Kubernetes (apiVersion, kind, metadata, spec) sans revendiquer de
compatibilité avec l'API Kubernetes.
Ce qu'une implémentation doit faire (les règles propres au moteur) :
- Publier le schéma des manifestes généré à partir du code, et non écrit à la main (ADR-0007).
- Planifier, appliquer et détecter la dérive avec un diff à trois voies, et ne jamais ignorer un champ silencieusement.
- Servir un unique contrat de nœud via gRPC et HTTP/JSON sur le même socket local, avec le document OpenAPI généré à partir du protobuf (ADR-0040, Proposed ; ADR-0041).
Comment Delonix l'implémente.
- Table des Kinds :
crates/contexts/delonix-stack/src/kinds.rs(api_version, domaine, convergence, démontage de chaque Kind). Réconciliateur :src/reconcile.rs. - Schéma publié :
docs/schema/v1/delonix.json. - Contrat de nœud :
proto/delonix/node/v1/*.proto, avecdocs/api/openapi.yamlgénéré et vérifié parscripts/contract_gate.py.
État de conformité / lacunes. Contrôlé par la CI (le test du schéma, contract_gate.py), et non
par une suite externe. Voir Architecture et
System design.
Par où commencer la lecture. crates/contexts/delonix-stack/src/kinds.rs →
src/reconcile.rs → proto/delonix/node/v1/node.proto → scripts/contract_gate.py.
13.9 Sous-ensemble de l'API Docker Engine — une interface de facto#
Ce qu'est le standard. L'API Docker Engine
n'est pas un standard CNCF ni OCI. C'est l'API REST d'un fournisseur que de nombreux outils parlent
(CLI docker, compose, kind, frameworks de test). Elle figure ici parce que c'est une véritable
surface d'interopérabilité.
Ce qu'une implémentation doit faire. Répondre à /_ping et à la négociation de version, puis aux
routes qu'appelle un outil donné, avec les formes JSON et les codes de statut de Docker.
Comment Delonix l'implémente. bins/delonix-runtime-bin/src/cmd/dockerapi.rs, servi par
delonix serve docker-api [--addr unix://<socket>] :
API_VERSIONvaut"1.43",MIN_API_VERSIONvaut"1.24"; les préfixes de version sont retirés afin que/v<version>/...fonctionne.- La couverture est une table publiée :
API_MATRIX(routes servies) etAPI_UNIMPLEMENTED(routes refusées, avec une raison).delonix serve docker-api --matrixles affiche, et un test échoue si une branche de dispatch existe sans entrée dans la matrice. - Les routes du cycle de vie des containers délèguent aux mêmes fonctions que la CLI. Le socket est en
0600avecSO_PEERCRED(même uid uniquement).
État de conformité / lacunes.
- Le commentaire de module indique qu'elle a été vérifiée contre une vraie CLI
docker27.3.1 (sans date). - Refusées aujourd'hui, avec leurs raisons dans
API_UNIMPLEMENTED:execetattach(ont besoin du détournement HTTP, hijacking),logs,events,build, les réseaux,images/create(le pull que la plupart des outils appellent en premier),images/{name}/json,stats, les volumes. Lisez la table plutôt que de faire confiance à cette liste ; la table est le contrat. - Le modèle réseau de Docker (
NetworkingConfig) n'est pas traduit.
Par où commencer la lecture. API_MATRIX et API_UNIMPLEMENTED dans
bins/delonix-runtime-bin/src/cmd/dockerapi.rs → le match de dispatch dans le même fichier →
tests/compat/docker_api_smoke.py.
13.10 Compose Specification — une spécification de facto#
Ce qu'est le standard. La Compose Specification décrit une application
multi-containers en YAML (services, networks, volumes, secrets, configs). C'est une
spécification ouverte maintenue par le projet Compose, pas un standard CNCF ni OCI.
Ce qu'une implémentation doit faire. Analyser le modèle, ordonner les services selon depends_on
(avec ses conditions), créer les réseaux et les volumes, et ne pas changer silencieusement la
signification d'un fichier.
Comment Delonix l'implémente. bins/delonix-runtime-bin/src/cmd/compose.rs
(delonix compose up|down|ps|logs|config) : un traducteur vers RunOpts et vers les documents
Image/Network/Volume propres au moteur, avec l'appartenance dérivée des labels.
État de conformité / lacunes.
- Les clés inconnues sont refusées, pas ignorées :
check_unsupported_fieldsvérifie le YAML brut contre des listes d'autorisation (SUPPORTED_TOP,SUPPORTED_SERVICE, …) et des listes de refus avec raisons (KNOWN_UNSUPPORTED_TOP,KNOWN_UNSUPPORTED_SERVICE). Des notes plus anciennes ailleurs dans le workspace disent que les clés inconnues étaient avalées silencieusement ; le code ne le fait plus. include:est refusé (utilisez-f a.yml -f b.yml). Aucune suite de conformité Compose n'a été exécutée.
Par où commencer la lecture. Le commentaire de module et check_unsupported_fields dans
compose.rs.
13.11 OpenTelemetry#
Ce qu'est le standard. OpenTelemetry est le projet CNCF pour les traces, les métriques et les logs, avec le protocole de transport OTLP pour les exporter vers un collecteur.
Ce qu'une implémentation doit faire. Émettre des spans avec des attributs de ressource (au moins
service.name), les exporter via OTLP (gRPC ou HTTP), et les vider (flush) avant la fin du processus.
Comment Delonix l'implémente. crates/adapters/delonix-telemetry/src/telemetry.rs :
- Logs structurés via
tracing(DELONIX_LOG,DELONIX_LOG_FORMAT=json). - Traces via OTLP/HTTP protobuf lorsque
DELONIX_OTLP_ENDPOINTest défini (build_otlp_layer,/v1/tracesajouté s'il manque), avec un processeur de spans par lots sur son propre thread, de sorte que cela fonctionne à la fois dans le serveur CRI asynchrone et dans la CLI synchrone.service.namedistingue les binaires.
État de conformité / lacunes (tous énoncés dans le commentaire de module) :
- Traces uniquement. Les métriques passent par l'exposition Prometheus (13.12), pas par OTLP ; il n'y a pas d'export de logs OTLP.
- HTTP en clair uniquement. Aucun backend TLS n'est compilé, par décision liée à la supply chain ;
un endpoint
https://n'est pas pris en charge. - La CLI, de courte durée, ne vide pas les spans à la sortie, donc une invocation rapide peut perdre
ses spans. Le chemin fiable est le
delonix-cride longue durée.
Par où commencer la lecture. Commentaire de module, init et build_otlp_layer dans
crates/adapters/delonix-telemetry/src/telemetry.rs.
13.12 Format d'exposition Prometheus#
Ce qu'est le standard. Le format d'exposition Prometheus
et son successeur OpenMetrics définissent le texte qu'une
cible de scrape sert sur GET /metrics.
Ce qu'une implémentation doit faire. Servir le texte avec le bon Content-Type, avec des noms et
des types de métriques stables, suffisamment vite pour le délai de scrape.
Comment Delonix l'implémente.
- Un registre partagé unique :
crates/adapters/delonix-telemetry/src/metrics.rs(encode, et des setters commeset_containers,set_vms,set_memory,set_network,set_storage), construit sur le crateprometheus-client. delonix-cri: un listener/metricsoptionnel activé parDELONIX_METRICS_ADDR(src/lib.rs,metrics_handler), distinct du socket gRPC.delonix-mgmt:/metricssur son socket local (crates/interfaces/delonix-mgmt/src/lib.rs,metrics). Les champs peu coûteux sont calculés à chaque scrape ; les coûteux (parcours du disque) sont rafraîchis en arrière-plan afin que les scrapes restent rapides.- Les deux handlers servent
application/openmetrics-text; version=1.0.0; charset=utf-8.
État de conformité / lacunes. Aucune exécution de promtool check metrics n'est consignée. Les
jauges coûteuses peuvent avoir jusqu'à un intervalle de rafraîchissement de retard ; les notes
d'AGENTS.md expliquent pourquoi ce compromis a été choisi.
Par où commencer la lecture. crates/adapters/delonix-telemetry/src/metrics.rs →
metrics_handler dans crates/interfaces/delonix-cri/src/lib.rs → metrics et
src/dashstats.rs dans delonix-mgmt.
13.13 Supply chain : SBOM (SPDX), signatures, provenance SLSA#
Ce que sont les standards.
- SPDX (ISO/IEC 5962) est un format de nomenclature logicielle (software bill of materials).
- Sigstore cosign signe les images de container et stocke la
signature comme un artefact OCI tagué
sha256-<digest>.sig. - SLSA définit la provenance de build : une attestation qui indique quelle source et quel builder ont produit un artefact.
Ce qu'une implémentation doit faire. Publier un SBOM dont les paquets, les versions et les sommes de contrôle correspondent à l'artefact ; signer de sorte que la vérification échoue en cas d'altération ; lier la provenance aux fichiers publiés exacts.
Comment Delonix l'implémente.
- SBOM des binaires de release :
scripts/sbom.pyécrit du SPDX 2.3 à partir deCargo.lock. L'étape « SBOM (SPDX 2.3, do Cargo.lock) » derelease.ymlécritdelonix-sbom.spdx.jsonet l'ajoute àSHA256SUMS, de sorte que le SBOM est couvert par la signature. - Signature de release :
release.ymlsigneSHA256SUMSavec minisign et la vérifie avec la clé publique embarquée dansscripts/install.sh(MINISIGN_PUBKEY). Si la clé est configurée et que le secret manque, la release échoue au lieu d'être publiée sans signature. - Provenance SLSA : l'étape « Proveniência (SLSA) dos binários » de
release.ymlutiliseactions/attest-build-provenancesur les binaires publiésdelonix,delonix-crietdelonix-mcp. Vérifiez avecgh attestation verify <file> --repo angolardevops/delonix-runtime. - Signatures d'images, compatibles cosign :
crates/adapters/delonix-oci/src/sign.rs.sign_image(derrièredelonix image sign) publie une charge utile simple-signing ECDSA P-256 comme artefact.sig;verify_signature(derrièreimage pull --verify <key>etimage verify) vérifie la signature et que la charge utile nomme le digest de l'image. Les images de VM utilisent le même mécanisme (ADR-0017). - Analyse d'images :
crates/adapters/delonix-scanner/src/lib.rs.extract_sbomlit les basesapk/dpkg(et les requirements Python) directement dans les layers du CAS sans exécuter l'image ;advisories_from_osvingère les flux OSV.
État de conformité / lacunes.
- Le SBOM de release ne couvre que l'arbre de dépendances Rust, pas les bibliothèques système, et ne
promet pas un build reproductible ;
sbom.pyle dit dans le champcommentdu document. - Les signatures d'images sont uniquement à base de clés.
sign.rsne contient aucun code Fulcio ou Rekor, il n'y a donc ni signature sans clé (keyless) ni journal de transparence. - Le SBOM de l'analyseur d'images est une liste de paquets interne, pas un document SPDX ni CycloneDX ; aucun code Rust du moteur n'écrit de SPDX.
- Aucune exécution d'un validateur SPDX ou de
slsa-verifiern'est consignée dans ce dépôt.
Par où commencer la lecture. scripts/sbom.py → les étapes SBOM, minisign et provenance de
.github/workflows/release.yml → crates/adapters/delonix-oci/src/sign.rs →
crates/adapters/delonix-scanner/src/lib.rs.
13.14 Machines virtuelles : KVM, virtio, UEFI, cloud-init NoCloud#
Ce que sont les standards.
- KVM est l'interface d'hyperviseur du noyau Linux
(
/dev/kvm). - virtio (OASIS) est le standard de périphériques paravirtualisés : disque, réseau, 9p/fs et console.
- UEFI est l'interface de firmware par laquelle démarrent les images cloud.
- cloud-init NoCloud est la
source de données qui lit
user-data,meta-dataetnetwork-configdepuis un volume local étiquetécidata.
Ce qu'une implémentation doit faire. Donner à l'invité des périphériques virtio et un firmware sur lequel il peut démarrer, et lui remettre un seed NoCloud dont la configuration réseau correspond à sa carte réseau.
Comment Delonix l'implémente. crates/adapters/delonix-vm :
- Backends derrière un port :
trait VmBackendetregister_backenddanssrc/lib.rs. Cloud Hypervisor (VMM Rust sur/dev/kvm) et libvirt/QEMU sont locaux ; Proxmox VE est un provider distant (crates/providers/delonix-proxmox). Voir Construire des microVMs. - virtio :
libvirt_domain_xmlrend le disque principal enbus='virtio'(vda), les cartes réseau en<model type='virtio'/>, et les volumes partagés en virtio-9p. - Firmware UEFI pour Cloud Hypervisor :
DEFAULT_CH_FIRMWARESpréfère leCLOUDHV.fdd'EDK2 àhypervisor-fw. Son commentaire de documentation consigne pourquoi : avechypervisor-fw, les images du projet ne démarrent pas ; avec EDK2, elles démarrent (mesuré le 2026-08-12 selonAGENTS.md). libvirt utilise un<loader>pflash. - cloud-init NoCloud :
src/cloudinit.rs.build_user_data,build_network_config(DHCP sur la carte réseau principale reconnue par MAC, issue demac_for, car la reconnaissance par nom casse les invités NetworkManager), etgenerate_seed_iso, qui empaquette le seed aveccloud-localds. Les backends distants reçoivent l'intention (hostname, utilisateur, clés SSH) au lieu d'un ISO local.
État de conformité / lacunes.
- Cloud Hypervisor ne prend pas en charge virtio-9p ;
spec.volumessur une VM CH est refusé (virtio-fs nécessiterait le daemonvirtiofsd, qui n'est pas câblé). delonix-vm-base:fedora-42ne démarre pas sous l'EDK2 de Cloud Hypervisor, y compris l'image d'origine du fournisseur (AGENTS.md, 2026-08-12) ; le démarrage direct du noyau fonctionne.- La migration à chaud est un NO-GO : ADR-0031.
- Les images de VM publiées sont uniquement amd64 : ADR-0018.
Par où commencer la lecture. trait VmBackend et create_with dans
crates/adapters/delonix-vm/src/lib.rs → src/cloudinit.rs → libvirt_domain_xml →
DEFAULT_CH_FIRMWARES.
13.15 Linux : cgroup v2 et délégation systemd#
Ce qu'est le standard. Pas CNCF : cgroup v2 est l'interface de contrôle des ressources du noyau, et le contrat de délégation de systemd définit qui peut écrire quelle partie de l'arborescence. Chaque runtime de containers dépend des deux.
Ce qu'une implémentation doit faire. N'écrire des limites que dans un sous-arbre qui lui est délégué, respecter la règle « no internal processes », et ne jamais supposer qu'un contrôleur listé à la racine est disponible pour la session appelante.
Comment Delonix l'implémente. L'endroit où les containers sont placés (mode root sous
delonix.slice, rootless sous user@<uid>.service/dlx-containers) est décrit dans le
Manuel de cloud native 4.2 ; l'arborescence et la règle de délégation elles-mêmes sont dans
Fondations Linux. Ce qui compte pour le contrat, dans
crates/adapters/delonix-linux/src/lib.rs :
cgroup_limits_applyrépond à « les limites s'appliqueront-elles ici ? » sans démarrer de container. En rootless, il sonde le cgroup courant du processus (delegated_base_usable), et non le cgroup racine de l'hôte ; en root, il sondedelonix.sliceet le crée s'il manque (root_slice_writable).- Sous le kubelet,
transient_scope_argvconstruit l'appelStartTransientUnitpour un scope délégué sous une slice de pod (ADR-0038).
État de conformité / lacunes. Un simple scope de session SSH n'est pas délégué ; le remède est
systemd-run --user --scope -p Delegate=yes (mesuré le 2026-08-04 selon AGENTS.md). Sans délégation,
container run refuse -m/--cpus/--cpu-weight avec le code de sortie 69
(preflight_resource_limits dans bins/delonix-runtime-bin/src/cmd/container.rs ;
DELONIX_ALLOW_UNENFORCED_LIMITS=1 exécute sans application, avec un avertissement). Cette sonde ne
couvre que la base memory/cpu/pids ; --cpuset, --io-weight et les flags
--device-*-bps/--device-*-iops ont leur propre sonde par contrôleur
(preflight_controller_limits) et sont refusés avec le code 69 lorsque le cgroup du container n’a
pas cpuset/io — le cas habituel sur un Ubuntu standard, où user@.service reçoit
cpu memory pids et un scope Delegate=yes ne peut rien recevoir de plus. Le remède est un
drop-in root sur user@.service (Delegate=cpu cpuset io memory pids). Voir
Environnement et ADR-0015.
Par où commencer la lecture. cgroup_limits_apply → user_service_base → try_delegated_base →
transient_scope_argv, tous dans crates/adapters/delonix-linux/src/lib.rs.
13.16 Model Context Protocol (MCP) — pas un standard CNCF#
Ce qu'est le standard. Le Model Context Protocol est un protocole JSON-RPC par lequel un client d'IA appelle des tools et lit des resources exposés par un serveur. Ce n'est pas un standard CNCF, OCI ni Kubernetes ; il apparaît ici parce que c'est l'une des interfaces du moteur.
Ce qu'une implémentation doit faire. Servir du JSON-RPC sur un transport (stdio ou HTTP), déclarer les capacités du serveur, et décrire les entrées des outils avec JSON Schema.
Comment Delonix l'implémente. crates/interfaces/delonix-mcp (binaire delonix-mcp, également
delonix mcp serve), construit sur le crate rmcp :
- stdio uniquement : un processus enfant au premier plan du client d'IA, qui se termine lorsque stdin se ferme. Ce n'est pas un daemon (ADR-0025).
- Les entrées des outils sont typées et validées par schéma ; les sorties sont du texte JSON. Les
outils portent une classe de risque (
src/risk.rs) et les appels sont audités (src/audit.rs). - Le seul principal est l'uid local, la même frontière que
delonix-mgmt.
État de conformité / lacunes. Pas de transport HTTP ni de sortie d'outil structurée, par décision (voir le commentaire de module). Aucun outillage de conformité MCP n'a été exécuté.
Par où commencer la lecture. Commentaire de module dans crates/interfaces/delonix-mcp/src/lib.rs →
src/risk.rs → src/audit.rs.
13.17 Tableau récapitulatif#
Le statut est implémenté (le moteur satisfait le cœur du contrat), partiel (un sous-ensemble documenté, ou un écart documenté) ou non implémenté. La colonne des éléments de preuve indique où vérifier l'affirmation, ce n'est pas une promesse.
| Standard | Composant Delonix | Statut | Éléments de preuve |
|---|---|---|---|
| OCI Runtime Spec | delonix-linux (mécanismes natifs) ; bundle image export via build_runtime_spec |
partiel — produit des bundles, n'est pas un runtime consommant des bundles ; pas de hooks | 13.1, ADR-0033 |
| OCI Image Spec | delonix-oci (cas, overlay, write_oci_archive) |
partiel — lit les manifests OCI et Docker ; écrit des manifests Docker schema 2 | 13.2, src/registry.rs |
| OCI Distribution Spec | delonix-oci::registry (verify_manifest_digest, blobs reprenables, artefacts) |
implémenté (client) — pas de pagination des listes de tags ; pas d'exécution de conformité | 13.3 |
CRI (runtime.v1) |
delonix-cri |
partiel — critest v1.36.0 : 79/103 réussis, moteur v0.63.1, 2026-08-25 ; kubelet 1.36.4 validé le 2026-09-15 | cri-conformance.md, ADR-0038 |
| CNI | delonix-sdn::cni ; CRI en mode root, rootless optionnel DELONIX_CNI=1 |
partiel — ADD/DEL ; pas d'appels CHECK/GC/STATUS, pas de runtimeConfig |
13.5 |
| CSI | aucun (kind: Volume, delonix-volume, delonix-truenas) |
non implémenté — nécessite un daemon | ADR-0034 |
| CDI | delonix-linux::cdi (HostDevices) |
partiel — consommateur ; hooks non exécutés | 13.7 |
| Kinds du moteur + contrat de nœud | delonix-stack, proto/delonix/node/v1 |
implémenté (API propre) — contrôlé par la CI | ADR-0040, scripts/ |
| Docker Engine API (de facto) | cmd/dockerapi.rs |
partiel — API_MATRIX / API_UNIMPLEMENTED publiés |
delonix serve docker-api --matrix |
| Compose Spec (de facto) | cmd/compose.rs |
partiel — liste d'autorisation, clés inconnues refusées, pas de include: |
13.10 |
| OpenTelemetry | delonix-telemetry:: |
partiel — traces OTLP/HTTP uniquement, pas de TLS | 13.11 |
| Prometheus / OpenMetrics | delonix-telemetry::, /metrics dans delonix-cri et delonix-mgmt |
implémenté — aucune exécution de promtool consignée |
13.12 |
| SBOM SPDX | scripts/sbom.py dans release.yml |
partiel — arbre de dépendances Rust des binaires ; l'analyseur d'images n'émet pas de SPDX | 13.13 |
| Signatures (compatibles cosign, minisign) | delonix-oci::sign ; minisign dans release.yml |
partiel — à base de clés ; pas de keyless, pas de journal de transparence | 13.13, ADR-0017 |
| Provenance SLSA | actions/ dans release.yml |
implémenté pour les binaires de release | 13.13 |
| KVM / virtio / UEFI | delonix-vm (Cloud Hypervisor, libvirt) |
implémenté — pas de virtio-9p sur Cloud Hypervisor ; pas de migration à chaud | 13.14, ADR-0031 |
| cloud-init NoCloud | delonix-vm::cloudinit |
implémenté | 13.14 |
| cgroup v2 + délégation systemd (Linux) | delonix-linux |
implémenté — les limites nécessitent un scope délégué | 13.15, ADR-0015 |
| MCP (pas CNCF) | delonix-mcp |
partiel — stdio uniquement | ADR-0025 |
Lorsque vous modifiez l'un de ces composants, mettez à jour sa ligne et sa section dans la même pull request. Si vous réexécutez une suite de conformité, remplacez ensemble le nombre, la date et la version, et mettez d'abord à jour le document source (docs/cri-conformance.md pour le CRI).
Suivant : Variables d'environnement (DELONIX_*) — chaque variable DELONIX_* lue par le code, sa valeur par défaut, et lesquelles abaissent une frontière.