Helm chart para uma aplicação Next.js
Use para charts/<app>/ e como o Argo CD o consome. A imagem executada vem de docker-nextjs; o pipeline que publica ambos é github-actions.
O modelo em charts/__APP__/ é a fonte da verdade. Todos os valores com comentários: references/values.md. Integração com Argo CD: references/argocd.md.
Regras
-
Um chart por aplicação, em
charts/<app>/na raiz do repositório da aplicação. Por que lá: o Argo CD pode sincronizá-lo diretamente do Git (path: charts/<app>) para um ambiente de desenvolvimento e do registro OCI para produção, com os mesmos arquivos; está fora deapps/, portanto não está nem no contexto de build do Docker nem em um pacote do pnpm workspace; e o chart muda no mesmo PR que o código que precisa dele. O chart é propositalmente para uma única aplicação: sem umbrella, sem subcharts. Templates genéricos orientados a valores (como o chart umbrella de backend) apenas onde uma única aplicação precisa da alternância: ingress, HPA, PDB, topology spread. -
Nunca edite manualmente
versionouappVersion. Ambos permanecem0.0.0no Git. Orelease.yamlexecutahelm package --version X.Y.Z --app-version vX.Y.Za partir da tagvX.Y.Z, de modo que o chart publicado e a tag da imagem sempre correspondam. -
image.tagpadrão éappVersion; defina-o apenas para ambientes sincronizados pelo Git. Pelo OCI,appVersioné a tag de release e a imagem éghcr.io/nuvraxis/<app>:vX.Y.Z. Sincronizado pelo Git,appVersioné0.0.0, então o Application do Argo CD defineimage.tag: sha-<short-sha>(oumain).image.repositoryé sempre minúsculo. -
Probes: startup, liveness e readiness, todas em
/api/health. A probe startup (2s × 30) cobre a inicialização; liveness e readiness só iniciam depois dela. A rota nunca toca em uma dependência, portanto uma falha no banco de dados não reinicia os pods. Não aponte uma probe para/: isso renderiza uma página. -
Contexto de segurança corresponde à imagem: uid/gid 1001,
runAsNonRoot,readOnlyRootFilesystem, sem escalonamento de privilégios, todas as capabilities removidas, seccompRuntimeDefault.automountServiceAccountToken: falsetanto no ServiceAccount quanto no pod: a aplicação não chama a API do Kubernetes. -
.next/cacheé umemptyDircomsizeLimit. É o único caminho gravável (/app/apps/<app>/.next/cache). O limite evita que um cache de imagem descontrolado encha o nó. -
Configuração através de
envFrom: um ConfigMap a partir devalues.config, e um Secret que já existe.config: API_BASE_URL: https://api.nuvraxis.com existingSecret: portal-secretsO chart nunca faz template de valores secretos: sem
kind: Secretcomdatavindo de values, sem--set secret=…. O Secret é criado por External Secrets, Sealed Secrets ou um operador, e apenas seu nome está em values. Uma alteração no ConfigMap faz o rollout dos pods através da anotaçãochecksum/config. -
Sem
NEXT_PUBLIC_*no chart. Eles são incorporados no build da imagem (vejadocker-nextjs); defini-los em tempo de execução não faz efeito. -
Recursos: requests para CPU e memória, um limite de memória, sem limite de CPU. Limites de CPU limitam um servidor Node durante picos e aumentam a latência; o limite de memória permanece porque o heap do Node cresce conforme o que é dado.
-
Alta disponibilidade por padrão: 2 réplicas, PDB
maxUnavailable: 1, atualização rolling commaxUnavailable: 0, restrições de topology spread entre zonas e nós (ScheduleAnyway). Comautoscaling.enabled, o Deployment omitereplicas, para que o Argo CD e o HPA não entrem em conflito. -
Ingress é opt-in, TLS através de anotações do cert-manager.
ingress.enabled,className, hosts,tlscomsecretName, ecert-manager.io/cluster-issuernas anotações. Para respostas streaming no ingress-nginx, adicionenginx.ingress.kubernetes.io/proxy-buffering: "off"; para rate limiting,limit-rps(vejanextjs-security). -
Sem Helm hooks, sem
lookup, sem valores aleatórios. O Argo CD renderiza o chart comhelm templatee aplica o resultado: hooks se tornam hooks do Argo com semântica diferente,lookupnão retorna nada, erandAlphaNummuda a cada sincronização e mostra a aplicação permanentemente fora de sincronia. Tudo o que é renderizado deve ser uma função pura dos valores. -
Pacotes GHCR privados precisam de credenciais de pull. Pacotes GHCR são privados no primeiro push. Para imagens: um Secret
docker-registrycom um token que tenharead:packages, referenciado emimagePullSecrets(valores de produção referenciamghcr-pull). Para o chart no Argo CD: um Secret de repositório comenableOCI: "true"(vejareferences/argocd.md). Ou torne os pacotes públicos no GitHub se o código for público. -
values-production.yamlcontém apenas o que difere em produção. Faça a camada:-f values.yaml -f values-production.yaml. Não copie os padrões para ele. -
Valide com
helm lint --strictehelm template | kubeconform -strict. Por que kubeconform em vez de helm-unittest: os bugs que um chart de aplicação única realmente tem são nomes de campos, tipos ou versões de API errados na saída renderizada, o que kubeconform detecta contra os schemas reais do Kubernetes com zero código de teste. O helm-unittest testa a lógica do template, que este chart mal tem. Valide lint e ambos os arquivos de valores, como fazpr.yaml.
Adicionando coisas
| Necessidade | Alteração |
|---|---|
| Uma variável de ambiente em runtime | config: em values (não secreta) ou uma chave no Secret existente |
| Um segredo | adicione-o ao Secret externo; nada no chart muda |
| Outra porta ou sidecar | justifique primeiro; uma aplicação Next precisa de uma porta |
| Um cron job | um chart ou aplicação separada, não este Deployment |
| NetworkPolicy | adicione templates/networkpolicy.yaml, ativado por networkPolicy.enabled |
Verificar
helm lint --strict charts/<app>
helm lint --strict charts/<app> -f charts/<app>/values-production.yaml
helm template <app> charts/<app> -f charts/<app>/values-production.yaml \
| docker run --rm -i ghcr.io/yannh/kubeconform:v0.8.0 -strict -summary -kubernetes-version 1.34.0 -
Fontes
- https://helm.sh/docs/topics/charts/
- https://helm.sh/docs/chart_best_practices/
- https://helm.sh/docs/topics/registries/
- https://helm.sh/docs/overview/
- https://github.com/yannh/kubeconform
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
- https://kubernetes.io/docs/concepts/security/pod-security-standards/
- https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
- https://kubernetes.io/docs/concepts/workloads/pods/disruptions/
- https://argo-cd.readthedocs.io/en/stable/user-guide/helm/
- https://cert-manager.io/docs/usage/ingress/
- https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry