Testing Kubernetes manifests: kubeval, conftest e datree

1. Introdução à validação de manifests Kubernetes

Em pipelines DevOps modernos, a validação de manifests Kubernetes deixou de ser opcional para se tornar uma etapa crítica. Um YAML mal formatado, uma imagem sem tag ou um campo ausente podem causar falhas em produção, rollbacks emergenciais ou até brechas de segurança. Testar manifests antes de aplicá-los ao cluster reduz drasticamente o ciclo de feedback e aumenta a confiabilidade das entregas.

Existem três tipos principais de validação:
- Sintática: verifica se o YAML é válido e adere ao schema da API do Kubernetes.
- Semântica: checa regras de negócio e políticas organizacionais.
- Boas práticas: assegura conformidade com recomendações de segurança, performance e resiliência.

Três ferramentas se destacam nesse ecossistema: kubeval, conftest e datree. Cada uma cobre uma camada específica, e combiná-las em pipeline é a abordagem recomendada por especialistas DevOps.

2. kubeval: validação estrutural contra a OpenAPI do Kubernetes

O kubeval utiliza os schemas OpenAPI oficiais do Kubernetes para validar se um manifest está estruturalmente correto. Ele não executa lógica de negócio, mas garante que os campos obrigatórios existam, os tipos estejam corretos e a versão da API seja suportada.

Uso básico:

# Validar um único arquivo
kubeval deployment.yaml

# Validar múltiplos arquivos
kubeval deployment.yaml service.yaml

# Validar recursivamente um diretório
kubeval --directories ./manifests/

# Ignorar schemas de CRDs não encontrados
kubeval --ignore-missing-schemas deployment.yaml

Integração com CI/CD (GitHub Actions):

# .github/workflows/kubeval.yml
name: Validate Kubernetes manifests
on: [push]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install kubeval
        run: |
          wget https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz
          tar xf kubeval-linux-amd64.tar.gz
          sudo mv kubeval /usr/local/bin
      - name: Validate manifests
        run: kubeval --strict --directories ./k8s/

O kubeval é ideal para validação rápida em estágios iniciais do pipeline, pois executa em milissegundos e não requer configuração complexa.

3. conftest: políticas declarativas com Rego (OPA)

O conftest utiliza o Open Policy Agent (OPA) e sua linguagem Rego para definir políticas personalizadas. Diferente do kubeval, que apenas verifica schemas, o conftest permite impor regras de negócio como "nenhuma imagem com tag latest" ou "todo container deve ter resource limits definidos".

Exemplo de política Rego (policy/deny.rego):

package main

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  endswith(container.image, ":latest")
  msg := sprintf("Container %v uses 'latest' tag", [container.name])
}

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  not container.resources.limits
  msg := sprintf("Container %v has no resource limits", [container.name])
}

Execução:

# Testar políticas contra um manifest
conftest test deployment.yaml --policy policy/

# Saída esperada:
# FAIL - deployment.yaml - Container nginx uses 'latest' tag
# FAIL - deployment.yaml - Container nginx has no resource limits

Integração com kubeval em pipeline:

# pipeline.sh
kubeval --strict deployment.yaml && \
conftest test deployment.yaml --policy policy/ && \
echo "All validations passed"

O conftest é a ferramenta certa quando você precisa de políticas customizadas e auditáveis, especialmente em organizações com compliance rigoroso.

4. datree: prevenção de configurações incorretas contra melhores práticas

O datree oferece um catálogo de centenas de regras pré-definidas baseadas nas melhores práticas da comunidade Kubernetes. Ele cobre segurança, confiabilidade, performance e boas práticas de cluster. Seu diferencial é o modo interativo que sugere correções e a capacidade de bloquear PRs automaticamente.

Uso via CLI:

# Testar um manifest
datree test deployment.yaml

# Testar recursivamente um diretório
datree test ./k8s/ --schema-version 1.27

# Modo silencioso para CI
datree test deployment.yaml --output json

Exemplo de saída com sugestões:

$ datree test deployment.yaml
>> Error: container "nginx" has no memory limit defined
   Suggestion: Add resources.limits.memory to container "nginx"
   Rule: ensure-memory-limit
   Link: https://hub.datree.io/rules/ensure-memory-limit

>> Error: container "nginx" uses image tag "latest"
   Suggestion: Use a fixed version tag like "1.25.0"
   Rule: no-latest-tag

Diferenciais do datree:
- Análise de contexto: considera namespace, cluster e versão do Kubernetes.
- Bloqueio em PRs via integração com GitHub/GitLab.
- Catálogo de regras atualizado continuamente pela comunidade.

5. Comparação prática entre as ferramentas

Característica kubeval conftest datree
Tipo de validação Estrutural (schema) Políticas (Rego) Boas práticas
Velocidade Muito rápida Rápida Moderada
Regras pré-definidas Não Não (crie as suas) Sim (centenas)
Customização Limitada Total (Rego) Limitada (config)
Saída interativa Não Não Sim
Ideal para CI rápido Regras de negócio Compliance

Cenários ideais:
- kubeval: validação inicial em cada commit, antes de qualquer outra etapa.
- conftest: políticas corporativas que exigem auditoria e versionamento.
- datree: equipes que querem adotar boas práticas sem criar regras do zero.

Combinação em pipeline:

# Pipeline de validação em camadas
# 1. Lint YAML
yamllint ./k8s/

# 2. Validação estrutural
kubeval --strict --directories ./k8s/

# 3. Políticas customizadas
conftest test ./k8s/ --policy ./policies/

# 4. Boas práticas
datree test ./k8s/ --schema-version 1.27

# Se tudo passar, prossegue para deploy

6. Implementação em pipelines DevOps com Docker e Kubernetes

Dockerfile multi-stage para testar manifests antes do build:

FROM alpine:3.18 AS validator

RUN apk add --no-cache curl tar
RUN wget -q https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz && \
    tar xf kubeval-linux-amd64.tar.gz && \
    mv kubeval /usr/local/bin/
RUN wget -q https://github.com/open-policy-agent/conftest/releases/latest/download/conftest_linux_amd64.tar.gz && \
    tar xf conftest_linux_amd64.tar.gz && \
    mv conftest /usr/local/bin/
RUN curl -fsSL https://get.datree.io | sh

COPY k8s/ /k8s/
COPY policies/ /policies/

RUN kubeval --strict --directories /k8s/ && \
    conftest test /k8s/ --policy /policies/ && \
    datree test /k8s/ --schema-version 1.27

FROM node:18-alpine AS app
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["node", "index.js"]

Pipeline CI/CD com validação sequencial:

# .gitlab-ci.yml
stages:
  - validate
  - build
  - deploy

validate-manifests:
  stage: validate
  image: alpine:3.18
  before_script:
    - apk add --no-cache curl tar
    - wget -q https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz
    - tar xf kubeval-linux-amd64.tar.gz && mv kubeval /usr/local/bin/
    - wget -q https://github.com/open-policy-agent/conftest/releases/latest/download/conftest_linux_amd64.tar.gz
    - tar xf conftest_linux_amd64.tar.gz && mv conftest /usr/local/bin/
    - curl -fsSL https://get.datree.io | sh
  script:
    - kubeval --strict --directories ./k8s/
    - conftest test ./k8s/ --policy ./policies/
    - datree test ./k8s/ --schema-version 1.27

Validação de manifests renderizados por Helm ou Kustomize:

# Helm
helm template release ./chart/ | kubeval --strict --stdin
helm template release ./chart/ | conftest test --policy ./policies/ --stdin
helm template release ./chart/ | datree test --stdin

# Kustomize
kustomize build ./overlays/prod/ | kubeval --strict --stdin
kustomize build ./overlays/prod/ | conftest test --policy ./policies/ --stdin
kustomize build ./overlays/prod/ | datree test --stdin

7. Boas práticas e armadilhas comuns

Evitar falsos positivos:

  • Versões de API obsoletas: o kubeval pode rejeitar manifests com apiVersion: apps/v1beta2. Sempre use schemas da versão do seu cluster.
  • Schemas parciais: para CRDs, use --ignore-missing-schemas no kubeval ou forneça os schemas manualmente.

Gerenciamento de dependências:

  • Para CRDs customizados, mantenha os schemas OpenAPI em um repositório central.
  • O conftest permite importar pacotes Rego de outros arquivos, facilitando a reutilização.

Versionamento de regras:

  • Armazene políticas do conftest e configurações do datree no mesmo repositório dos manifests.
  • Use tags Git para versionar as regras junto com o código da aplicação.

Armadilhas comuns:

  • Ignorar warnings do kubeval pode esconder problemas reais.
  • Políticas muito restritivas no conftest podem quebrar o pipeline sem necessidade.
  • O datree pode sugerir correções que conflitam com configurações específicas do cluster.

8. Conclusão e próximos passos

A validação de manifests Kubernetes é uma prática indispensável em pipelines DevOps modernos. kubeval, conftest e datree formam uma combinação poderosa que cobre desde a estrutura básica até políticas de compliance e boas práticas. Enquanto o kubeval oferece velocidade e simplicidade, o conftest traz flexibilidade para regras customizadas, e o datree acelera a adoção de padrões de qualidade.

Para equipes que já utilizam Helm ou Kustomize, a integração com essas ferramentas é direta e permite validar os manifests renderizados antes do deploy. O próximo passo natural é explorar ferramentas como kube-score para análises mais profundas e kyverno para políticas no cluster.

Checklist para implementação em produção:
1. Adicione kubeval no estágio mais inicial do pipeline.
2. Crie políticas Rego básicas com conftest (no latest, resource limits, probes).
3. Configure datree com as regras de segurança e performance do seu time.
4. Teste a pipeline com manifests reais e ajuste falsos positivos.
5. Documente as regras e compartilhe com o time de desenvolvimento.

Referências