En corto

1
2
3
4
5
6
export HELM_DIFF_THREE_WAY_MERGE=true        # diff contra lo que hay en el clúster, no contra el último release
export HELM_DIFF_NORMALIZE_MANIFESTS=true    # quita ruido de formato del diff
export HELMFILE_GOCCY_GOYAML=true            # helmfile 0.x: evita "key already set in map"

helmfile -e prod -l name=rabbitmq diff        # una sola release
helmfile -e prod apply --skip-diff-on-install # primera instalación gigante sin diff

Y en CI, versiones fijas de las tres piezas (helm, helmfile, helm-diff): la mitad de los errores raros de helmfile son combinaciones que no se han probado juntas.

Los errores y qué los arregla

MensajeCausaArreglo
helmfile diff dice que no hay cambios, pero el clúster no coincide con el charthelm-diff compara el manifiesto del último release con el nuevo, no con el estado vivo; un kubectl edit a mano no apareceHELM_DIFF_THREE_WAY_MERGE=true (o --three-way-merge en helm-diff)
El diff está lleno de cambios de comillas, orden de claves e indentaciónDistintas versiones de Helm o del chart serializan distintoHELM_DIFF_NORMALIZE_MANIFESTS=true
key "image" already set in map al renderizar valoresLa librería YAML antigua no admite claves duplicadas ni ciertos anclajes en valuesHELMFILE_GOCCY_GOYAML=true en helmfile 0.x; helmfile 1.x ya usa esa librería
Body is too long (maximum is 65536 characters) o el job se eterniza en la primera instalaciónEl diff de una instalación nueva es el chart entero, y el comentario en la PR o el log no lo aguantan--skip-diff-on-install
Error: failed to authorize: … 403 Forbidden al bajar un chart de oci://ghcr.io/…Helm anterior a 3.8 con soporte OCI experimental, o sin helm registry loginActualizar helm; helm registry login ghcr.io si el registro es privado
Error: validation: more than one dependency with name or aliasDesajuste entre helm y helmfile (helm 3.15 necesitó helmfile ≥ 0.164; helm 3.13 iba con 0.158)Actualizar helmfile a la par que helm; en 1.x ya no ocurre
El diff sale sin color en CIhelm-diff detecta que no hay TTYHELM_DIFF_COLOR=true

Adoptar recursos que ya existen

El caso típico: alguien instaló ArgoCD (o lo que sea) con kubectl apply -f, y ahora quieres que lo gestione una release de helmfile. Helm se niega a instalar sobre recursos que no son suyos (rendered manifests contain a resource that already exists … invalid ownership metadata). Desde Helm 3.2 basta con marcarlos como suyos antes de instalar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
NS=argocd; REL=argocd
for kind in deploy sts svc cm secret sa ingress role rolebinding networkpolicy; do
  kubectl -n $NS get $kind -o name 2>/dev/null | while read -r r; do
    kubectl -n $NS label "$r" app.kubernetes.io/managed-by=Helm --overwrite
    kubectl -n $NS annotate "$r" meta.helm.sh/release-name=$REL meta.helm.sh/release-namespace=$NS --overwrite
  done
done
# recursos de clúster: mismas etiquetas, sin -n
for r in $(kubectl get crd,clusterrole,clusterrolebinding -o name | grep -i argo); do
  kubectl label "$r" app.kubernetes.io/managed-by=Helm --overwrite
  kubectl annotate "$r" meta.helm.sh/release-name=$REL meta.helm.sh/release-namespace=$NS --overwrite
done
helmfile -e prod -l name=$REL diff     # debería ser casi vacío
helmfile -e prod -l name=$REL apply

Solo marca lo que el chart va a renderizar: un recurso etiquetado que el chart no incluye no pasa nada, pero uno que el chart renderiza con otro nombre acaba duplicado.

helmfile 1.x y Helm 4

Si vienes de 0.x, esto es lo que cambia al actualizar:

  • Un helmfile.yaml con plantillas Go tiene que llamarse helmfile.yaml.gotmpl; el .yaml a secas ya no se renderiza.
  • environments: y releases: van en partes separadas por --- dentro del mismo archivo.
  • helmfile delete desaparece (es destroy), helmfile charts también, y --args se elimina.
  • HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS pasa a ser HELMFILE_DISABLE_INSECURE_FEATURES.
  • helmfile 1.x funciona con Helm 3 y Helm 4. Con Helm 4, instala helm-diff con helm plugin install https://github.com/databus23/helm-diff --verify=false (Helm 4 verifica la procedencia de los plugins y helm-diff no la publica).

Trampas

  • apply sin diff previo en CI: helmfile apply ya hace el diff y solo aplica si hay cambios; sync aplica siempre. En pipelines, diff en la PR y apply en main.
  • installed: false desinstala la release en el siguiente apply; útil para retirar cosas por Git, peligroso si lo copias de otro entorno.
  • Secretos en values: helmfile los deja en el manifiesto del release (Secret de Helm en el namespace); usa helm-secrets con SOPS o referencias externas.
  • --skip-diff-on-install no es --skip-diff: solo se salta el diff en releases que aún no existen. Las actualizaciones siguen mostrando su diff.
  • Tres binarios, tres versiones: helm version, helmfile version y helm plugin list en el primer paso del pipeline, y en la imagen de CI fijadas por tag.

Referencias: helm-diff, helmfile y la propuesta de cambios para 1.0.

Ver también