Aller au contenu
English
Conteneurs & Orchestration medium

CRD et Helm : qui possède le cycle de vie ?

55 min de lecture

logo helm

Une CRD placée dans le dossier crds/ n'appartient pas à votre release : Helm l'installe, puis ne la met plus jamais à jour et ne la supprime jamais. C'est le comportement qui surprend le plus d'exploitants, et c'est celui que ce guide établit par la mesure, avec les sept questions que pose tout chart contenant une CustomResourceDefinition.

  • Distinguer ce que Helm fait de crds/ et de templates/
  • Prévoir l'effet d'un upgrade et d'un uninstall sur une CRD
  • Reconnaître le message qui signale une CRD manquante
  • Décider à qui confier le cycle de vie d'une CRD
  • Choisir entre les deux emplacements, en connaissant le prix de chacun
  • Savoir installer et mettre à jour une release (voir Lifecycle)
  • Savoir ce qu'est une CustomResourceDefinition et une ressource personnalisée
  • Un cluster local, kind par exemple, où détruire une CRD est sans conséquence

Une CRD n'est pas une ressource comme les autres : elle crée un type. Tant qu'elle n'existe pas dans le cluster, l'API server ne sait pas ce qu'est un Widget, et rien ne peut en créer un.

Or Helm construit tous les objets d'un chart avant d'en appliquer un seul. Il doit donc résoudre chaque kind auprès de l'API, et cette résolution échoue pour la ressource personnalisée dont la CRD n'est pas encore posée. Le dossier crds/ existe pour casser cette boucle : son contenu part avant le reste, hors du rendu de templates.

Toutes les lignes ci-dessous ont été relevées avec Helm 4.3.0 sur un cluster kind en Kubernetes 1.37, avec le même chart déposé tantôt dans crds/, tantôt dans templates/.

QuestionCRD dans crds/CRD dans templates/
Rendue par helm templatenonoui
Installée avant les autres ressourcesouinon
Templatée, values interprétéesnonoui
Porte les métadonnées Helmnonoui, meta.helm.sh/release-name et managed-by: Helm
Présente dans helm get manifestnonoui
Mise à jour par helm upgradenonoui
Supprimée par helm uninstallnonoui, avec quelques secondes de latence
Concernée par --skip-crdsouinon

Deux lignes de ce tableau valent qu'on s'y arrête, parce qu'elles piègent en production.

Le rendu local ignore purement et simplement le dossier. Sur un chart qui contient une CRD et une ressource personnalisée, la sortie ne porte que la seconde :

Fenêtre de terminal
helm template essai ./mon-chart | grep -E '^kind:'
Sortie
kind: Widget

La CustomResourceDefinition n'apparaît nulle part. La conséquence est directe et coûte cher : helm template … | kubectl apply -f - n'installera jamais la CRD, et l'application échouera sur la ressource personnalisée. Ce mode de déploiement, courant en GitOps, demande donc d'appliquer les CRD séparément.

Modifier le schéma d'une CRD dans crds/ puis lancer un upgrade ne produit aucun effet sur le cluster. La release se met bien à jour, la commande sort en 0, et la CRD reste dans son état d'origine. Mesuré en ajoutant un champ au schéma : après l'upgrade, l'API server ne le connaît toujours pas.

C'est le message que produit toute CRD manquante, quelle qu'en soit la cause :

Sortie
Error: INSTALLATION FAILED: unable to build kubernetes objects from release
manifest: resource mapping not found for name: "premier" namespace: "" from "":
no matches for kind "Widget" in version "demo.local/v1"
ensure CRDs are installed first

La dernière ligne, ensure CRDs are installed first, est ajoutée par Helm lui-même. Trois situations produisent exactement ce message, et le diagnostic consiste à les départager :

  1. La CRD est dans templates/, avec la ressource personnalisée du même chart. Helm résout tous les kind avant d'appliquer quoi que ce soit : la CRD n'existe pas encore au moment où il cherche à mapper la CR. Le chart ne s'installera jamais, même sur un cluster neuf.

    Fenêtre de terminal
    ls mon-chart/templates/ | grep -i crd
  2. Vous avez passé --skip-crds sur un chart dont une ressource dépend de la CRD. Helm saute l'installation du dossier, puis bute sur la ressource orpheline.

  3. La CRD relève d'un autre composant, un opérateur installé à part par exemple, et ce composant n'est pas là.

    Fenêtre de terminal
    kubectl get crd | grep demo.local

L'option dit à Helm d'ignorer le dossier crds/. Elle sert quand quelqu'un d'autre possède les CRD : un opérateur déjà installé, une équipe plateforme qui les applique séparément, un cluster où vous n'avez pas le droit de créer des ressources à portée cluster.

Fenêtre de terminal
helm install mon-app ./mon-chart -n demo --skip-crds

Sur un chart dont une ressource dépend de la CRD absente, l'installation échoue avec le message ci-dessus. Ce n'est pas un défaut : c'est le drapeau qui fait son travail, et qui vous dit que le prérequis n'est pas rempli.

La vraie question n'est pas technique, elle est de gouvernance : une CRD est un objet à portée cluster, partagé par tous les namespaces. Deux releases du même chart dans deux namespaces se partagent la même CRD, et la dernière installée l'emporte.

Votre situationL'emplacement à retenir
Vous livrez un opérateur, la CRD est votre produitcrds/, et vous documentez la procédure de montée de version
Le chart consomme une CRD posée par un autreni l'un ni l'autre : documentez le prérequis, et vérifiez-le
La CRD n'existe que pour votre release, dans un cluster que vous maîtriseztemplates/, à condition qu'aucune CR du même chart n'en dépende
Vous déployez en GitOps par helm templateappliquez les CRD dans une étape séparée, en amont

Le motif retenu par les gros projets, cert-manager, Prometheus Operator ou Cilium, est le premier : la CRD vit dans crds/, et sa montée de version fait l'objet d'une section dédiée dans leurs notes de publication. Ils assument que Helm ne la fera pas pour vous.

Puisque Helm ne dira rien, le contrôle vous revient. Comparez ce que le chart livre à ce que le cluster sert, avant de monter de version :

Fenêtre de terminal
kubectl get crd widgets.demo.local -o jsonpath='{.spec.versions[*].name}'
Sortie
v1

Si le chart apporte une v2, la sortie ci-dessus le dira, et vous saurez qu'il faut appliquer la CRD à la main :

Fenêtre de terminal
kubectl apply -f mon-chart/crds/

Cette commande est idempotente et sans effet si rien n'a changé. La placer avant chaque helm upgrade d'un chart à CRD est le réflexe le moins coûteux.

  • Une CRD de crds/ est installée une fois, puis ignorée : ni upgrade, ni uninstall, ni métadonnées Helm
  • helm template ne rend pas crds/ : un déploiement GitOps par rendu local n'installera jamais la CRD
  • Une CRD de templates/ est suivie normalement, mais le chart échoue si une ressource du même chart en dépend
  • Le message no matches for kind ... ensure CRDs are installed first a trois causes à départager
  • --skip-crds sert quand la CRD appartient à quelqu'un d'autre ; il ne répare rien
  • Il n'existe aucune option pour faire monter une CRD de version : c'est kubectl apply en dehors de Helm
  • Une CRD est à portée cluster : deux releases dans deux namespaces se partagent la même

Sept questions sur ce que Helm fait réellement d'une CRD : ce que helm upgrade change dans crds/, ce que helm template en montre, et laquelle des trois causes produit le message ensure CRDs are installed first.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

7 questions
5 min.
80% requis

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

  • Qualité, schéma et documentation : kubeconform valide les manifestes rendus contre le schéma de l'API, et ne connaît donc aucune ressource personnalisée. Une CRD dans crds/ échappe doublement à la chaîne de qualité.
  • Droits RBAC et secrets de release : une CRD est à portée cluster, son installation demande donc des droits qu'un compte confiné dans son namespace n'a pas.
  • Packaging et promotion en CI/CD : c'est là que se décide l'étape séparée qui applique les CRD avant le chart, quand la chaîne déploie par rendu local.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn