O Helm para Node.js empacota recursos Kubernetes em um chart versionado e configurável. Em vez de duplicar arquivos Deployment, Service, HPA, ConfigMap e Ingress para cada ambiente, a equipe mantém templates e fornece valores diferentes para desenvolvimento, homologação e produção.
Helm não substitui o entendimento do Kubernetes. Um chart pode gerar manifestos válidos e ainda criar uma aplicação insegura, sem probes ou com selectors incorretos. O objetivo é reduzir repetição, validar configurações e controlar releases, sem esconder as decisões operacionais.
Neste guia, você aprenderá a criar um chart para uma API Node.js, organizar Chart.yaml, values, templates, helpers, schema, secrets, upgrades, rollback, testes e publicação em registry OCI.
O que é um chart?
A documentação oficial de charts do Helm define chart como uma coleção de arquivos que descreve recursos relacionados do Kubernetes. A estrutura básica é:
orders-api/
├── Chart.yaml
├── values.yaml
├── values.schema.json
├── templates/
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── serviceaccount.yaml
│ ├── configmap.yaml
│ ├── NOTES.txt
│ └── tests/
└── .helmignoreCriando o chart
helm create orders-apiO comando gera um exemplo genérico. Remova templates que não fazem parte do serviço e adapte os nomes, labels e valores.
Chart.yaml
apiVersion: v2
name: orders-api
description: API de pedidos em Node.js
type: application
version: 0.1.0
appVersion: "1.4.3"
kubeVersion: ">=1.30.0-0"version é a versão do chart. appVersion documenta a versão da aplicação, mas não altera automaticamente a imagem. Use SemVer e incremente o chart sempre que templates ou defaults mudarem.
values.yaml
replicaCount: 3
image:
repository: registry.example.com/orders-api
tag: "1.4.3"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 3000
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1
memory: 512Mi
config:
nodeEnv: production
port: 3000
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 20
targetCPUUtilizationPercentage: 60Defaults devem ser seguros. Não coloque senhas ou tokens no values versionado.
Helpers de nomes
Em templates/_helpers.tpl:
{{- define "orders-api.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "orders-api.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name (include "orders-api.name" .) | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}Helpers evitam repetir lógica e mantêm nomes consistentes.
Labels recomendadas
{{- define "orders-api.labels" -}}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/name: {{ include "orders-api.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}Selectors devem usar apenas labels estáveis. Não inclua chart version no selector, pois ele mudaria durante upgrade.
Deployment template
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "orders-api.fullname" . }}
labels:
{{- include "orders-api.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "orders-api.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "orders-api.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
serviceAccountName: {{ include "orders-api.fullname" . }}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.targetPort }}
resources:
{{- toYaml .Values.resources | nindent 12 }}Veja Kubernetes Deployment no Node.js.
Probes
probes:
readiness:
path: /health/ready
initialDelaySeconds: 2
liveness:
path: /health/live
initialDelaySeconds: 10No template:
readinessProbe:
httpGet:
path: {{ .Values.probes.readiness.path | quote }}
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
livenessProbe:
httpGet:
path: {{ .Values.probes.liveness.path | quote }}
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}Consulte Probes Kubernetes em Node.js.
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "orders-api.fullname" . }}
data:
NODE_ENV: {{ .Values.config.nodeEnv | quote }}
PORT: {{ .Values.config.port | quote }}Monte por envFrom ou variáveis específicas. Uma alteração no ConfigMap não reinicia automaticamente o Deployment.
Checksum para rollout
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}Quando o conteúdo renderizado muda, a annotation muda e o Deployment cria novos Pods.
Secrets
Evite gerar Secret com valor em texto claro dentro de values.yaml. Prefira External Secrets, Sealed Secrets ou integração com o provedor. O chart pode receber o nome de um Secret existente:
existingSecret: orders-api-secretsenvFrom:
- secretRef:
name: {{ required "existingSecret é obrigatório" .Values.existingSecret }}Veja ConfigMaps e Secrets no Node.js.
Service
apiVersion: v1
kind: Service
metadata:
name: {{ include "orders-api.fullname" . }}
spec:
type: {{ .Values.service.type }}
selector:
app.kubernetes.io/name: {{ include "orders-api.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: httpHPA
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "orders-api.fullname" . }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "orders-api.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}Quando HPA está ativo, o template omite replicas. Veja Kubernetes HPA no Node.js.
Values por ambiente
values.yaml
values-development.yaml
values-staging.yaml
values-production.yamlO arquivo base contém defaults. Os ambientes sobrescrevem apenas diferenças:
helm upgrade --install orders-api ./orders-api \
--namespace production \
--create-namespace \
--values values-production.yamlEvite excesso de parâmetros
Um chart com centenas de flags vira uma linguagem própria. Exponha valores que realmente variam entre instalações e mantenha invariantes de segurança no template.
values.schema.json
A documentação oficial permite validar values com JSON Schema:
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["image", "resources", "existingSecret"],
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"image": {
"type": "object",
"required": ["repository", "tag"],
"properties": {
"repository": {"type": "string", "minLength": 1},
"tag": {"type": "string", "minLength": 1}
}
}
}
}Schema detecta valores ausentes e tipos errados antes da instalação.
required e fail
{{ required "image.repository é obrigatório" .Values.image.repository }}Use validação explícita para invariantes que JSON Schema não expressa facilmente.
Renderização local
helm template orders-api ./orders-api \
--namespace production \
--values values-production.yamlInspecione o YAML gerado antes de aplicar. Isso ajuda a encontrar indentation, valores vazios e APIs incorretas.
Lint
helm lint ./orders-api \
--values values-production.yaml \
--strictLint deve fazer parte do CI, mas não substitui validação contra schemas Kubernetes.
Validação no CI
helm dependency build ./orders-api
helm lint ./orders-api --strict
helm template orders-api ./orders-api \
--values values-production.yaml \
| kubeconform -strict -summaryTambém execute scanners de política, segurança e APIs depreciadas.
Dry-run no servidor
helm upgrade --install orders-api ./orders-api \
--namespace production \
--values values-production.yaml \
--dry-run=serverO dry-run local não conhece todos os recursos e admission policies do cluster. O modo servidor oferece validação adicional, mas não deve expor secrets nos logs.
Upgrade atômico
helm upgrade --install orders-api ./orders-api \
--namespace production \
--values values-production.yaml \
--atomic \
--wait \
--timeout 10m--atomic tenta desfazer uma atualização que falha. --wait aguarda recursos ficarem prontos. Migrations e sistemas externos ainda precisam de estratégia própria.
Histórico e rollback
helm history orders-api -n production
helm rollback orders-api 7 -n production --waitRollback restaura manifestos da release. Ele não desfaz dados, filas ou migrations. Use mudanças de banco compatíveis.
Hooks
Hooks podem executar Jobs antes ou depois do upgrade:
metadata:
annotations:
helm.sh/hook: pre-upgrade
helm.sh/hook-weight: "0"
helm.sh/hook-delete-policy: before-hook-creation,hook-succeededHooks de migration podem bloquear e tornar rollback complexo. Prefira um pipeline explícito quando o processo exige controle detalhado.
Chart tests
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "orders-api.fullname" . }}-test"
annotations:
helm.sh/hook: test
spec:
restartPolicy: Never
containers:
- name: curl
image: curlimages/curl:8.12.1
command:
- curl
- --fail
- http://{{ include "orders-api.fullname" . }}/health/livehelm test orders-api -n productionDependências
dependencies:
- name: redis
version: "20.6.1"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabledFixe versões e execute helm dependency update. Para serviços de produção, bancos e caches gerenciados separadamente costumam ter ciclo de vida diferente da API.
OCI registry
Charts podem ser armazenados em registries OCI:
helm package ./orders-api
helm push orders-api-0.1.0.tgz oci://registry.example.com/chartsInstalação:
helm upgrade --install orders-api \
oci://registry.example.com/charts/orders-api \
--version 0.1.0Assinatura e provenance
Verifique origem e integridade de charts distribuídos. A documentação de provenance do Helm explica arquivos de assinatura e verificação. Em registries OCI, combine controles do registry, digest e ferramentas de assinatura.
Observabilidade da release
helm list -n production
helm status orders-api -n production
helm get values orders-api -n production
helm get manifest orders-api -n productionRegistre chart version, app version, image digest e revisão da release.
Erros comuns
- Selector usa versão: upgrade deixa de encontrar os Pods.
- Secrets no values: credenciais vazam no Git ou histórico.
- Tag latest: release não é reproduzível.
- Sem schema: tipos inválidos chegam ao template.
- Parâmetros demais: o chart fica impossível de manter.
- Hook de migration inseguro: rollback não recupera o banco.
- Confiar apenas no lint: políticas do cluster não são testadas.
- Chart e app com mesma versão: ciclos independentes ficam confusos.
Conclusão
O Helm para Node.js organiza manifestos Kubernetes em charts versionados, com values, templates, schema, releases e rollback. A ferramenta reduz repetição e facilita configurar ambientes, mas os recursos gerados continuam exigindo boas práticas do Kubernetes.
Mantenha defaults seguros, selectors estáveis e secrets externos. Valide com lint, template, schema e políticas no CI. Use upgrades atômicos com observabilidade e trate migrations separadamente. Assim, o chart se torna um pacote previsível para entregar aplicações Node.js.



