DEV Community

Cover image for Kyverno Policy as Code no Kubernetes
Kauê Matos
Kauê Matos

Posted on

Kyverno Policy as Code no Kubernetes

Kyverno (do grego "governar") é um motor de políticas nativo do Kubernetes, projeto da CNCF, que permite validar, alterar e gerar recursos do cluster usando apenas YAML, sem aprender uma linguagem nova.

Em clusters compartilhados, qualquer pessoa com acesso ao kubectl apply pode criar um Pod privilegiado, uma imagem sem tag ou um Service exposto sem querer. Revisão manual não escala, e documentação de boas práticas não impede ninguém de errar. O Kyverno resolve isso aplicando regras no momento em que o recurso chega à API do Kubernetes, antes de ele ser persistido no etcd.

O diferencial frente a outras ferramentas é que as políticas são recursos Kubernetes comuns (ClusterPolicy, Policy), versionáveis em Git e entregues por GitOps. Quem já escreve manifests consegue escrever políticas no mesmo dia.

O que o Kyverno faz, em resumo:

  • Validar: bloquear ou apenas auditar recursos fora do padrão (por exemplo, containers rodando como root).
  • Mutar: injetar valores padrão (labels, securityContext, imagePullPolicy) automaticamente.
  • Gerar: criar recursos derivados, como NetworkPolicy e ResourceQuota em todo novo namespace.
  • Verificar imagens: exigir assinaturas e atestações (Cosign/Sigstore) antes de rodar uma imagem.
  • Limpar: remover recursos expirados por regras de TTL ou de agendamento.

Arquitetura

O Kyverno roda dentro do cluster como um conjunto de controladores, e o principal deles é um admission webhook registrado no API Server.

[embedded content: fluxo de admissão e componentes do Kyverno]

Quando uma requisição de criação ou atualização chega ao API Server, ele consulta o webhook do Kyverno, que avalia as políticas e devolve a decisão: aprovar, negar ou aprovar com alterações (patch). Só o que é aprovado é gravado no etcd.

Os componentes:

  • Admission controller: atende o webhook, aplicando as regras validate, mutate e verifyImages em tempo real.
  • Background controller: processa regras generate e mutate sobre recursos existentes.
  • Reports controller: consolida os resultados em PolicyReport e ClusterPolicyReport.
  • Cleanup controller: executa as políticas de limpeza e a remoção por TTL.

Como cada controlador é um Deployment separado, dá para dimensionar e escalar cada um de forma independente. Por exemplo, o admission controller, que fica no caminho de toda requisição, merece mais réplicas e mais atenção que os demais.

Tipos de regras

Uma política tem uma ou mais regras, e cada regra declara um match (a quais recursos se aplica), condições opcionais (exclude, preconditions) e uma ação. Existem cinco tipos de ação.

Tipo O que faz Quando roda
validate Aprova ou rejeita o recurso conforme um padrão, uma expressão CEL ou deny com condições Admissão e varredura em background
mutate Altera o recurso, via merge patch, JSON patch ou foreach Admissão (e sobre recursos existentes, se configurado)
generate Cria ou sincroniza outros recursos a partir de um gatilho Quando o recurso gatilho é criado ou atualizado
verifyImages Confere assinaturas e atestações de imagens de container Admissão de Pods e workloads
cleanup Apaga recursos que casam com uma condição, em um cronograma Periodicamente (CleanupPolicy)

A ordem importa: o Kubernetes executa as mutações antes das validações, então uma política mutate pode preencher um campo que uma política validate exige logo depois.

A ação de uma política validate depende do campo validationFailureAction. Com Audit, a violação é registrada, mas o recurso passa. Com Enforce, a requisição é negada e o usuário recebe a mensagem de erro definida na política. Nas versões mais recentes essa configuração pode ser refinada por namespace, o que facilita uma adoção gradual.

Exemplos práticos

Os três exemplos abaixo usam a API kyverno.io/v1 (ClusterPolicy). Os nomes de campos podem variar entre versões, então confira a documentação da versão instalada.

1. Validar: exigir limites de recursos

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: check-limits
      match:
        any:
          - resources:
              kinds: [Pod]
      validate:
        message: "Todos os containers devem definir limits de CPU e memória."
        pattern:
          spec:
            containers:
              - resources:
                  limits:
                    memory: "?*"
                    cpu: "?*"
Enter fullscreen mode Exit fullscreen mode

2. Mutar: adicionar um padrão de segurança

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-security-context
spec:
  rules:
    - name: set-run-as-non-root
      match:
        any:
          - resources:
              kinds: [Pod]
      mutate:
        patchStrategicMerge:
          spec:
            securityContext:
              +(runAsNonRoot): true
Enter fullscreen mode Exit fullscreen mode

O prefixo +() é um "anchor" de adição: o valor só é inserido se o campo ainda não existir, respeitando o que o desenvolvedor já definiu.

3. Gerar: NetworkPolicy padrão em todo namespace novo

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: default-deny-ingress
spec:
  rules:
    - name: generate-default-deny
      match:
        any:
          - resources:
              kinds: [Namespace]
      generate:
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        name: default-deny-ingress
        namespace: "{{request.object.metadata.name}}"
        synchronize: true
        data:
          spec:
            podSelector: {}
            policyTypes: [Ingress]
Enter fullscreen mode Exit fullscreen mode

Com synchronize: true, se alguém apagar ou editar a NetworkPolicy gerada, o Kyverno a restaura. Isso transforma a regra em uma garantia contínua, e não apenas em um passo inicial.

Policy Reports, Audit vs Enforce e exceções

O caminho seguro para adotar o Kyverno em um cluster existente é começar em Audit, medir o impacto e só então passar para Enforce.

O Kyverno grava os resultados de cada avaliação em recursos PolicyReport (por namespace) e ClusterPolicyReport, no formato padronizado da comunidade (Policy WG). Com background: true, as políticas também varrem recursos que já existem, e não só os novos. Assim você descobre quantos workloads violariam a regra antes de bloquear qualquer deploy.

kubectl get policyreport -A
kubectl get clusterpolicyreport -o wide
Enter fullscreen mode Exit fullscreen mode

Um roteiro de adoção que funciona bem:

  1. Instale a política em Audit e deixe rodar alguns dias.
  2. Leia os relatórios (ou exporte para Prometheus/Grafana) e corrija os workloads que violam.
  3. Trate os casos legítimos com exceções, nunca afrouxando a regra para todos.
  4. Mude para Enforce, começando por namespaces não críticos.

Para exceções pontuais existem duas ferramentas: o bloco exclude dentro da própria regra (por namespace, label, usuário ou role) e o recurso PolicyException, que permite a uma equipe pedir a isenção de uma política específica sem editar a política original. O PolicyException costuma ser mais auditável, porque cada exceção vira um objeto próprio, com dono e histórico no Git.

Também vale excluir os namespaces do sistema (kube-system, o próprio namespace do Kyverno) das políticas mais restritivas, para não travar componentes essenciais do cluster.

Kyverno CLI e testes no CI/CD

O Kyverno CLI aplica as mesmas políticas fora do cluster, o que permite barrar um manifest inválido no pull request, bem antes do deploy.

Há dois comandos principais:

  • kyverno apply: avalia políticas contra manifests locais (ou contra recursos de um cluster) e imprime aprovações e violações.
  • kyverno test: roda uma suíte de testes declarativa, comparando o resultado esperado de cada regra com o obtido.
# Valida os manifests do repositório contra as políticas
kyverno apply ./policies --resource ./k8s/deployment.yaml

# Executa os testes das políticas
kyverno test ./policies
Enter fullscreen mode Exit fullscreen mode

Um arquivo kyverno-test.yaml lista as políticas, os recursos de entrada e o resultado esperado (pass, fail, skip) por regra. Tratar políticas como código significa testá-las como código: um teste de que o recurso ruim falha e o recurso bom passa evita que uma edição "inocente" na política abra uma brecha.

Em um pipeline do GitHub Actions, o fluxo típico é:

  1. Fazer checkout do repositório de manifests e de políticas.
  2. Instalar o CLI (ação oficial ou download do binário).
  3. Rodar kyverno test nas políticas e kyverno apply nos manifests da aplicação.
  4. Falhar o job se houver violações em políticas de severidade alta.

O resultado é um feedback em segundos para quem abriu o PR, e o admission controller do cluster fica como última linha de defesa, não como a primeira.

Instalação e operação em produção

A instalação recomendada é via Helm, em um namespace dedicado e com réplicas suficientes para alta disponibilidade.

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update

helm install kyverno kyverno/kyverno \
  -n kyverno --create-namespace \
  --set admissionController.replicas=3
Enter fullscreen mode Exit fullscreen mode

Em produção, alguns pontos merecem atenção desde o primeiro dia:

  • Alta disponibilidade: use três réplicas do admission controller, com PodDisruptionBudget e anti-afinidade. Como o webhook está no caminho de toda requisição de criação, uma indisponibilidade pode travar deploys.
  • failurePolicy do webhook: com Fail, se o Kyverno estiver fora do ar, as requisições são negadas (mais seguro, menos disponível). Com Ignore, elas passam sem validação. Escolha de forma consciente por cluster.
  • Recursos e escala: o consumo de memória cresce com o número de recursos no cluster e de políticas. Defina requests e limits e acompanhe as métricas.
  • Observabilidade: o Kyverno expõe métricas Prometheus (latência de admissão, resultados por política). O Policy Reporter, projeto complementar, entrega dashboards e notificações a partir dos PolicyReport.
  • Políticas via GitOps: mantenha as políticas em um repositório próprio e aplique com Argo CD ou Flux, para que toda mudança tenha revisão e histórico.
  • Evite o webhookConfiguration ruidoso: restrinja o match aos tipos de recurso necessários, para o Kyverno não ser chamado em requisições irrelevantes.

Kyverno vs OPA/Gatekeeper e ValidatingAdmissionPolicy

Kyverno se destaca pela curva de aprendizado baixa e pelo escopo amplo (mutar, gerar e verificar imagens); o Gatekeeper é a escolha de quem já usa OPA e Rego em outros sistemas; a ValidatingAdmissionPolicy nativa cobre validações simples sem instalar nada.

Critério Kyverno OPA/Gatekeeper ValidatingAdmissionPolicy (nativa)
Linguagem das regras YAML, com CEL e JMESPath em casos avançados Rego (via ConstraintTemplate) CEL
Valida Sim Sim Sim
Muta Sim Sim, com recursos mais limitados Há política de mutação nativa, mais recente
Gera recursos Sim Não Não
Verifica assinatura de imagens Sim (Cosign/Notary) Não nativamente Não
Componente extra no cluster Sim Sim Não, roda dentro do API server
Curva de aprendizado Baixa para quem conhece YAML Alta (Rego) Média (CEL)

Na prática, as três opções não são excludentes. Há times que usam a ValidatingAdmissionPolicy para regras simples e de alta performance e o Kyverno para mutação, geração e verificação de imagens. O próprio Kyverno vem incorporando CEL e novos tipos de política para se aproximar do modelo nativo, então vale conferir na documentação o estado atual dessa evolução antes de escolher o formato das suas políticas.

Uma regra de bolso: se o time já domina Rego e usa OPA fora do Kubernetes, o Gatekeeper preserva o investimento. Se a prioridade é adotar rápido, com políticas legíveis por qualquer pessoa que escreva manifests, o Kyverno costuma ser o caminho mais curto.

Boas práticas e armadilhas comuns

A maior parte dos problemas com Kyverno vem de adotar rápido demais ou de escrever regras amplas demais.

  • Comece em Audit: bloquear no primeiro dia é o jeito mais rápido de gerar resistência das equipes.
  • Mensagens de erro claras: diga o que está errado e como corrigir. Uma mensagem boa economiza um chamado de suporte.
  • Uma política, um objetivo: políticas pequenas e nomeadas pelo que fazem (require-labels, disallow-latest-tag) são mais fáceis de testar, excluir e auditar.
  • Reaproveite as políticas da comunidade: o catálogo de políticas do Kyverno cobre o Pod Security Standards, boas práticas de rede e supply chain, e serve de ponto de partida.
  • Cuidado com generate e mutate em cascata: regras que geram recursos que disparam outras regras são difíceis de depurar. Teste com kyverno test antes.
  • Exclua componentes críticos: o kube-system e o próprio Kyverno devem ficar fora das regras mais restritivas, para evitar o deadlock de um cluster que não consegue subir os próprios pods.
  • Revise exceções periodicamente: exceções temporárias tendem a virar permanentes se ninguém as reavalia.
  • Versione tudo no Git: políticas, testes e exceções, com revisão por pull request.

Conclusão

O Kyverno transforma boas práticas de segurança e governança em regras executáveis, escritas na mesma linguagem dos manifests que o time já domina. Ele valida e muta na admissão, gera recursos que precisam existir em todo namespace e confere a origem das imagens, tudo versionado em Git e testável no CI.

Para começar, instale o Kyverno em um cluster de teste, aplique uma política de validação em Audit, leia os PolicyReport e evolua gradualmente até o Enforce. Em poucos dias você terá uma visão concreta do quanto o cluster se afasta do padrão desejado, e um caminho seguro para corrigir isso.

Top comments (0)