Helm: gerenciador de pacotes do Kubernetes

1. Introdução ao Helm e seus conceitos fundamentais

No ecossistema DevOps, gerenciar aplicações no Kubernetes pode se tornar rapidamente complexo à medida que o número de manifestos YAML cresce. O Helm surge como o gerenciador de pacotes oficial do Kubernetes, permitindo definir, instalar e atualizar aplicações de forma padronizada e reutilizável.

O Helm é essencial para equipes DevOps porque abstrai a complexidade dos manifestos Kubernetes, oferecendo versionamento, gerenciamento de dependências e facilidade de rollback. Seus três componentes principais são:

  • Chart: Pacote contendo todos os recursos Kubernetes necessários para executar uma aplicação (Deployments, Services, ConfigMaps, etc.)
  • Release: Uma instância específica de um Chart em execução no cluster
  • Repository: Local onde Charts são armazenados e compartilhados

Uma mudança significativa ocorreu entre o Helm 2 e o Helm 3. No Helm 2, existia o Tiller, um componente server-side instalado no cluster que geria as releases. O Helm 3 removeu completamente o Tiller, tornando-se um cliente puro que interage diretamente com a API do Kubernetes via kubeconfig, aumentando significativamente a segurança.

2. Instalação e configuração do Helm

A instalação do cliente Helm é simples em qualquer sistema operacional. No Linux, por exemplo:

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

No macOS via Homebrew:

brew install helm

Após a instalação, é necessário adicionar repositórios de Charts. O repositório oficial da Bitnami é um dos mais utilizados:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

Comandos básicos para explorar Charts disponíveis:

helm search repo bitnami/nginx
helm search hub nginx
helm list

O comando helm list mostra todas as releases instaladas no namespace atual.

3. Estrutura de um Helm Chart

Um Chart Helm segue uma estrutura de diretórios padronizada. Vamos criar um Chart de exemplo:

helm create meu-nginx

A estrutura gerada é:

meu-nginx/
├── Chart.yaml          # Metadados do Chart (nome, versão, descrição)
├── values.yaml         # Valores padrão que podem ser sobrescritos
├── charts/             # Dependências (subcharts)
├── templates/          # Templates Go dos manifestos Kubernetes
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   └── _helpers.tpl    # Funções auxiliares
└── .helmignore         # Arquivos a ignorar no empacotamento

O template engine Go permite injetar valores dinâmicos nos manifestos. Exemplo de sintaxe básica:

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-nginx
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
        - name: nginx
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

Os valores são definidos no values.yaml:

# values.yaml
replicaCount: 3
image:
  repository: nginx
  tag: stable

4. Instalação, upgrade e rollback de releases

Para instalar um Chart, utilizamos o comando helm install. Vamos instalar o Chart que criamos:

helm install meu-servidor ./meu-nginx

Podemos personalizar valores durante a instalação:

helm install meu-servidor ./meu-nginx --set replicaCount=5 --set image.tag=1.25.0

Ou utilizando um arquivo de valores customizado:

helm install meu-servidor ./meu-nginx -f valores-producao.yaml

Para atualizar uma release já existente:

helm upgrade meu-servidor ./meu-nginx --set image.tag=1.26.0

O Helm mantém um histórico de releases. Para visualizar:

helm history meu-servidor

Em caso de problemas com a atualização, o rollback é simples:

helm rollback meu-servidor 1

O número 1 refere-se à revisão anterior no histórico. O Helm automaticamente reverte todos os recursos Kubernetes ao estado daquela revisão.

5. Personalizando Charts com values e variáveis

A personalização de Charts é uma das funcionalidades mais poderosas do Helm. Podemos sobrescrever valores de várias formas, com diferentes níveis de prioridade.

Arquivo values.yaml customizado:

# valores-producao.yaml
replicaCount: 10
image:
  repository: nginx
  tag: 1.25.3-alpine
service:
  type: LoadBalancer
  port: 80
resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

Uso de --set para parâmetros inline:

helm upgrade meu-servidor ./meu-nginx \
  --set image.tag=1.26.0 \
  --set resources.limits.cpu=1 \
  --set resources.limits.memory=1Gi

A hierarquia de valores segue esta ordem de precedência (do maior para o menor):

  1. --set (inline)
  2. Arquivo passado com -f ou --values
  3. values.yaml do Chart
  4. Valores padrão definidos no template

Para valores globais que devem ser acessíveis em subcharts, usamos:

# values.yaml
global:
  environment: production
  registry: registry.internal.company.com

6. Empacotamento e distribuição de Charts próprios

Criar um Chart do zero é facilitado pelo comando helm create. Após desenvolver o Chart, é importante validá-lo:

helm lint ./meu-nginx

O comando helm lint verifica a estrutura, sintaxe dos templates e valores obrigatórios.

Para empacotar o Chart em um arquivo .tgz:

helm package ./meu-nginx

Isso gera meu-nginx-0.1.0.tgz. Para versionamento, atualizamos a versão no Chart.yaml antes de empacotar.

Para distribuir Charts, podemos usar o ChartMuseum, um servidor HTTP para Charts Helm:

helm repo add chartmuseum http://chartmuseum.internal.com
helm push meu-nginx-0.1.0.tgz chartmuseum

Outra opção popular é utilizar GitHub Pages para hospedar um repositório de Charts. Basta criar um diretório docs no repositório, adicionar os arquivos .tgz e gerar o índice:

helm repo index docs/ --url https://seuusuario.github.io/meu-repo

7. Boas práticas DevOps com Helm

No contexto DevOps, o Helm deve ser integrado ao pipeline CI/CD. O versionamento semântico é fundamental:

# Chart.yaml
apiVersion: v2
name: meu-nginx
version: 1.2.3
appVersion: 1.26.0

A versão do Chart (version) deve seguir SemVer e ser incrementada a cada alteração. A appVersion indica a versão da aplicação empacotada.

Exemplo de pipeline CI/CD com GitHub Actions:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Lint Chart
        run: helm lint ./charts/app
      - name: Package Chart
        run: helm package ./charts/app --version ${{ github.ref_name }}
      - name: Deploy
        run: |
          helm upgrade --install minha-app ./charts/app \
            --namespace production \
            --set image.tag=${{ github.sha }}

Gerenciamento de dependências com subcharts:

# Chart.yaml
dependencies:
  - name: postgresql
    version: 12.x.x
    repository: https://charts.bitnami.com/bitnami
  - name: redis
    version: 17.x.x
    repository: https://charts.bitnami.com/bitnami

Para atualizar dependências:

helm dependency update ./meu-nginx

Quanto à segurança, o Helm permite assinar Charts com GPG:

helm package --sign --key 'meu-email@exemplo.com' ./meu-nginx
helm verify meu-nginx-0.1.0.tgz

Isso garante a integridade e autenticidade dos Charts distribuídos.

Referências