
Une image validée en recette doit arriver en production sans être reconstruite, et sans que personne édite un fichier à la main. C'est ce que Kargo automatise. Vous décrivez une suite d'environnements, test puis prod, et Kargo retient ce qui a été validé où, puis refuse de sauter une étape. Cette page part du problème concret, explique les quatre objets de Kargo avant de l'installer, monte une chaîne à deux étages et promeut une image. Les commandes ont été rejouées sur un cluster, et les sorties affichées sont les vraies.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Installer Kargo par Helm depuis un registre OCI, avec une version épinglée
- Distinguer les quatre objets du modèle : Warehouse, Freight, Stage, Promotion
- Enchaîner deux environnements et savoir ce qui autorise le second à recevoir
- Reconnaître les refus de l'API qui coûtent le plus de temps
- Décider si Kargo vous apporte quelque chose que votre outil GitOps ne fait pas
Prérequis
Section intitulée « Prérequis »- Un cluster Kubernetes fonctionnel, un cluster local suffit
- Helm 3.13.1 au minimum, pour la raison expliquée plus bas
- cert-manager installé, dont dépend la configuration par défaut
- Les bases du GitOps et, idéalement, une pratique d'Argo CD
Le problème, en situation
Section intitulée « Le problème, en situation »Prenons une équipe de trois personnes qui exploite un cluster. L'image nginx:1.31.6 est déployée en recette depuis deux jours, les tests passent, la mise en production est décidée. Quelqu'un ouvre le dépôt Git, cherche le fichier de l'environnement de production, remplace 1.31.5 par 1.31.6, ouvre une demande de fusion, attend une relecture, fusionne. Son outil de déploiement voit le changement et applique.
Ce geste fonctionne, et il pose trois problèmes qui grandissent avec l'équipe. Personne ne garantit que la version mise en production est celle qui a été testée : un chiffre se recopie de travers. Rien n'empêche de sauter la recette : éditer directement le fichier de production est tout aussi simple. Et la trace se perd : six mois après, retrouver quelle version est passée par quel environnement demande de relire l'historique Git.
Argo CD sait appliquer ce que Git contient, mais il ne décide pas ce qui a le droit d'y entrer. C'est précisément le vide que Kargo occupe : il surveille les nouvelles versions, les regroupe en candidates, et fait respecter l'ordre des environnements. Le guide déploiement multi-environnements montre la version manuelle de ce geste ; Kargo l'automatise.
Les quatre objets de Kargo
Section intitulée « Les quatre objets de Kargo »Kargo ajoute son propre vocabulaire à Kubernetes, et quatre mots suffisent pour commencer. Ils décrivent le trajet d'une version : d'où elle vient, ce qu'elle contient, où elle va, et qui l'y envoie. Les comprendre maintenant évite d'installer cinq composants sans savoir à quoi ils servent.
| Objet | Rôle | Analogie |
|---|---|---|
| Warehouse | Surveille une source, image ou dépôt Git, et détecte les nouvelles versions | Le quai de réception |
| Freight | Un ensemble de versions constaté à un instant donné, immuable | Le colis scellé |
| Stage | Un environnement, qui déclare d'où il accepte son Freight | Une étape du trajet |
| Promotion | L'ordre de faire entrer un Freight donné dans un Stage donné | Le bon de livraison |
Le Freight est la pièce centrale. Il ne contient pas qu'un numéro de version : il fige un ensemble cohérent, par exemple une image et le commit Git qui l'accompagne. C'est ce colis entier qui voyage d'un environnement au suivant, ce qui garantit que rien ne se désynchronise en route.
Kargo installe en réalité neuf ressources dans le groupe kargo.akuity.io. Les cinq autres portent la configuration et les tâches réutilisables : vous les croiserez en listant le cluster, sans avoir à les connaître pour suivre cette page.
Installer Kargo avec son chart OCI
Section intitulée « Installer Kargo avec son chart OCI »Kargo ne se distribue pas par un dépôt Helm classique, mais par un registre OCI. Un registre OCI est un entrepôt d'images de conteneurs, comme Docker Hub ou GitHub Packages ; depuis Helm 3, il sait aussi stocker des charts, c'est-à-dire des paquets d'installation Kubernetes. Conséquence pratique : l'adresse oci://ghcr.io/akuity/kargo-charts/kargo ne s'ajoute pas avec helm repo add, elle se passe directement à helm upgrade. Cette différence explique à elle seule deux messages d'erreur déroutants, traités dans le dépannage.
-
Installer cert-manager
Kargo réclame des certificats pour ses webhooks d'admission, ces composants que l'API de Kubernetes appelle avant d'écrire une ressource, et qui peuvent la refuser. Comme l'API leur parle en HTTPS, ils ont besoin d'un certificat, que cert-manager fabrique et renouvelle. La documentation amont présente cert-manager comme une dépendance non absolue ; en configuration par défaut, elle l'est bel et bien.
Fenêtre de terminal kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.1/cert-manager.yamlkubectl -n cert-manager rollout status deploy/cert-manager-webhook --timeout=300s -
Générer le mot de passe administrateur et la clé de signature
Le chart n'a aucune valeur par défaut pour ces deux champs : sans eux, l'installation échoue. Le mot de passe est transmis haché, jamais en clair, et la clé de signature authentifie les jetons de l'API.
Fenêtre de terminal pass=$(openssl rand -base64 48 | tr -d "=+/" | head -c 32)echo "Mot de passe administrateur : $pass"hashed_pass=$(htpasswd -bnBC 10 "" "$pass" | tr -d ':\n')signing_key=$(openssl rand -base64 48 | tr -d "=+/" | head -c 32)htpasswdvient du paquetapache2-utilssur Debian et Ubuntu,httpd-toolssur les distributions de la famille Red Hat. -
Installer le chart avec une version épinglée
La documentation amont omet
--version, ce qui installe la dernière publiée et rend l'installation non reproductible. On l'épingle.Fenêtre de terminal helm upgrade --install kargo \oci://ghcr.io/akuity/kargo-charts/kargo \--version 1.11.4 \--namespace kargo \--create-namespace \--set api.adminAccount.passwordHash="$hashed_pass" \--set api.adminAccount.tokenSigningKey="$signing_key" \--wait --timeout 10m -
Vérifier ce qui tourne
Fenêtre de terminal kubectl -n kargo get deployRésultat NAME READY UP-TO-DATE AVAILABLEkargo-api 1/1 1 1kargo-controller 1/1 1 1kargo-external-webhooks-server 1/1 1 1kargo-management-controller 1/1 1 1kargo-webhooks-server 1/1 1 1
Kargo n'est pas un contrôleur unique, mais cinq déploiements. C'est une dépendance sérieuse ajoutée au cluster, et une raison de mesurer son intérêt avant de l'installer. Le kargo-api sert l'interface web et l'API ; les deux serveurs de webhooks interceptent les écritures ; les deux contrôleurs réconcilient les objets.
Pourquoi cert-manager n'est pas une option
Section intitulée « Pourquoi cert-manager n'est pas une option »La dépendance se vérifie, elle ne se suppose pas. Une fois Kargo installé, trois objets Certificate apparaissent dans son namespace :
kubectl -n kargo get certificateNAME READYkargo-api Truekargo-external-webhooks-server Truekargo-webhooks-server TrueSans cert-manager, aucun contrôleur ne sert ces objets : ils restent sans certificat, et les webhooks n'ont pas de TLS. Le cluster n'échoue pas bruyamment, il reste à moitié installé, ce qui est plus difficile à diagnostiquer qu'une erreur franche.
Monter une chaîne à deux étages
Section intitulée « Monter une chaîne à deux étages »Le projet et le Warehouse
Section intitulée « Le projet et le Warehouse »Un Project Kargo crée son propre namespace. Le Warehouse ci-dessous surveille une image publique et se limite aux versions 1.31.x :
apiVersion: kargo.akuity.io/v1alpha1kind: Projectmetadata: name: demo---apiVersion: kargo.akuity.io/v1alpha1kind: Warehousemetadata: name: nginx namespace: demospec: subscriptions: - image: repoURL: docker.io/library/nginx semverConstraint: ^1.31.0 # 1.31.x uniquement, jamais 1.32 discoveryLimit: 3 # ne retient que les 3 versions les plus récentesQuelques secondes après l'application, le Warehouse a fait son travail :
kubectl -n demo get warehouse nginx \ -o jsonpath='{.status.conditions[?(@.type=="Ready")].message}'Successfully discovered artifacts from 1 subscriptionsChaque Freight reçoit un alias lisible, deux mots séparés d'un tiret. Kargo le génère pour vous éviter de manipuler son identifiant réel, une empreinte hexadécimale illisible à l'œil :
kubectl -n demo get freight \ -o jsonpath='{range .items[*]}{.alias} {.images[0].repoURL}:{.images[0].tag}{"\n"}{end}'virtuous-chicken docker.io/library/nginx:1.31.6Les deux Stages
Section intitulée « Les deux Stages »Le Stage test accepte son Freight directement du Warehouse. Le Stage prod, lui, ne l'accepte que s'il est passé par test : c'est toute la chaîne, et elle tient dans le seul champ sources.
apiVersion: kargo.akuity.io/v1alpha1kind: Stagemetadata: name: test namespace: demospec: requestedFreight: - origin: {kind: Warehouse, name: nginx} sources: {direct: true} # se sert au quai de réception promotionTemplate: spec: steps: - uses: file-write config: path: promu.txt contents: test---apiVersion: kargo.akuity.io/v1alpha1kind: Stagemetadata: name: prod namespace: demospec: requestedFreight: - origin: {kind: Warehouse, name: nginx} sources: {stages: ["test"]} # ne prend que ce qui a passé test promotionTemplate: spec: steps: - uses: file-write config: path: promu.txt contents: prodPromouvoir, et voir ce qui débloque l'étape suivante
Section intitulée « Promouvoir, et voir ce qui débloque l'étape suivante »Une Promotion nomme un Stage et un Freight. Le champ freight attend le nom réel de l'objet, celui que renvoie metadata.name, et non l'alias affiché plus haut, qui ne sert qu'à la lecture humaine :
FREIGHT=$(kubectl -n demo get freight -o jsonpath='{.items[0].metadata.name}')
kubectl apply -f - <<EOFapiVersion: kargo.akuity.io/v1alpha1kind: Promotionmetadata: name: promo-test-1 namespace: demospec: stage: test freight: $FREIGHTEOFpromotion.kargo.akuity.io/test.01m376e8c2bc3gje3sb4qka4hf.e7f0029 createdLe nom demandé n'a pas été retenu. Kargo impose le sien, construit en <stage>.<identifiant unique>.<freight abrégé>. Un script qui référencerait ensuite promo-test-1 ne trouverait rien : on relit toujours le nom rendu par la création.
Ce qui autorise prod à recevoir
Section intitulée « Ce qui autorise prod à recevoir »Une promotion réussie ne se contente pas de changer l'état du Stage : elle marque le Freight.
kubectl -n demo get freight "$FREIGHT" -o jsonpath='{.status.verifiedIn}'{"test":{"verifiedAt":"2026-09-23T13:14:20Z"}}C'est ce champ verifiedIn, et lui seul, qui débloque l'étape suivante. Le Stage prod déclare sources: {stages: ["test"]} : il ne réclamera un Freight que si celui-ci porte la trace de son passage par test. La chaîne n'est donc pas une convention de nommage ni une discipline d'équipe, c'est une contrainte que l'API applique.
La promotion vers la production s'écrit avec le même manifeste, à un mot près : stage: prod remplace stage: test. Le Freight désigné, lui, ne change pas, et c'est tout l'intérêt de la manœuvre : c'est le même colis qui poursuit son trajet.
kubectl apply -f - <<EOFapiVersion: kargo.akuity.io/v1alpha1kind: Promotionmetadata: name: promo-prod-1 namespace: demospec: stage: prod freight: $FREIGHTEOFLes deux étages portent désormais leur promotion, et une seule commande donne l'état final de la chaîne :
kubectl -n demo get promotion \ -o custom-columns=NOM:.metadata.name,STAGE:.spec.stage,PHASE:.status.phaseNOM STAGE PHASEprod.01m376f9n8f4cjdre86jm3y6kv.e7f0029 prod Succeededtest.01m376e8c2bc3gje3sb4qka4hf.e7f0029 test SucceededLes deux lignes se terminent par le même suffixe, e7f0029, et c'est là que se lit le résultat : un seul et même Freight a franchi les deux étages. La colonne PHASE dit où en est chaque ordre, et Succeeded signifie que toutes les étapes du promotionTemplate ont abouti.
Où se place la validation humaine
Section intitulée « Où se place la validation humaine »Rien ne se promeut tout seul. C'est le point que l'on suppose souvent à l'envers : autoPromotionEnabled vaut false par défaut, et la documentation du champ le dit sans ambiguïté sur le cluster.
kubectl explain projectconfig.spec.promotionPolicies.autoPromotionEnabledfield defaults to false, but is commonly set to true for Stages thatsubscribe to Warehouses instead of other, upstream Stages.Autrement dit, la validation humaine est le comportement par défaut : sans Promotion créée par quelqu'un, en ligne de commande ou depuis l'interface web, un Freight reste au quai. C'est l'automatisation qui s'active explicitement, pas l'inverse. L'usage courant consiste à l'ouvrir sur le premier étage, celui qui s'abonne au Warehouse, et à la laisser fermée ensuite.
apiVersion: kargo.akuity.io/v1alpha1kind: ProjectConfigmetadata: name: demo namespace: demospec: promotionPolicies: - stageSelector: name: test autoPromotionEnabled: true # test suit le Warehouse # prod n'apparaît pas : il reste manuelL'approbation, qui est autre chose
Section intitulée « L'approbation, qui est autre chose »Approuver n'est pas promouvoir, et la distinction se paie cher si on la manque. L'approbation manuelle sert au correctif urgent : elle autorise un Freight à sauter des étages du pipeline.
kargo approve --project demo --freight <identifiant> --stage prodCette commande n'est pas kubectl : elle vient de la CLI kargo, un binaire distinct que le projet publie pour Linux, macOS et Windows, et qui s'installe à part. Tout le reste de cette page s'en passe volontairement, pour ne dépendre que de l'API Kubernetes.
Trois limites à connaître, toutes trois documentées par le projet :
- l'approbation ne crée aucune
Promotion: elle lève une condition, elle ne déclenche rien ; - elle contourne les vérifications seulement. Le Stage doit toujours réclamer le Freight depuis son origine, sinon l'approbation échoue ;
- elle exige les mêmes droits qu'une promotion vers ce Stage, ce qui évite qu'une approbation serve de porte dérobée.
Le statut du Freight distingue ces trois situations, et c'est là qu'on lit ce qui s'est réellement passé :
| Champ | Ce qu'il dit |
|---|---|
currentlyIn | Les Stages où ce Freight se trouve maintenant |
verifiedIn | Les Stages qui l'ont validé par le parcours normal |
approvedFor | Les Stages pour lesquels un humain l'a approuvé d'avance, hors parcours |
Une entrée dans approvedFor est donc une trace d'exception, et c'est exactement ce qu'on veut auditer après coup : elle nomme le raccourci pris, quand verifiedIn ne décrit que le chemin nominal.
Dépannage
Section intitulée « Dépannage »Les quatre messages ci-dessous couvrent l'essentiel des blocages d'une première installation. Les deux premiers n'évoquent en rien leur cause réelle, ce qui les rend coûteux : ils parlent de droits d'accès quand le problème est une version d'outil ou un jeton périmé.
| Message | Cause réelle | Correction |
|---|---|---|
401 Unauthorized sur le chart | Helm antérieur à 3.13.1, qui gère mal les registres OCI | Mettre Helm à jour, le message ne parle pas de version |
403 Forbidden sur le chart | Jeton ghcr.io expiré dans la configuration Docker | Se déconnecter de ghcr.io : le chart est public, l'anonyme fonctionne |
cannot re-use a name that is still in use | helm install sur un release déjà présent | Utiliser helm upgrade --install, qui vaut pour les deux cas |
steps in body should have at least 1 items | promotionTemplate sans aucune étape | Ajouter au moins une étape, même triviale |
Le troisième mérite une mention : il ne se rencontre pas à la première installation, mais à la deuxième, quand on rejoue une procédure sur un cluster qui porte déjà Kargo. C'est la raison pour laquelle ce guide écrit helm upgrade --install partout.
Faut-il adopter Kargo ?
Section intitulée « Faut-il adopter Kargo ? »Kargo n'a aujourd'hui aucun concurrent open source direct et vivant, ce qui est autant un argument pour que contre : le créneau est peu disputé, mais l'outil est jeune.
| Solution | État | Ce qu'elle couvre |
|---|---|---|
| Argo CD Image Updater | actif | Met à jour un tag d'image. Une brique, pas une chaîne d'environnements |
| Flux image-automation | actif | L'équivalent côté Flux, même périmètre réduit |
| Spinnaker | actif | Plateforme de livraison multi-cloud, d'une tout autre ampleur, antérieure au GitOps |
| KubeVela | actif | Plateforme applicative avec workflows multi-environnements |
| Keptn | archivé | Orchestration multi-étages pilotée par SLO |
| Telefonistka | archivé | Promotion GitOps entre environnements, le plus proche conceptuellement |
Trois questions tranchent. Promouvez-vous un ensemble de versions plutôt qu'une image isolée ? Avez-vous plus de deux environnements en file ? Voulez-vous que la règle « rien ne passe en production sans être passé en recette » soit appliquée par l'API plutôt que par une revue humaine ? Trois oui désignent Kargo. Un seul non, et Argo CD seul avec des pull requests de promotion vous coûtera moins cher en exploitation.
À retenir
Section intitulée « À retenir »- Kargo promeut, il ne déploie pas : il décide ce qui passe à l'étape suivante, votre outil GitOps applique
- Le chart vient d'un registre OCI, il s'épingle avec
--version, ethelm upgrade --installévite l'échec au deuxième passage - cert-manager est un vrai prérequis : Kargo lui demande trois certificats pour ses webhooks
- L'installation pose cinq déploiements et neuf ressources personnalisées, ce n'est pas un composant d'appoint
- Le Freight fige un ensemble de versions, c'est lui qui voyage d'un environnement au suivant
- Un Stage exige au moins une étape de promotion, un
steps: []est refusé - Kargo impose son propre nom de Promotion, celui que vous demandez est ignoré
- Le champ
verifiedInest ce qui autorise l'environnement suivant à réclamer un Freight - Rien ne se promeut tout seul :
autoPromotionEnabledvautfalsepar défaut, la validation humaine est le comportement natif - Approuver n'est pas promouvoir :
kargo approvelève les vérifications pour un correctif urgent, sans créer de Promotion
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Déploiements progressifs : le canary et le blue-green, qui décident comment un Freight promu atteint ses utilisateurs.
- Rollback et reprise : revenir en arrière quand la promotion a livré un défaut en production.
- Admission Controllers : les webhooks qui filtrent les écritures, du même ordre que ceux que Kargo installe.