Helm Charts: Gerenciamento de Pacotes do Kubernetes

Implantações do Kubernetes com gerenciamento de pacotes Helm

Helm revolucionou a implantação de aplicações no Kubernetes ao introduzir conceitos de gerenciamento de pacotes familiares aos sistemas operacionais tradicionais.

Com o crescimento da adoção do Kubernetes, gerenciar aplicações complexas com dezenas de arquivos YAML torna-se desafiador. Os Helm Charts resolvem esse problema ao agrupar todos os recursos em pacotes versionados e configuráveis.

desenvolvedor de software na natureza Esta bela imagem foi gerada pelo modelo de IA Flux 1 dev.

Compreendendo o Helm: O Gerenciador de Pacotes do Kubernetes

O Helm é para o Kubernetes o que o apt é para o Debian, o yum para o RedHat, ou o Homebrew para o macOS. Ele empacota aplicações Kubernetes em Charts – coleções de arquivos que descrevem recursos Kubernetes relacionados. Um único Chart pode implantar uma pilha de aplicação completa: servidores web, bancos de dados, camadas de cache, regras de ingresso e componentes de monitoramento. Para aqueles novos no Kubernetes, uma Lista de Comandos do Kubernetes fornece comandos e conceitos essenciais para começar.

Por que o Helm Importa no DevOps Moderno

Redução de Complexidade: Em vez de gerenciar 20+ arquivos YAML, você gerencia um único Chart com valores personalizáveis.

Reprodutibilidade: Implante configurações idênticas em desenvolvimento, homologação e produção com sobrescritas de valores específicas do ambiente. Isso é especialmente valioso ao implantar arquiteturas de microsserviços complexas onde a consistência importa.

Controle de Versão: Os Charts são versionados, permitindo rollback e rastreamento de upgrades fáceis.

Ecossistema da Comunidade: Milhares de Charts pré-construídos disponíveis através do Artifact Hub (anteriormente Helm Hub) para aplicações populares como PostgreSQL, Redis, NGINX, Prometheus e muito mais.

Poder de Templating: Go templates permitem a geração dinâmica de recursos com base em valores de entrada, reduzindo a duplicação.

Arquitetura e Conceitos Centrais do Helm

Arquitetura do Helm 3

O Helm 3 simplificou a arquitetura removendo o Tiller, o componente problemático de servidor do Helm 2:

  • Cliente Helm: Ferramenta de linha de comando que interage diretamente com a API do Kubernetes
  • Chart: Formato de pacote contendo templates e metadados
  • Release: Uma instância de um Chart executando em um cluster Kubernetes
  • Repositório: Local de armazenamento para Charts (servidor HTTP ou registro OCI)

Componentes Chave de um Helm Chart

my-app-chart/
├── Chart.yaml          # Metadados e versão do Chart
├── values.yaml         # Valores de configuração padrão
├── charts/             # Charts dependentes
├── templates/          # Templates de recursos Kubernetes
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl    # Helpers de template
│   └── NOTES.txt       # Notas pós-instalação
├── .helmignore         # Arquivos a ignorar ao empacotar
├── README.md
└── LICENSE

Criando seu Primeiro Helm Chart

Inicializar um Novo Chart

helm create my-application
cd my-application

Isso gera um Chart inicial com templates de exemplo para deployment, service e ingress.

Chart.yaml: Definindo Metadados

apiVersion: v2
name: my-application
description: Um chart de aplicação pronto para produção
type: application
version: 1.0.0        # Versão do Chart
appVersion: "2.4.1"   # Versão da aplicação

maintainers:
  - name: Your Team
    email: team@company.com

dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

Values.yaml: Gerenciamento de Configuração

O arquivo values.yaml define configurações padrão que os usuários podem sobrescrever. Esta abordagem separa a configuração dos templates, facilitando o gerenciamento de diferentes ambientes (desenvolvimento, homologação, produção) e a personalização de implantações sem modificar os arquivos de template.

replicaCount: 3

image:
  repository: myapp/backend
  tag: "1.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: "nginx"
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: Prefix

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

Templates: Manifestos Kubernetes Dinâmicos

Os templates usam a sintaxe de templating do Go para gerar recursos Kubernetes dinamicamente. Esses templates podem gerar qualquer tipo de recurso Kubernetes, desde Deployments simples até StatefulSets complexos para aplicações com estado que requerem armazenamento persistente. Para aplicações que precisam de identidades estáveis e volumes persistentes, você deve usar StatefulSets em vez de Deployments, conforme detalhado em nosso guia sobre StatefulSets e Armazenamento Persistente no Kubernetes.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-application.fullname" . }}
  labels:
    {{- include "my-application.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-application.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-application.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: 8080
          protocol: TCP
        resources:
          {{- toYaml .Values.resources | nindent 10 }}

Helpers de Template (_helpers.tpl)

Crie funções de template reutilizáveis para evitar repetições:

{{/*
Expanda o nome do chart.
*/}}
{{- define "my-application.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Crie um nome de aplicação totalmente qualificado padrão.
*/}}
{{- define "my-application.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}

{{/*
Labels comuns
*/}}
{{- define "my-application.labels" -}}
helm.sh/chart: {{ include "my-application.chart" . }}
{{ include "my-application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

Gerenciando Helm Charts: Instalação e Operações

Instalando um Chart

# Instalar de um repositório
helm install my-release bitnami/postgresql

# Instalar de um diretório local
helm install my-app ./my-application

# Instalar com valores personalizados
helm install my-app ./my-application -f values-production.yaml

# Instalar com sobrescritas de valores inline
helm install my-app ./my-application \
  --set replicaCount=5 \
  --set image.tag=2.0.0

Atualizando Releases

# Atualizar com novos valores
helm upgrade my-app ./my-application -f values-production.yaml

# Atualizar com rollback atômico em caso de falha
helm upgrade my-app ./my-application --atomic --timeout 5m

# Forçar atualizações de recursos
helm upgrade my-app ./my-application --force

Rollback e Histórico

# Visualizar histórico de releases
helm history my-app

# Rollback para versão anterior
helm rollback my-app

# Rollback para revisão específica
helm rollback my-app 3

Testes e Depuração

# Dry-run para ver manifestos gerados
helm install my-app ./my-application --dry-run --debug

# Renderização de template sem instalação
helm template my-app ./my-application

# Lint do chart para problemas
helm lint ./my-application

# Testar release com ganchos de teste
helm test my-app

Recursos Avançados do Helm

Dependências de Chart

Helm Charts podem depender de outros Charts, permitindo que você componha aplicações complexas a partir de componentes reutilizáveis. Isso é particularmente útil ao implantar microsserviços que precisam de bancos de dados, filas de mensagens ou outros serviços de suporte. Defina dependências em Chart.yaml:

dependencies:
  - name: redis
    version: "17.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

Atualizar dependências:

helm dependency update ./my-application

Hooks do Helm para Gerenciamento de Ciclo de Vida

Hooks são executados em pontos específicos do ciclo de vida do release:

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-application.fullname" . }}-db-migration
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install
    "helm.sh/hook-weight": "5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      containers:
      - name: db-migrate
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        command: ["python", "manage.py", "migrate"]
      restartPolicy: Never

Tipos de hooks incluem:

  • pre-install: Antes que os recursos sejam instalados
  • post-install: Após todos os recursos serem instalados
  • pre-upgrade: Antes da atualização
  • post-upgrade: Após a atualização
  • pre-delete: Antes da exclusão
  • post-delete: Após a exclusão
  • pre-rollback: Antes do rollback
  • post-rollback: Após o rollback

Lógica Condicional e Controle de Fluxo

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "my-application.fullname" . }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  {{- if .Values.ingress.className }}
  ingressClassName: {{ .Values.ingress.className }}
  {{- end }}
  rules:
  {{- range .Values.ingress.hosts }}
  - host: {{ .host | quote }}
    http:
      paths:
      {{- range .paths }}
      - path: {{ .path }}
        pathType: {{ .pathType }}
        backend:
          service:
            name: {{ include "my-application.fullname" $ }}
            port:
              number: {{ $.Values.service.port }}
      {{- end }}
  {{- end }}
{{- end }}

Suporte a Registro OCI: Distribuição Moderna de Charts

Desde o Helm 3.8, o suporte a registro OCI (Open Container Initiative) é estável, permitindo que Charts sejam armazenados junto com imagens de contêiner.

Publicando em Registro OCI

# Login no registro
helm registry login registry.example.com

# Empacotar o chart
helm package ./my-application

# Push para registro OCI
helm push my-application-1.0.0.tgz oci://registry.example.com/charts

# Instalar de registro OCI
helm install my-app oci://registry.example.com/charts/my-application --version 1.0.0

Benefícios de Registros OCI

  • Armazenamento Unificado: Charts e imagens em um só lugar
  • Ferramentas Padrão: Usar infraestrutura de registro existente
  • Melhor Segurança: Aproveitar autenticação e varredura do registro
  • Gerenciamento Simples: Nenhum servidor de repositório de Chart separado necessário

Melhores Práticas para Helm Charts em Produção

1. Estrutura e Documentação de Valores

Documente todos os valores com comentários:

# -- Número de réplicas para a aplicação
replicaCount: 3

# -- Configuração de imagem
image:
  # -- Repositório de imagem
  repository: myapp/backend
  # -- Política de pull de imagem
  pullPolicy: IfNotPresent
  # -- Tag de imagem (padrão é appVersion do chart)
  tag: ""

2. Gerenciamento de Recursos

Sempre defina solicitações e limites de recursos:

resources:
  limits:
    cpu: 1000m
    memory: 1Gi
  requests:
    cpu: 500m
    memory: 512Mi

3. Contextos de Segurança

Defina contextos de segurança para contêineres:

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  capabilities:
    drop:
    - ALL
  readOnlyRootFilesystem: true

4. Verificações de Saúde

Inclua sondas de liveness e readiness:

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

5. Gerenciamento de ConfigMap e Secret

O gerenciamento adequado de segredos é crítico para implantações em produção. Use gerencadores de segredos externos (Sealed Secrets, External Secrets Operator ou Vault) em vez de armazenar segredos em arquivos de valores. Isso garante que dados sensíveis como senhas de banco de dados, chaves de API e certificados sejam manipulados com segurança:

envFrom:
- secretRef:
    name: {{ include "my-application.fullname" . }}-secrets
- configMapRef:
    name: {{ include "my-application.fullname" . }}-config

6. Validação de Schema

Crie values.schema.json para validar entradas do usuário:

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1
    },
    "image": {
      "type": "object",
      "properties": {
        "repository": {
          "type": "string"
        },
        "tag": {
          "type": "string"
        }
      },
      "required": ["repository"]
    }
  },
  "required": ["image"]
}

7. NOTES.txt para Orientação do Usuário

Forneça instruções pós-instalação:

1. Obtenha a URL da aplicação executando:
{{- if .Values.ingress.enabled }}
  https://{{ (index .Values.ingress.hosts 0).host }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "my-application.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- end }}

2. Monitore a implantação:
  kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "my-application.name" . }}"

Teste de Helm Charts e Integração CI/CD

Teste de Chart com chart-testing (ct)

# Instalar chart-testing
brew install chart-testing

# Lint de charts
ct lint --config ct.yaml

# Instalar e testar charts
ct install --config ct.yaml

Exemplo de GitHub Actions

name: Helm Chart CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Set up Helm
        uses: azure/setup-helm@v3
        with:
          version: 3.12.0

      - name: Set up chart-testing
        uses: helm/chart-testing-action@v2

      - name: Lint charts
        run: ct lint --config ct.yaml

      - name: Create kind cluster
        uses: helm/kind-action@v1

      - name: Install charts
        run: ct install --config ct.yaml

GitOps com Helm: ArgoCD e Flux

Ferramentas GitOps como ArgoCD e Flux integram-se perfeitamente com Helm Charts, permitindo implantações declarativas e automatizadas. Essas ferramentas monitoram seu repositório Git por alterações e sincronizam automaticamente releases Helm, tornando a implantação contínua simples. Para arquiteturas de microsserviços complexas, considere como padrões de transação distribuída como o padrão Saga podem ajudar a gerenciar a consistência entre serviços implantados via Helm.

Aplicação ArgoCD

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/my-app-chart
    targetRevision: main
    path: charts/my-application
    helm:
      valueFiles:
        - values-production.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Flux HelmRelease

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: my-application
  namespace: flux-system
spec:
  interval: 5m
  chart:
    spec:
      chart: my-application
      version: '1.x.x'
      sourceRef:
        kind: HelmRepository
        name: my-charts
  values:
    replicaCount: 5
    image:
      tag: "2.0.0"

Solução de Problemas Comuns do Helm

Problema: Atualização Falhada Presa em Pendente

# Verificar status do release
helm list --all-namespaces

# Obter detalhes do release
helm status my-app -n namespace

# Forçar exclusão se necessário (use com cuidado)
kubectl delete secret -n namespace -l owner=helm,name=my-app

Problema: Erros de Renderização de Template

# Depurar renderização de template
helm template my-app ./my-application --debug

# Validar contra Kubernetes
helm template my-app ./my-application | kubectl apply --dry-run=client -f -

Problema: Valores Não Aplicados

# Verificar valores mesclados
helm get values my-app

# Mostrar todos os valores computados
helm get values my-app --all

Ecossistema e Ferramentas do Helm

O ecossistema do Helm inclui inúmeras ferramentas que estendem suas capacidades e integram-se com outras tecnologias Kubernetes. Ao implantar aplicações que requerem recursos avançados de rede como comunicação serviço-a-serviço, gerenciamento de tráfego e políticas de segurança, considere integrar com uma Service Mesh com Istio e Linkerd, que pode ser implantada e gerenciada através de Helm Charts.

Ferramentas Essenciais

  • Helmfile: Especificação declarativa para implantar Helm Charts
  • Helm Diff: Pré-visualizar alterações antes da atualização
  • Helm Secrets: Gerenciar segredos com SOPS
  • Nova: Encontrar Helm Charts desatualizados
  • Pluto: Detectar APIs Kubernetes depreciadas

Exemplo de Helmfile

repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: postgresql
    namespace: database
    chart: bitnami/postgresql
    version: 12.x.x
    values:
      - postgresql:
          auth:
            database: myapp
            username: appuser

  - name: my-app
    namespace: production
    chart: ./charts/my-application
    values:
      - values-production.yaml
    needs:
      - database/postgresql

O Futuro do Helm

O ecossistema do Helm continua evoluindo:

  • Nativo OCI: Transição completa para registros OCI como padrão
  • Segurança Melhorada: Melhor gerenciamento de segredos e capacidades de assinatura
  • Desempenho: Renderização e instalação mais rápidas para Charts grandes
  • Suporte WASM: WebAssembly para plugins e extensões de Chart
  • Validação Melhorada: Validação de schema aprimorada e aplicação de políticas

Conclusão

O Helm tornou-se o padrão de facto para gerenciamento de pacotes Kubernetes, e dominá-lo é essencial para práticas modernas de DevOps. Ao compreender a estrutura de Charts, templating, gerenciamento de valores e melhores práticas, você pode criar implantações Kubernetes mantíveis, seguras e escaláveis.

Comece com Charts simples, incorpore gradualmente recursos avançados como hooks e dependências, e integre com ferramentas GitOps para infraestrutura de nível de produção. A comunidade do Helm fornece milhares de Charts pré-construídos, mas o verdadeiro poder vem da criação de Charts personalizados adaptados às necessidades da sua organização. Seja você esteja implantando aplicações stateless ou cargas de trabalho com estado que requerem armazenamento persistente, o Helm simplifica a complexidade do gerenciamento de recursos Kubernetes. Para equipes configurando novos clusters Kubernetes, considere instalar Kubernetes com Kubespray ou explorar distribuições Kubernetes como k3s ou MicroK8s para ambientes de desenvolvimento. Se você estiver avaliando qual distribuição se adequa às suas necessidades de homelab ou cluster pequeno, veja nossa comparação abrangente de distribuições Kubernetes para uma análise detalhada.

Assinar

Receba novos artigos sobre sistemas, infraestrutura e engenharia de IA.