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.
Trois sources
Section intitulée « Trois sources »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).

À 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 »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 avalregistries: substitutions: docker.io: registry.upstream.example/docker.io ghcr.io: registry.upstream.example/ghcr.io
retriever: source: oci://registry.upstream.example/cookbook/retriever:v1La 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
refnominal é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 ».
Credentials entre instances
Section intitulée « Credentials entre instances »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.jsonLe 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.