Featured image of post HelmRelease vs Kustomization dans FluxCD

HelmRelease vs Kustomization dans FluxCD

HelmRelease déploie un chart Helm packagé, Kustomization applique des manifests bruts (avec overlays) — les deux se combinent plutôt que de s'exclure.

Contexte

En mettant en place FluxCD sur un cluster, je me suis retrouvé avec deux façons de déclarer ce que je veux déployer : Kustomization et HelmRelease. Les deux apparaissent dans quasiment tous les repos GitOps Flux, mais elles ne font pas la même chose.

Ce que j’ai appris

Kustomization (la CR Flux, pas l’objet Kustomize natif) applique des manifests YAML bruts depuis un GitRepository, en passant éventuellement par des overlays Kustomize. HelmRelease déploie un chart Helm depuis une HelmRepository/OCIRepository, avec ses values et son cycle de vie (install/upgrade/rollback) géré par le Helm controller. Une bonne partie des repos Flux utilisent en réalité les deux : une Kustomization qui, elle-même, applique des fichiers HelmRelease.yaml.

Détails

Deux ressources Flux distinctes, avec des controllers différents (kustomize-controller vs helm-controller) :

# Kustomization : applique des manifests bruts (ou un overlay Kustomize)
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps-infra
  namespace: flux-system
spec:
  interval: 10m
  path: ./clusters/prod/infra
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system
---
# HelmRelease : déploie un chart Helm avec ses values
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  interval: 10m
  chart:
    spec:
      chart: ingress-nginx
      version: "4.11.x"
      sourceRef:
        kind: HelmRepository
        name: ingress-nginx
  values:
    controller:
      replicaCount: 2

Organisation qui fonctionne bien en pratique :

  • clusters/<env>/ : une ou deux Kustomization racines par cluster, qui pointent vers apps/ et infra/.
  • infra/<outil>/ : un dossier par outil tiers packagé en chart (ingress-nginx, cert-manager, prometheus…) contenant sa HelmRelease.yaml + une HelmRepository/OCIRepository associée.
  • apps/<app>/base + apps/<app>/overlays/<env> : manifests maison, gérés en Kustomize natif, appliqués via une Kustomization Flux par environnement.

Règle simple : si ça vient d’un chart Helm publié par un tiers, HelmRelease ; si c’est du YAML qu’on écrit et qu’on veut décliner par environnement, Kustomization + overlays.

Que réconcilier après une modification ?

J’ai mis à jour la chart (nouvelle version dans HelmRelease.spec.chart.spec, ou nouvelle version poussée dans le repo Helm/OCI) → Flux ne voit la nouvelle version qu’au prochain polling de la HelmRepository/OCIRepository. Il faut réconcilier la source, puis le HelmChart généré, puis la HelmRelease — le flag --with-source fait les trois d’un coup :

flux reconcile helmrelease ingress-nginx -n ingress-nginx --with-source

J’ai mis à jour les values de la HelmRelease → ces values vivent dans le manifest Git de la HelmRelease, appliqué par une Kustomization Flux. Pas de nouvelle version de chart à récupérer, juste le commit à relire : réconcilier la Kustomization suffit, le helm-controller détecte le changement de génération sur la HelmRelease et relance l’upgrade tout seul :

flux reconcile kustomization apps-infra --with-source

Inutile d’appeler flux reconcile helmrelease dans ce second cas : dès que le nouveau commit est appliqué, le bump de génération suffit à déclencher le reconcile.

Une Kustomization par app ou par environnement ?

Plutôt une Kustomization par app (ou par composant infra) qu’une seule grosse par environnement. Avec une Kustomization par unité, chaque app a son propre health check, son propre prune et peut être reconciliée ou rollback indépendamment ; avec une seule Kustomization pour tout un env, un healthcheck qui échoue ou un prune: true mal maîtrisé impacte tout le lot d’un coup, et Flux ne peut pas ordonner finement les dépendances entre apps.

En pratique : une Kustomization par composant infra (cert-manager, ingress-nginx…) et une par app métier, reliées par dependsOn quand l’ordre compte (les apps dépendent souvent de l’infra) :

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps-checkout
  namespace: flux-system
spec:
  interval: 10m
  path: ./apps/checkout/overlays/prod
  prune: true
  dependsOn:
    - name: infra-ingress-nginx
  sourceRef:
    kind: GitRepository
    name: flux-system

Ne grouper que ce qui est vraiment couplé et doit vivre/mourir ensemble, pas juste “tout ce qui tourne dans cet environnement”.

Pourquoi c’est utile

Ça évite deux pièges : réécrire en YAML brut des charts tiers complexes (perdre les hooks, les valeurs par défaut du chart, les mises à jour de version), et à l’inverse forcer des manifests maison dans un chart Helm juste pour “faire comme Flux”. Séparer clairement infra/ (HelmRelease) et apps/ (Kustomization + overlays) rend le repo GitOps beaucoup plus lisible.

Sources

Généré avec Hugo
Thème Stack conçu par Jimmy