Automatiser le cycle de vie des charts Helm en CI/CD garantit la qualité (lint, tests), la reproductibilité (versioning automatique), et la traçabilité (qui a publié quoi, quand). Ce module présente une pipeline complète avec GitLab CI et GitHub Actions, ainsi que les patterns de promotion dev → staging → prod.
Prérequis
Section intitulée « Prérequis »- Un repo Git contenant vos charts
- Accès à un registry OCI (Harbor, GHCR, ECR)
- Module 10, OCI registries
- Module 11, Provenance (optionnel)
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Architecture d'une pipeline Helm
- Étape 1 : Lint et validation
- Étape 2 : Tests de chart
- Étape 3 : Package et versioning
- Étape 4 : Publish sur registry
- Promotion multi-environnements
- Intégration GitOps
Architecture d'une pipeline Helm
Section intitulée « Architecture d'une pipeline Helm »Un chart Helm est un artefact versionné, au même titre qu'une image de conteneur : il se valide, se construit, se publie, puis se consomme par sa version. La chaîne reprend donc les étapes classiques d'une livraison logicielle, appliquées à un paquet YAML. Le déploiement est volontairement séparé : rien n'oblige la chaîne qui publie à être celle qui installe.
Workflow standard
Section intitulée « Workflow standard »Les quatre premières étapes s'enchaînent sans intervention et produisent un chart publié. La cinquième, en pointillés sur le schéma, dépend de votre modèle de déploiement : elle appartient souvent à une autre chaîne, voire à un outil GitOps.
Ce que fait chaque étape
Section intitulée « Ce que fait chaque étape »Chaque étape ne valide qu'une seule chose, et échoue vite si cette chose ne va pas. Ce découpage a une raison très pratique : quand la chaîne casse, le nom du job suffit à savoir ce qui est en cause, sans lire les journaux.
| Étape | Outils | Objectif |
|---|---|---|
| Lint | helm lint, ct lint | Syntaxe YAML, bonnes pratiques |
| Test | helm template, kubeval, kubeconform | Manifests K8s valides |
| Package | helm package | Créer le .tgz versionné |
| Publish | helm push | Pousser sur registry OCI |
| Deploy | helm upgrade --install ou GitOps | Déployer sur cluster |
Étape 1 : Lint et validation
Section intitulée « Étape 1 : Lint et validation »Le lint contrôle le chart en tant que paquet : présence et cohérence du Chart.yaml, structure des répertoires, syntaxe des templates, conformité des values au schéma déclaré. Il ne dit rien de la validité Kubernetes des manifestes produits, qui est le rôle de l'étape suivante. C'est le job le plus rapide, à placer en premier.
helm lint (basique)
Section intitulée « helm lint (basique) »Sans --strict, helm lint sort en succès malgré des avertissements ; en CI, c'est ce qui laisse passer les problèmes.
# Lint un charthelm lint ./charts/my-app
# Lint strict (warnings = erreurs)helm lint ./charts/my-app --strictChart Testing (ct), recommandé
Section intitulée « Chart Testing (ct), recommandé »Chart Testing (ct) est l'outil officiel pour tester des charts en CI :
# Installer ctpip install chart-testing
# Lint tous les charts modifiésct lint --config .ct.yaml
# Lint tous les chartsct lint --all --config .ct.yamlConfiguration .ct.yaml :
chart-dirs: - chartsvalidate-maintainers: falsevalidate-chart-schema: truelint-conf: - --strictValidation du schema (values)
Section intitulée « Validation du schema (values) »Un fichier values.schema.json placé à la racine du chart décrit les valeurs attendues, leurs types et celles qui sont obligatoires. Helm l'applique automatiquement, sans option supplémentaire, et refuse un jeu de values non conforme.
# Si values.schema.json existehelm lint ./charts/my-app # Valide automatiquement les valuesÉtape 2 : Tests de chart
Section intitulée « Étape 2 : Tests de chart »Un chart peut passer le lint et produire des manifestes que Kubernetes refusera. Cette étape rend les templates hors cluster, puis confronte le YAML obtenu aux schémas de l'API. Elle ne demande aucun accès à un cluster, ce qui la rend exécutable sur n'importe quel agent.
helm template (rendu local)
Section intitulée « helm template (rendu local) »La commande écrit les manifestes rendus sur la sortie standard et renvoie un code de retour non nul en cas d'erreur de template, ce qui suffit à faire échouer le job sans traitement supplémentaire :
# Générer les manifests sans clusterhelm template my-app ./charts/my-app -f values-test.yaml > rendered.yaml
# Vérifier que ça génère du YAML validehelm template my-app ./charts/my-app > /dev/nullecho $? # 0 = OKValidation des manifests K8s
Section intitulée « Validation des manifests K8s »Deux validateurs consomment le YAML rendu et le comparent aux schémas OpenAPI de Kubernetes. kubeconform est le choix par défaut aujourd'hui : maintenu, rapide, et capable de gérer les ressources personnalisées via des schémas additionnels. kubeval rend le même service, mais son dépôt n'est plus actif.
# Installer kubeconform (rapide, maintenu)# https://github.com/yannh/kubeconform
helm template my-app ./charts/my-app | kubeconform -strict -summary# Installer kubeval# https://github.com/instrumenta/kubeval
helm template my-app ./charts/my-app | kubeval --strictTests helm (intégration)
Section intitulée « Tests helm (intégration) »Dernier niveau, et le seul qui exige un vrai cluster : Helm installe la release, puis exécute les Pods portant l'annotation helm.sh/hook: test, et considère le test réussi si leur conteneur sort en code 0. C'est ce code de retour qui fait échouer l'étape, pas le contenu des journaux.
# Déployer puis testerhelm install my-app ./charts/my-app -n test --waithelm test my-app -n testhelm uninstall my-app -n testÉtape 3 : Package et versioning
Section intitulée « Étape 3 : Package et versioning »Le champ version du Chart.yaml est ce qui identifie le chart sur le registre, et un registre OCI refuse d'écraser une version déjà publiée. Toute la difficulté du packaging tient donc à une seule question : qui décide du numéro. Le champ appVersion, lui, désigne la version de l'application et évolue indépendamment.
Versioning automatique
Section intitulée « Versioning automatique »Trois approches, du plus simple au plus automatisé. La première repose sur la discipline humaine et finit toujours par produire un oubli ; les deux autres dérivent le numéro de l'historique Git, ce qui le rend reproductible et vérifiable.
Option 1 : Version depuis Chart.yaml (manuelle)
version: 1.2.3 # Incrémenter manuellementappVersion: "2.0.0"Option 2 : Version depuis Git tag
# Récupérer la version depuis le tag GitVERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
# Remplacer dans Chart.yamlsed -i "s/^version:.*/version: $VERSION/" charts/my-app/Chart.yaml
# Packagerhelm package ./charts/my-appOption 3 : Semantic Release
# .releaserc.yaml pour semantic-releaseplugins: - "@semantic-release/commit-analyzer" - "@semantic-release/release-notes-generator" - ["@semantic-release/exec", { "prepareCmd": "sed -i 's/^version:.*/version: ${nextRelease.version}/' charts/my-app/Chart.yaml" }]Package avec métadonnées
Section intitulée « Package avec métadonnées »helm package produit une archive nommée d'après le nom et la version du chart, dans le répertoire courant. C'est ce fichier, et lui seul, qui sera poussé sur le registre : tout ce qui n'y est pas n'existe pas pour le consommateur.
# Packagerhelm package ./charts/my-app
# Résultat : my-app-1.2.3.tgzLes deux drapeaux --version et --app-version évitent le sed -i de l'option 2 : ils surchargent les champs du Chart.yaml au moment de l'empaquetage, sans jamais toucher le fichier du dépôt. Mesuré sur Helm v4.1.0, un chart nommé my-app en version: 0.1.0 :
helm package ./charts/my-app --version 9.9.9 --app-version 7.7.7L'archive s'appelle my-app-9.9.9.tgz et le Chart.yaml qu'elle contient porte version: 9.9.9 et appVersion: 7.7.7, tandis que charts/my-app/Chart.yaml reste sur 0.1.0 dans le dépôt. C'est exactement ce que réclame une chaîne d'intégration : dériver le numéro du tag Git ou du numéro de construction, sans commit de version et donc sans le commit de retour qui déclencherait la pipeline suivante.
Étape 4 : Publish sur registry
Section intitulée « Étape 4 : Publish sur registry »Depuis Helm 3.8, un chart se publie sur un registre OCI, la même infrastructure que celle qui héberge vos images de conteneurs. Vous réutilisez donc l'authentification, les quotas et les politiques de rétention déjà en place, sans serveur de charts dédié à maintenir.
Push OCI
Section intitulée « Push OCI »Le mot de passe transite par l'entrée standard avec --password-stdin : passé en argument, il apparaîtrait dans la liste des processus et dans les journaux de l'agent, où il resterait bien après la fin du job.
# Login (une fois par job)echo "$REGISTRY_PASSWORD" | helm registry login $REGISTRY_URL -u $REGISTRY_USER --password-stdin
# Pushhelm push my-app-1.2.3.tgz oci://$REGISTRY_URL/chartsVérification post-push
Section intitulée « Vérification post-push »Un push réussi ne garantit pas que le chart soit lisible par ses consommateurs, notamment si les droits du dépôt sont restreints. Cette lecture depuis le registre ferme la boucle, et c'est la seule façon de vérifier ce que verra quelqu'un d'autre :
# Vérifier que le chart est accessiblehelm show chart oci://$REGISTRY_URL/charts/my-app --version 1.2.3Pipeline complète GitLab CI
Section intitulée « Pipeline complète GitLab CI »Ce fichier assemble les quatre étapes précédentes en autant de stages. Deux mécanismes structurent l'ensemble : le modèle .helm-base, réutilisé par extends pour ne déclarer l'image qu'une fois, et les blocs rules, qui décident quand chaque job s'exécute. Le lint tourne sur les demandes de fusion, la publication uniquement sur un tag.
Notez que l'image n'est plus construite à partir d'une variable. Un épinglage par digest interdit l'interpolation : alpine/helm:${HELM_VERSION} désigne un tag mutable, que son éditeur peut redéplacer sur un autre contenu, alors que alpine/helm:4.3.0@sha256:… désigne un contenu précis. On perd la commodité d'une variable, on gagne la certitude que deux exécutions de la même pipeline utilisent le même binaire Helm.
Notez aussi les apostrophes autour de la commande sed, qui ne sont pas décoratives. Un élément de liste YAML non quoté qui contient une séquence deux-points suivie d'une espace est interprété comme un dictionnaire, pas comme une chaîne. Sans elles, GitLab refuse la pipeline avant de créer le moindre job :
jobs:package:script config should be a string or a nested array of stringsLe piège ne se voit pas à la lecture, puisque le sed est parfaitement valide côté shell. Il ne frappe que les éléments de liste : le workflow GitHub plus bas y échappe parce que son sed vit dans un bloc run: |, un scalaire littéral où les deux-points ne sont plus interprétés.
La forme longue de image, avec entrypoint: [""], n'est pas non plus un ornement. L'image alpine/helm déclare ENTRYPOINT ["helm"] : elle est faite pour s'utiliser comme un exécutable, pas comme un environnement de travail. Or GitLab Runner démarre le conteneur de job avec un shell, et la commande devient alors helm sh :
Error: unknown command "sh" for "helm"Le job meurt avant la première ligne du script. Neutraliser l'entrypoint rend l'image utilisable comme n'importe quelle autre. La règle vaut pour toute image d'outil dont l'entrypoint est le binaire lui-même, cas fréquent chez kubectl, terraform ou aws-cli.
Enfin, deux variables séparent l'hôte du chemin, et ce n'est pas une coquetterie non plus. helm registry login veut un nom d'hôte seul, helm push oci:// veut l'hôte suivi du chemin de dépôt. Réutiliser une seule variable pour les deux casse la connexion :
registry login currently only supports registry hostname, not a repository pathError: invalid reference: invalid registry "harbor.example.com/charts"C'est la même règle que le guide de migration énonce pour l'authentification OCI en v4, et que le workflow GitHub plus bas applique déjà, avec REGISTRY d'un côté et REGISTRY_PATH de l'autre.
Enfin, ${CI_COMMIT_TAG#v} retire le v du tag. Un tag Git s'écrit par convention v1.2.3, une version de chart est du SemVer nu, 1.2.3. Sans cette coupe, le chart publié porte version: v1.2.3 et ne correspond plus à ce que produit le workflow GitHub à partir du même tag. Deux chaînes du même dépôt livreraient alors deux versions différentes de la même chose.
stages: - lint - test - package - publish
variables: CHART_PATH: "charts/my-app" REGISTRY_HOST: "harbor.example.com" REGISTRY_PATH: "charts"
.helm-base: image: name: alpine/helm:4.3.0@sha256:a6cf54599ccb99d90cf0712b30f03fdb3cab062e6b94e0418cc4db7e8a1464b2 entrypoint: [""] before_script: - helm version --short
lint: extends: .helm-base stage: lint script: - helm lint ${CHART_PATH} --strict - helm template test ${CHART_PATH} > /dev/null rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
test: extends: .helm-base stage: test image: alpine:3.24.1@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b before_script: - apk add --no-cache helm curl - curl -sL https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | tar xz - mv kubeconform /usr/local/bin/ script: - helm template test ${CHART_PATH} | kubeconform -strict -summary rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
package: extends: .helm-base stage: package script: # Version depuis le tag Git ou CI_COMMIT_TAG - | if [ -n "$CI_COMMIT_TAG" ]; then VERSION=${CI_COMMIT_TAG#v} else VERSION="0.0.0-${CI_COMMIT_SHORT_SHA}" fi - 'sed -i "s/^version:.*/version: $VERSION/" ${CHART_PATH}/Chart.yaml' - helm package ${CHART_PATH} artifacts: paths: - "*.tgz" expire_in: 1 week rules: - if: $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
publish: extends: .helm-base stage: publish script: - echo "${REGISTRY_PASSWORD}" | helm registry login ${REGISTRY_HOST} -u ${REGISTRY_USER} --password-stdin - helm push *.tgz oci://${REGISTRY_HOST}/${REGISTRY_PATH} dependencies: - package rules: - if: $CI_COMMIT_TAGPipeline complète GitHub Actions
Section intitulée « Pipeline complète GitHub Actions »Même logique transposée aux workflows GitHub, avec deux différences. Les dépendances entre jobs s'expriment par needs plutôt que par des stages, et la publication vers GHCR ne réclame aucun secret à créer : le jeton fourni automatiquement suffit, à condition de lui accorder la permission packages: write.
name: Helm CI/CD
on: push: branches: [main] tags: ['v*'] pull_request: branches: [main]
permissions: {}
env: CHART_PATH: charts/my-app REGISTRY: ghcr.io REGISTRY_PATH: ${{ github.repository_owner }}/charts
jobs: lint: runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false
- name: Set up Helm uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 with: version: '4.3.0'
- name: Lint chart run: | helm lint ${{ env.CHART_PATH }} --strict helm template test ${{ env.CHART_PATH }} > /dev/null
test: runs-on: ubuntu-latest needs: lint permissions: contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false
- name: Set up Helm uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 with: version: '4.3.0'
- name: Install kubeconform run: | VERSION=v0.8.0 curl -fsSLO "https://github.com/yannh/kubeconform/releases/download/$VERSION/kubeconform-linux-amd64.tar.gz" curl -fsSLO "https://github.com/yannh/kubeconform/releases/download/$VERSION/CHECKSUMS" grep " kubeconform-linux-amd64.tar.gz$" CHECKSUMS | sha256sum -c - tar -xzf kubeconform-linux-amd64.tar.gz kubeconform sudo mv kubeconform /usr/local/bin/
- name: Validate manifests run: helm template test ${{ env.CHART_PATH }} | kubeconform -strict -summary
publish: runs-on: ubuntu-latest needs: test if: startsWith(github.ref, 'refs/tags/v') permissions: contents: read packages: write steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false
- name: Set up Helm uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 with: version: '4.3.0'
- name: Get version from tag id: version run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Update Chart.yaml version run: | sed -i "s/^version:.*/version: ${{ steps.version.outputs.VERSION }}/" ${{ env.CHART_PATH }}/Chart.yaml
- name: Package chart run: helm package ${{ env.CHART_PATH }}
- name: Login to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin
- name: Push chart run: helm push *.tgz oci://${{ env.REGISTRY }}/${{ env.REGISTRY_PATH }}Promotion multi-environnements
Section intitulée « Promotion multi-environnements »Promouvoir, c'est déployer exactement le même artefact d'un environnement au suivant, sans le reconstruire. Un chart repackagé entre la recette et la production n'est plus le chart testé, et la recette ne prouve alors plus rien. Seule la configuration change d'un environnement à l'autre, jamais la version du chart.
Pattern : même chart, values différents
Section intitulée « Pattern : même chart, values différents »Les fichiers de values vivent hors du chart, dans un répertoire dédié. Le chart reste ainsi générique et publiable tel quel, tandis que les particularités d'environnement restent visibles et relisibles dans le dépôt, au lieu d'être noyées dans les templates.
Répertoirecharts/
Répertoiremy-app/
- Chart.yaml
- values.yaml Defaults
Répertoiretemplates/
- …
Répertoirevalues/
- values-dev.yaml Dev overrides
- values-staging.yaml
- values-prod.yaml
Déploiement par environnement
Section intitulée « Déploiement par environnement »Les trois commandes sont identiques à deux détails près : le fichier de values et le namespace. Le --version reste le même partout, et c'est précisément ce qui fait la promotion. La forme upgrade --install installe la release si elle n'existe pas et la met à jour sinon, ce qui rend la commande rejouable :
# Dev (automatique sur main)helm upgrade --install my-app oci://registry/charts/my-app \ --version 1.2.3 \ -f values/values-dev.yaml \ -n dev
# Staging (manuel ou tag)helm upgrade --install my-app oci://registry/charts/my-app \ --version 1.2.3 \ -f values/values-staging.yaml \ -n staging
# Prod (approval + tag)helm upgrade --install my-app oci://registry/charts/my-app \ --version 1.2.3 \ -f values/values-prod.yaml \ -n prodPipeline avec gates
Section intitulée « Pipeline avec gates »La mise en production ne doit pas se déclencher toute seule. Le mot-clé when: manual transforme le job en bouton à cliquer, et le bloc environment fait apparaître la release dans le suivi des environnements, avec son historique de déploiements.
# GitLab CI - promotion avec approvaldeploy-staging: stage: deploy script: - helm upgrade --install my-app oci://${REGISTRY}/my-app --version ${VERSION} -f values/values-staging.yaml -n staging environment: name: staging rules: - if: $CI_COMMIT_TAG
deploy-prod: stage: deploy script: - helm upgrade --install my-app oci://${REGISTRY}/my-app --version ${VERSION} -f values/values-prod.yaml -n prod environment: name: production when: manual # Approval requis rules: - if: $CI_COMMIT_TAGIntégration GitOps
Section intitulée « Intégration GitOps »Dans les chaînes précédentes, c'est l'agent d'intégration continue qui détient les accès au cluster et pousse les changements. L'approche GitOps inverse ce sens : un agent installé dans le cluster surveille une source de vérité et applique lui-même l'état déclaré. La chaîne s'arrête alors à la publication du chart, et plus aucun identifiant de cluster ne circule dans ses variables.
Argo CD avec Helm
Section intitulée « Argo CD avec Helm »Argo CD consomme le chart directement depuis le registre OCI : le champ targetRevision porte la version du chart, et syncPolicy.automated avec selfHeal ramène le cluster à l'état déclaré si quelqu'un le modifie à la main.
# Application Argo CDapiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: my-app namespace: argocdspec: project: default source: repoURL: oci://harbor.example.com/charts chart: my-app targetRevision: 1.2.3 helm: valueFiles: - values-prod.yaml destination: server: https://kubernetes.default.svc namespace: prod syncPolicy: automated: prune: true selfHeal: trueFlux avec HelmRelease
Section intitulée « Flux avec HelmRelease »Flux exprime la même intention avec une ressource HelmRelease, qui référence une source déclarée séparément. Le champ interval fixe la fréquence de réconciliation, ici toutes les cinq minutes.
# HelmRelease FluxapiVersion: helm.toolkit.fluxcd.io/v2kind: HelmReleasemetadata: name: my-app namespace: prodspec: interval: 5m chart: spec: chart: my-app version: "1.2.3" sourceRef: kind: HelmRepository name: my-charts namespace: flux-system values: replicaCount: 3 # ... prod valuesLab C3, Pipeline CI/CD complète
Section intitulée « Lab C3, Pipeline CI/CD complète »Ce lab met bout à bout tout ce qui précède sur un chart généré par helm create, donc valide dès le départ : l'objet de l'exercice est la chaîne, pas le chart. Comptez une trentaine de minutes, dont l'essentiel passe dans la configuration des accès au registre.
Objectif : Créer une pipeline qui lint, package et publie un chart sur push vers main ou tag.
-
Structure du repo
Fenêtre de terminal mkdir helm-cicd-lab && cd helm-cicd-labgit init# Créer un chartmkdir -p chartshelm create charts/my-app# Créer les values par envmkdir -p valuescp charts/my-app/values.yaml values/values-dev.yamlcp charts/my-app/values.yaml values/values-prod.yaml -
Créer la pipeline (GitLab ou GitHub selon votre environnement)
Copier le fichier
.gitlab-ci.ymlou.github/workflows/helm.ymlci-dessus. -
Configurer les secrets
-
GitLab : Settings → CI/CD → Variables
REGISTRY_URLREGISTRY_USERREGISTRY_PASSWORD
-
GitHub : Settings → Secrets and variables → Actions
GITHUB_TOKENest automatique pour GHCR
-
-
Pousser et déclencher
Fenêtre de terminal git add .git commit -m "feat: initial chart"git push origin main# Créer un tag pour publishgit tag v0.1.0git push origin v0.1.0 -
Vérifier
- Pipeline lint/test passe
- Chart publié sur le registry
helm show chart oci://registry/charts/my-app --version 0.1.0
Critères de réussite :
- Pipeline déclenchée sur push
-
helm lintexécuté sans erreur - Manifests validés avec kubeconform
- Chart packagé et versionné depuis le tag
- Publication automatique vers registry OCI
À retenir
Section intitulée « À retenir »- Lint :
helm lint --strict+ct lintpour la qualité - Test :
helm template+kubeconformpour valider les manifests - Package : versioning automatique depuis Git tag
- Publish :
helm pushvers registry OCI - Promotion : même chart, values différents par environnement
- GitOps : Argo CD / Flux pour les déploiements prod (recommandé)
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Trois questions sur l'industrialisation : le rôle d'index.yaml, l'ordre des étapes d'une chaîne, et pourquoi --strict s'impose en intégration continue.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Flux CD : Laisser un opérateur déployer le chart depuis Git plutôt qu'un job de pipeline.
- GitLab CI : Les mécanismes de pipeline sur lesquels s'appuie ce packaging.
- GitHub Actions : La même chaîne, côté GitHub.