Aller au contenu

Retriever de zone et cascade

Une zone est pilotée par un seul document : son Retriever. Il liste, par nom et par contrainte de version, les recipes que la zone doit détenir, et nomme le cookbook où les résoudre. L’instance le relit à chaque synchronisation ; changer ce que contient une zone, c’est changer ce document — ou publier une nouvelle version de recipe qu’une contrainte existante couvre déjà. Le format du document est normatif sur le site recipe-spec : voir la spécification du Retriever (le kind Retriever, recipe.tobby.dev/v1alpha1). Un exemple complet et commenté est livré dans le dépôt, sous examples/retriever.yaml.

retriever.source accepte trois formes (FR-010) :

Forme Exemple Quand
Fichier local /etc/tobby/retriever.yaml Le document est géré avec la configuration de l’instance.
URL HTTP(S) https://git.example.com/platform/retriever.yaml Le document vit dans un dépôt Git ou sur n’importe quel serveur web — le montage GitOps habituel.
Référence OCI oci://registry.example.com/config/retriever:v1 Le document voyage comme le contenu qu’il décrit — y compris d’une zone à l’autre, porté par Tobby lui-même.

La source configurée est affichée telle quelle sur l’écran d’administration Retriever (/admin/retriever, rôle admin) et sur son miroir d’API GET /api/v1/retriever — aux côtés des périmètres de confiance relâchés déclarés et de l’intervalle de synchronisation effectif. La surcharge d’intervalle vit sur le même écran (PUT /api/v1/retriever/interval, et DELETE pour revenir à la valeur configurée) ; elle persiste dans le répertoire d’état, survit aux redémarrages, l’emporte sur sync.interval, et est auditée comme un changement de configuration sensible (FR-094).

L’écran d’administration Retriever : source configurée, intervalle et sa surcharge à chaud

À chaque cycle, l’instance résout depuis le cookbook chaque recipe listée, vérifie sa signature contre les trust roots configurées (FR-033), puis réconcilie. Les contraintes de version sont résolues à chaque passe ; si aucune version publiée ne satisfait une contrainte, cette entrée échoue et le dit — les autres entrées poursuivent. Une seule recipe non résolvable ne bloque jamais la zone.

La cascade : connectée → restreinte → plus restreinte

Section intitulée « La cascade : connectée → restreinte → plus restreinte »
Zone A — amont Zone B — aval Zone C — plus en aval Tobby re-vérifie à l'entrée Tobby re-vérifie à l'entrée Tobby re-vérifie à l'entrée registre de zone …/docker.io/bitnami/wordpress registre de zone …/docker.io/bitnami/wordpress registre de zone …/docker.io/bitnami/wordpress recipes recipes Les mêmes recipes signées descendent sans modification — chaque instance re-vérifie contre ses propres trust roots Les chemins relocalisés sont invariants : le même chemin …/docker.io/… dans chaque zone, quel que soit le nombre de sauts

Les topologies réelles enchaînent les zones. La zone amont promeut dans son registre ; le Tobby de la zone aval récupère depuis ce registre, alors même que les recipes — immuables, signées, au bit près — continuent de nommer les hôtes d’origine (docker.io/...). Le pont, c’est la substitution de source (FR-036) :

# Instance aval
registries:
substitutions:
docker.io: registry.upstream.example/docker.io
ghcr.io: registry.upstream.example/ghcr.io
retriever:
source: oci://registry.upstream.example/cookbook/retriever:v1

La substitution change uniquement le point de terminaison réseau contacté — jamais le chemin de destination calculé (FR-035). C’est cette invariance qui rend la cascade composable : docker.io/bitnami/wordpress se relocalise en <registry>/docker.io/bitnami/wordpress dans chaque zone, quel que soit le nombre de sauts franchis, et ne dégénère jamais en reg.zone2/reg.zone1/docker.io/.... Le registre de chaque zone détient les mêmes chemins relocalisés sous son propre hôte, et le cookbook de chaque zone — alimenté par la propagation des recipes (FR-034) — est ce que désigne le Retriever de la zone suivante. La règle et sa justification sont dans ADR-0013 ; la grammaire normative (forme canonique des hôtes, encodage des ports, sémantique de substitution) est dans RECIPE-SPEC §11.5.

Deux politiques lisent délibérément des références différentes :

  • La liste blanche de registries (FR-030) et la recherche de credentials portent sur l’hôte effectif réellement contacté — le substitut. C’est de là que viennent les octets, c’est donc ce que la politique réseau doit nommer.
  • Les périmètres des trust roots (FR-033) s’appliquent au ref nominal écrit dans la recipe. Une provenance signée ne change pas parce que le contenu a été récupéré depuis une copie plus proche.

Les journaux enregistrent la correspondance nominal→effectif à chaque récupération substituée : un audit peut donc toujours répondre aux deux questions — « quel était ce contenu » et « d’où viennent ces octets ».

Une instance aval s’authentifie auprès de son amont comme n’importe quel client de registre. Créez sur l’instance amont un compte (ou un jeton) dédié — voir Authentification et RBAC — dont le seul besoin est la lecture, et transmettez-le à l’instance aval par son fichier de credentials (FR-004) :

registries:
credentialsFile: /etc/tobby-credentials/config.json

Le fichier est une charge dockerconfigjson standard ; les entrées sont recherchées par hôte effectif, l’entrée nomme donc le registre amont — registry.upstream.example — et non docker.io. Il doit vivre en dehors du store (les secrets ne voyagent jamais sur un média transportable), et sur Kubernetes c’est un Secret monté que le chart câble pour vous. Les credentials en écriture suivent le même chemin : le push vers le registre de destination de la zone utilise le même fichier de credentials, indexé par l’hôte de destination.

Le versant destination de la même instance a sa propre section de configuration — destination.registry, plus destination.basePath et destination.cookbook — délibérément séparée des substitutions : l’une répond à « où est-ce que je lis », l’autre à « où est-ce que je promeus », et appliquer une réécriture côté lecture à une écriture publierait dans un registre que personne n’a nommé.

Ensuite : vos clusters et vos hôtes consomment ce qui est arrivé — Brancher vos clients.