Como configurar OPA Gatekeeper no Kubernetes
Objetivo
Um cluster Kubernetes sem controle de admissão aceita pods sem resources.limits, imagens em
:latest e namespaces sem label de time — não porque alguém decidiu que está tudo bem, mas porque
nada barra isso antes do objeto ser aceito. OPA Gatekeeper resolve isso aplicando políticas como
código no momento da admissão.
Este guia mostra como instalar o Gatekeeper, criar uma primeira política e validar que ela está funcionando. Não cobre modelagem de políticas complexas em Rego nem integração com pipelines de CI — isso fica para um próximo artigo.
Premissas
- Cluster Kubernetes com acesso de administrador (permissão para instalar CRDs e webhooks).
- Helm 3.x instalado localmente.
- Antes de aplicar em produção, confira a versão do Gatekeeper compatível com a sua versão de Kubernetes na documentação oficial — a matriz de compatibilidade muda entre releases e não está fixada aqui.
- Os comandos e manifestos abaixo seguem a documentação oficial e os templates da gatekeeper-library, mas não foram executados neste ambiente. Mensagens de erro e campos de status mostrados são exemplos do comportamento esperado, não capturas reais — valide na sua versão antes de aplicar em produção.
Implementação
Instalar o Gatekeeper via Helm
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update
helm install gatekeeper gatekeeper/gatekeeper \
--namespace gatekeeper-system \
--create-namespace
Confirme que os pods do controller chegaram a Running antes de continuar:
kubectl get pods -n gatekeeper-system
Se algum pod ficar em CrashLoopBackOff, veja os logs (kubectl logs -n gatekeeper-system <pod>)
antes de prosseguir — nessa etapa, isso costuma indicar falta de permissão para instalar os
webhooks de admissão.
Criar a política: exigir label obrigatória em namespace
Gatekeeper separa a definição da regra (ConstraintTemplate, em Rego) da aplicação dela
(Constraint, que define o escopo). O exemplo a seguir exige que todo Namespace tenha a label
team:
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: requiredlabels
spec:
crd:
spec:
names:
kind: RequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package requiredlabels
violation[{"msg": msg}] {
required := input.parameters.labels
provided := input.review.object.metadata.labels
missing := required[_]
not provided[missing]
msg := sprintf("label obrigatória ausente: %v", [missing])
}
Essa sintaxe Rego segue o padrão usado nos templates públicos da gatekeeper-library. Se a sua
versão do Gatekeeper exigir Rego v1 (import rego.v1 e if), ajuste a regra de acordo.
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequiredLabels
metadata:
name: require-team-label
spec:
enforcementAction: dryrun
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
excludedNamespaces: ["kube-system", "gatekeeper-system"]
parameters:
labels: ["team"]
Dois pontos nesse manifesto costumam ser esquecidos e causar incidente:
enforcementAction: dryrun— na primeira aplicação, a constraint só registra violações, sem bloquear nada. Isso permite ver o impacto antes de decidir bloquear de verdade.excludedNamespaces— sem excluirkube-systeme o própriogatekeeper-system, a política pode acabar bloqueando objetos internos do cluster e do próprio controller.
Validação
Com a constraint em dryrun, revise as violações registradas sem que nada seja bloqueado:
kubectl get requiredlabels require-team-label -o yaml
O campo status.violations lista os namespaces que não atendem à política. Revise essa lista antes
de mudar enforcementAction para deny.
Depois de confirmar que o comportamento em dryrun está de acordo com o esperado, mude para deny
e teste criando um namespace sem a label:
kubectl create namespace teste-sem-label
Com enforcementAction: deny, essa requisição deve ser rejeitada pelo admission controller, com uma
mensagem citando a violação definida no Rego (label obrigatória ausente: team).
Limitações relevantes
- Não é retroativo. Objetos criados antes da constraint entrar em vigor não são revalidados
automaticamente. O Gatekeeper tem um mecanismo de auditoria (
kubectl get constraints) que lista violações em objetos já existentes, mas isso é auditoria, não bloqueio. - Rego tem curva de aprendizado. Para políticas simples (labels, limits, proibir
:latest), vale usar os templates prontos da gatekeeper-library antes de escrever Rego do zero. - Isto não substitui teste em ambiente de homologação. Qualquer política nova deveria passar por
dryrunem um cluster de não produção antes de ir para produção comdeny.
Próximo passo
Para aplicar mais de uma política, comece adaptando os templates prontos da gatekeeper-library em vez de escrever Rego para cada caso — isso reduz a superfície de erro e mantém a política alinhada com o que a comunidade já testou e mantém.