INFRA

Helm: Gestión de Paquetes para Kubernetes

Guía completa de Helm — el gestor de paquetes para Kubernetes. Charts, values, templates Go, repositorios, hooks, tests, gestión de secrets, umbrella charts para flotas de microservicios, Helmfile, y estrategias de rollback probadas en batalla.

Por Jose Nobile | Actualizado 2026-06-11 | 18 min de lectura

Charts, Values y Templates

Un chart de Helm es un directorio que contiene manifiestos Kubernetes templatizados con templates Go, un archivo values.yaml con valores por defecto, y metadata en Chart.yaml. Los charts empaquetan todo lo necesario para desplegar una aplicación: Deployments, Services, ConfigMaps, Ingress, HPA, RBAC — todo parametrizado a través de values. En vez de mantener 15 archivos YAML crudos por microservicio, mantienes un chart con values configurables.

El archivo values.yaml define cada parámetro configurable con defaults sensatos. Al momento de instalar, los usuarios sobreescriben values específicos con --set key=value o -f custom-values.yaml. Esta separación de template y configuración es el poder central de Helm: el mismo chart despliega en desarrollo, staging y producción con diferentes archivos de values para cada ambiente.

La estructura del chart sigue una convención estricta: templates/ para manifiestos Kubernetes, charts/ para dependencias de sub-charts, crds/ para Custom Resource Definitions, y Chart.yaml para metadata (nombre, versión, appVersion, dependencias). El archivo _helpers.tpl dentro de templates/ define snippets de template reutilizables (labels, selectores, nombres) que mantienen tus manifiestos DRY.

my-service/
  Chart.yaml        # name, version, appVersion, dependencies
  values.yaml       # default configuration
  templates/
    _helpers.tpl     # reusable template snippets
    deployment.yaml  # Deployment manifest
    service.yaml     # Service manifest
    hpa.yaml         # HPA manifest
    ingress.yaml     # Ingress/Gateway rules
    configmap.yaml   # ConfigMap
    NOTES.txt        # Post-install message

Motor de Templates Go en Profundidad

Helm usa el paquete text/template de Go mejorado con funciones Sprig. Los templates acceden a values vía {{ .Values.key }}, metadata del release vía {{ .Release.Name }}, y metadata del chart vía {{ .Chart.Name }}. Las estructuras de control incluyen condicionales ({{ if }}), loops ({{ range }}), contexto acotado ({{ with }}), y pipelines ({{ .Values.name | default "app" | quote }}). La acción {{ with }} reasigna el punto (.) a un nuevo scope — {{ with .Values.ingress }}{{ .host }}{{ end }} accede a .Values.ingress.host sin repetir la ruta completa, y omite el bloque por completo si el valor es nil.

Los named templates definidos con {{ define "chart.labels" }} e invocados con {{ include "chart.labels" . }} son los bloques fundamentales de charts mantenibles. Define labels estándar de Kubernetes, selector labels y nombres de recursos una vez en _helpers.tpl e incluílos en todas partes. Usa include (no la acción built-in template) porque retorna un string que puedes pasar por funciones como nindent para indentación YAML correcta. La función tpl renderiza un string como template en tiempo de ejecución — {{ tpl .Values.annotations . }} permite a los usuarios pasar expresiones Go template dentro de archivos de values, útil para annotations o labels dinámicos que referencian otros values.

Funciones clave: toYaml convierte un valor a formato YAML ({{ toYaml .Values.resources | nindent 12 }}), esencial para renderizar maps y listas anidadas. include llama a un named template y retorna su salida como string. tpl evalúa un string como template Go. Errores comunes: el control de whitespace es crítico ({{- recorta izquierda, -}} recorta derecha), los values anidados necesitan null checks ({{ if .Values.ingress.enabled }} falla si .Values.ingress es nil — usa {{ with .Values.ingress }}{{ if .enabled }}{{ end }}{{ end }} o la función dig), y la indentación YAML debe ser explícita. Siempre valida la salida con helm template antes de desplegar.

# templates/_helpers.tpl — define reusable named templates
{{- define "app.labels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

# templates/deployment.yaml — include, with, range, toYaml, tpl
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-{{ .Chart.Name }}
  labels:
    {{- include "app.labels" . | nindent 4 }}
  annotations:
    {{- with .Values.annotations }}
    {{- tpl (toYaml .) $ | nindent 4 }}
    {{- end }}
spec:
  replicas: {{ .Values.replicaCount | default 2 }}
  template:
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        {{- with .Values.resources }}
        resources:
          {{- toYaml . | nindent 12 }}
        {{- end }}
        env:
        {{- range .Values.env }}
        - name: {{ .name }}
          value: {{ .value | quote }}
        {{- end }}

Repositorios de Charts

Los repositorios de charts alojan charts empaquetados para distribución. Repos públicos (Bitnami, Prometheus Community, Jetstack) proveen charts production-ready para software común. Repos privados (Google Artifact Registry, AWS ECR, ChartMuseum, Harbor) alojan los charts internos de tu organización. Helm 3 soporta registries OCI nativamente, permitiéndote subir charts al mismo registry que aloja tus imágenes Docker.

Agrega un repo con helm repo add bitnami https://charts.bitnami.com/bitnami, luego instala charts con helm install my-redis bitnami/redis -f values.yaml. Para registries OCI, sube con helm push chart.tgz oci://gcr.io/my-project/charts e instala con helm install my-app oci://gcr.io/my-project/charts/my-app --version 1.2.3.

En producción, los charts internos se publican en Google Artifact Registry como artefactos OCI durante CI. El chart de cada microservicio se versiona independientemente (la versión del chart registra la estructura del chart, la appVersion registra la versión de la aplicación). Un chart base compartido contiene templates comunes que todos los charts de servicio heredan como dependencia, asegurando consistencia en 20+ servicios.

Hooks y Tests

Los hooks de Helm son recursos especiales que se ejecutan en puntos específicos del ciclo de vida de un release: pre-install, post-install, pre-upgrade, post-upgrade, pre-delete, post-delete y pre-rollback. Anota un template con helm.sh/hook: pre-upgrade para convertirlo en hook. Usos comunes: migraciones de base de datos antes del upgrade, calentamiento de cache después del install, y limpieza al borrar.

El peso del hook (helm.sh/hook-weight) controla el orden de ejecución cuando múltiples hooks existen en el mismo punto del ciclo de vida. La política de borrado del hook (helm.sh/hook-delete-policy) determina si el recurso del hook se borra después de la ejecución: before-hook-creation (borrar viejo antes de crear nuevo), hook-succeeded (borrar si tuvo éxito), o hook-failed (borrar si falló).

Los tests de Helm son hooks especiales anotados con helm.sh/hook: test. Corren Pods que validan que el release está funcionando correctamente. Ejecuta tests con helm test release-name. Una suite de tests típica incluye: tests de conectividad (se puede alcanzar el Service), tests de dependencias (la app puede conectar a su base de datos), y smoke tests (el endpoint de health retorna 200). En producción, cada chart incluye un test de conectividad que corre automáticamente después de cada deployment vía CI.

# templates/pre-upgrade-migration.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ .Release.Name }}-migration
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        command: ["node", "dist/migrate.js"]
      restartPolicy: Never
  backoffLimit: 3

Gestión de Secrets con Helm

Helm no encripta secrets. Los archivos de values con datos sensibles nunca deben guardarse en Git en texto plano. Las soluciones principales son: inyectar secrets en tiempo de deploy vía variables de CI/CD (helm upgrade --set db.password=$DB_PASSWORD), usar el plugin helm-secrets con encriptación SOPS/age, o usar External Secrets Operator para sincronizar secrets desde el secret manager del proveedor cloud a Kubernetes.

El plugin helm-secrets se integra con Mozilla SOPS para encriptar archivos de values usando AWS KMS, GCP KMS, Azure Key Vault, o claves age. Los archivos encriptados son seguros para guardar en Git. La desencriptación sucede en tiempo de deploy: helm secrets upgrade release ./chart -f secrets.yaml. Esto te da secrets rastreados en Git con encriptación en reposo y rotación de claves a través del KMS cloud.

En producción, el enfoque preferido es External Secrets Operator (ESO). Los secrets viven en Google Secret Manager y ESO los sincroniza en objetos Secret de Kubernetes. Los charts de Helm referencian el Secret por nombre pero nunca contienen los valores sensibles reales. Esto separa completamente la gestión de secrets de las herramientas de deployment — los equipos de seguridad gestionan secrets en la consola cloud, y los desarrolladores los referencian por nombre en los values de Helm.

Nunca pases secrets vía values.yaml guardado en Git. Incluso con .gitignore, los secrets pueden filtrarse por historial de Git, logs de CI, o metadata del release de Helm (que almacena values en el cluster). Usa ESO, helm-secrets, o inyección de variables CI/CD. En producción, cero secrets existen en el repositorio Git — todos fluyen desde Google Secret Manager a través de External Secrets Operator.

Umbrella Charts para Microservicios

Un umbrella chart es un chart padre que depende de múltiples sub-charts, desplegando una plataforma de microservicios completa en un solo helm install. Cada sub-chart es un chart de servicio independiente (api, payment, notification, etc.) listado como dependencia en el Chart.yaml del padre. El values.yaml del padre pasa configuración hacia abajo a cada sub-chart bajo su clave de nombre.

Este enfoque tiene compromisos. Ventajas: deploys atómicos de toda la plataforma, versionado consistente entre servicios, CI/CD simplificado que despliega todo de una vez. Desventajas: una sola falla bloquea el release entero, los equipos de servicios independientes pierden autonomía de deployment, y los umbrella charts grandes se vuelven inmanejables. La plataforma empezó con un umbrella chart pero evolucionó a releases individuales por servicio para independencia de deployment.

El enfoque híbrido funciona mejor: un chart base compartido como librería (type: library en Chart.yaml) del cual todos los charts de servicio dependen, más releases individuales por servicio. El chart base provee templates comunes, labels y patrones de recursos. Los charts de servicio importan el chart base y agregan templates específicos del servicio. Esto da consistencia sin acoplar los ciclos de vida de deployment.

# Umbrella Chart.yaml
apiVersion: v2
name: the-platform
version: 1.0.0
dependencies:
  - name: api-service
    version: ~2.1.0
    repository: "oci://gcr.io/myproject/charts"
  - name: payment-service
    version: ~3.0.0
    repository: "oci://gcr.io/myproject/charts"
  - name: notification-service
    version: ~1.5.0
    repository: "oci://gcr.io/myproject/charts"

# Umbrella values.yaml
api-service:
  replicaCount: 3
  image:
    tag: v2.4.1
payment-service:
  replicaCount: 2
  image:
    tag: v3.1.0

Rollback y Versionado

Cada helm upgrade crea una nueva revisión. helm history release-name muestra todas las revisiones con timestamps y estado. helm rollback release-name 3 revierte a la revisión 3. Helm almacena el estado del release (incluyendo manifiestos renderizados y values) como Secrets en el cluster de Kubernetes, así que el rollback es rápido y no requiere acceso al repositorio de charts.

Versiona dos números independientemente: la versión del chart (registra cambios de template/estructura) y la appVersion (registra el build de la aplicación). Incrementa la versión del chart cuando modificas templates, agregas nuevos recursos o cambias valores por defecto. Incrementa la appVersion cuando despliegues un nuevo build de la aplicación. Esta distinción te permite actualizar versiones de la app sin cambiar el chart, y viceversa.

Configura --max-history para controlar cuántas revisiones retiene Helm (por defecto son 10). En producción, 10 generalmente es suficiente. Más historial significa más Secrets almacenados en el cluster y más datos para que helm diff compare. Usa el plugin helm-diff (helm diff upgrade) para previsualizar cambios antes de aplicarlos — esto atrapa cambios accidentales de values y regresiones de templates antes de que lleguen al cluster.

# View release history
helm history api-service -n production

# Rollback to specific revision
helm rollback api-service 5 -n production

# Preview changes before upgrade
helm diff upgrade api-service ./chart -f prod-values.yaml -n production

# Upgrade with max history
helm upgrade api-service ./chart \
  -f prod-values.yaml \
  --max-history 10 \
  -n production

Helmfile y Plugin helm-diff

Helmfile es una especificación declarativa para desplegar múltiples releases de Helm. En vez de scriptear docenas de comandos helm upgrade, defines todos los releases en un solo helmfile.yaml con ambientes, capas de values y orden de dependencias. Ejecuta helmfile sync para reconciliar cada release al estado deseado, o helmfile apply para ver un diff primero y aplicar solo si confirmas. Helmfile trae la mentalidad GitOps a Helm: todo el estado del cluster se declara en un archivo.

Helmfile soporta values específicos por ambiente (environments: staging: values: [...]), expresiones Go template en la especificación misma, y selectores (helmfile -l app=api sync) para apuntar a releases específicos. Puede obtener charts de cualquier repositorio incluyendo registries OCI. Para plataformas grandes con 20+ servicios, Helmfile elimina los scripts shell que típicamente conectan comandos Helm y hace los deployments multi-release reproducibles.

El plugin helm-diff (helm plugin install https://github.com/databus23/helm-diff) agrega un comando helm diff upgrade que muestra un diff con colores de lo que cambiaría antes de aplicar un upgrade. Compara los manifiestos desplegados actualmente contra los nuevos templates renderizados y muestra adiciones, eliminaciones y modificaciones. Helmfile integra helm-diff nativamente — helmfile apply ejecuta un diff primero y solo procede si se detectan cambios. Esta es la red de seguridad más importante para operaciones Helm en producción.

# helmfile.yaml
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

environments:
  staging:
    values: [environments/staging.yaml]
  production:
    values: [environments/production.yaml]

releases:
  - name: api-service
    chart: ./charts/api-service
    namespace: {{ .Environment.Name }}
    values:
      - values/api-service/common.yaml
      - values/api-service/{{ .Environment.Name }}.yaml

  - name: redis
    chart: bitnami/redis
    version: 18.6.1
    namespace: {{ .Environment.Name }}
    values:
      - values/redis/{{ .Environment.Name }}.yaml

# Preview changes then apply
# helmfile -e production diff
# helmfile -e production apply

Helm en Pipelines CI/CD

En pipelines CI/CD, Helm reemplaza el kubectl apply crudo con deployments versionados, parametrizados y con capacidad de rollback. El flujo típico del pipeline: construir la imagen Docker, subirla al registry, ejecutar helm upgrade --install con el nuevo tag de imagen pasado vía --set image.tag=$CI_COMMIT_SHA. El flag --install hace el comando idempotente — crea el release en la primera ejecución y hace upgrade en las siguientes.

Usa --atomic para hacer rollback automático en caso de falla. Si algún recurso no alcanza estado ready dentro del timeout, Helm revierte el release completo a la versión anterior. Combina con --timeout 5m para establecer cuánto espera Helm por readiness. Esto es esencial en CI/CD: un deployment fallido nunca debería dejar el cluster en estado roto.

En producción, los pipelines de GitLab CI usan Helm para cada deployment. El job de deploy ejecuta helm upgrade --install --atomic --timeout 5m con archivos de values específicos por ambiente (values-staging.yaml, values-production.yaml). Después del deployment, el pipeline ejecuta helm test para validar conectividad. Si los tests fallan, el pipeline dispara un rollback y alerta al equipo vía Slack.

Buenas Prácticas

Siempre ejecuta helm template o helm lint en CI antes de desplegar. Template renderiza localmente sin acceso al cluster, atrapando errores de sintaxis y panics por nil pointer. Lint valida la metadata y estructura del chart. Combina ambos: helm lint ./chart && helm template test ./chart -f values.yaml > /dev/null. Esta sola línea previene la mayoría de fallas de deployment.

Fija las versiones de dependencias de charts con rangos exactos o tilde (~2.1.0), nunca uses * o rangos caret en producción. Siempre especifica --atomic y --timeout en deployments de CI. Usa releases con namespace y evita el namespace default. Configura resource requests y limits en los defaults de values.yaml para que ningún deployment corra sin ellos. Incluye NOTES.txt para dar instrucciones post-instalación a los usuarios.

Mantén los archivos de values planos cuando sea posible — values profundamente anidados son más difíciles de sobreescribir con --set. Usa helm diff upgrade antes de cada upgrade en producción. Guarda values específicos por ambiente en archivos separados (values-staging.yaml, values-production.yaml) en vez de depender de overrides con --set que son difíciles de auditar. Versiona tus charts en un repositorio de charts (OCI preferido) en vez de desplegar desde directorios locales en producción. Documenta cada value en values.yaml con comentarios explicando qué controla.

Validar Antes de Desplegar

Ejecuta helm lint, helm template y helm diff en CI. Atrapa errores antes de que lleguen al cluster. Usa validación de schema (values.schema.json) para forzar tipos de valores y campos requeridos.

Versionar y Fijar Todo

Fija versiones de dependencias. Etiqueta releases de charts en registries OCI. Usa --atomic en producción. Registra chart version y appVersion independientemente. Nunca despliegues charts sin versión a producción.

Higiene de Values

Comenta cada value. Mantén el anidamiento superficial. Usa archivos separados por ambiente. Nunca guardes secrets en archivos de values. Configura resource limits como defaults. Usa values.schema.json para validación.

Helm 4: Qué Cambió

Helm 4 fue lanzado el 12 de noviembre de 2025. Helm 3 ahora está en modo de solo correcciones de seguridad hasta noviembre 2026. Este es el release más significativo de Helm desde la eliminación de Tiller en Helm 3, con cambios fundamentales en cómo Helm aplica recursos al cluster.

Server-Side Apply (SSA) reemplaza la estrategia de parche three-way merge. En vez de que Helm calcule diffs del lado del cliente y envíe patches, Kubernetes mismo maneja la detección de conflictos y la propiedad de campos. Los conflictos ahora producen errores explícitos en vez de sobrescrituras silenciosas — si otro controlador es dueño de un campo, Helm no lo sobrescribirá silenciosamente. Esto elimina toda una clase de bugs de deployment donde Helm y otras herramientas (operators, ediciones kubectl) pelearían silenciosamente por los mismos campos.

La integración de kstatus reemplaza el polling simplista de --wait con evaluación de readiness de Kubernetes adecuada. En vez de verificar si los Pods están Running, kstatus entiende la semántica de readiness real de cada tipo de recurso (Deployments, StatefulSets, Jobs, CRDs). Esto hace que --wait sea confiable para pipelines CI/CD de producción donde la implementación anterior a veces reportaba éxito prematuramente.

Los plugins basados en Wasm reemplazan el viejo sistema de plugins de scripts shell con módulos WebAssembly. Tres tipos de plugins son soportados: plugins CLI (extienden comandos de Helm), plugins getter (obtienen charts de fuentes personalizadas) y plugins post-renderer (transforman manifiestos antes de aplicar). Los post-renderers ahora deben ser un nombre de plugin, no una ruta de ejecutable arbitraria — este es un cambio de ruptura.

El soporte de digest OCI permite instalar charts por digest (helm install app oci://registry/chart@sha256:abc...) para seguridad de la cadena de suministro. Multi-doc values permite dividir values complejos en múltiples archivos YAML que se fusionan en profundidad en orden. El nuevo formato Chart v3 agrega metadata estructurada manteniendo compatibilidad hacia atrás con charts v2.

Helm 4.2.x (estable actual, mayo 2026): Helm 4.2.0 y 3.21.0 se publicaron el 14 de mayo de 2026. El release de funcionalidades 4.2.0 actualiza las bibliotecas cliente de Kubernetes a v1.36, agrega la función de plantilla mustToToml, hace que --dry-run=server respete generateName:, y depreca los flags sin uso --hide-notes y --render-subchart-notes. La adopción de registries OCI es ahora mainstream -- Docker Hub, GitHub Container Registry, Amazon ECR y Azure Container Registry hospedan charts Helm nativamente, y OCI es el método de distribución recomendado sobre repositorios de charts legacy. Helm 3 permanece en modo de solo correcciones de seguridad (Helm 3.21.x) hasta noviembre 2026.

Nota de migración: Los releases existentes usan client-side apply por defecto; la migración a server-side apply es opt-in vía --server-side-apply. El renombrado de flags CLI afecta algunos scripts de automatización — revisa tus pipelines CI/CD antes de actualizar. Prueba en staging primero: la detección de conflictos de SSA puede revelar conflictos de propiedad previamente ocultos entre Helm y otros controladores.

Caso Real: Estrategia Helm en Producción

La plataforma gestiona 20+ deployments de Kubernetes enteramente a través de charts de Helm. La estrategia de charts evolucionó de un umbrella chart monolítico a charts independientes por servicio compartiendo una librería base común, habilitando a cada equipo a desplegar independientemente mientras mantienen consistencia.

Chart Base Compartido

Un chart librería que provee templates comunes para Deployments, Services, HPA, RBAC y ConfigMaps. Los 20+ charts de servicio dependen de él. Los cambios de template se propagan a cada servicio en el próximo release.

Releases por Servicio

Cada microservicio tiene su propio release de Helm con versionado independiente. Los servicios despliegan independientemente vía GitLab CI. El rollback es por servicio, no de toda la plataforma. Cero coordinación necesaria entre equipos.

Deploys Atómicos + Tests

Cada deployment usa --atomic para rollback automático en caso de falla. Los tests de Helm post-deploy validan conectividad y salud. Tests fallidos disparan rollback automatizado y alertas de Slack en menos de 60 segundos.

Más Guías