6 min de leitura

Kubernetes v1.36: Políticas de admissão imutáveis no disco fecham a última lacuna de segurança

Modern building structure against a cloudy sky
Photo by Cuvii on Unsplash

Durante anos, a segurança do Kubernetes carregou uma contradição silenciosa: as regras que protegiam o cluster podiam ser apagadas por qualquer um com privilégios suficientes. O Kubernetes v1.36 resolve essa falha de raiz com políticas de admissão gravadas em disco — imutáveis, ativas desde o milissegundo zero e invisíveis até para o mais poderoso cluster-admin.

O problema que ninguém queria admitir

Políticas de admissão sempre foram tratadas como recursos comuns da API. Criadas, modificadas e removidas como um Deployment qualquer. O modelo funcionava — até o momento em que alguém, por acidente ou intenção, apagava exatamente a regra que mantinha o cluster seguro.

Esse modelo carregava duas fragilidades estruturais que tiravam o sono de qualquer engenheiro de plataforma:

  1. Janela de bootstrap exposta: quando o cluster sobe, nenhuma política de admissão existe ainda. Por segundos ou minutos, o ambiente opera completamente desprotegido — tempo suficiente para configurações indesejadas entrarem em produção.
  2. Auto-sabotagem permitida: políticas são objetos da API. Para protegê-las, você precisaria de outra política — que também pode ser deletada. Um loop lógico sem saída, impossível de resolver sem mecanismos externos.
O resultado era um ecossistema permanentemente dependente de vigilância externa: controladores de reconciliação, GitOps rigoroso e monitoramento constante. Faltava uma camada realmente imutável.

A virada: YAML no disco, segurança antes de tudo

Ilustração conceitual: manifestos YAML imutáveis sendo carregados em um servidor Kubernetes com estética cyber-blue e neon glow

O Kubernetes v1.36 introduz o controle de admissão baseado em manifestos estáticos (alpha). A ideia é simples na superfície e profunda nas implicações: políticas de admissão são carregadas diretamente de arquivos YAML no sistema de arquivos do API server, apontados pela configuração staticManifestsDir.

Os manifestos são lidos e aplicados antes que o API server aceite qualquer requisição. A janela de bootstrap simplesmente deixa de existir.

Como funciona na prática

O mecanismo é elegante e implacável ao mesmo tempo. Veja os pilares do funcionamento:

  • Localização: arquivos .yaml depositados no diretório de manifestos estáticos do API server.
  • Nomenclatura rígida: todo recurso precisa ter nome terminado em .static.k8s.io — isso evita conflitos com recursos da API e torna a origem dos objetos imediatamente identificável.
  • Carga implacável: se um manifesto tiver erro de sintaxe ou validação, o API server recusa-se a iniciar. Segurança total desde o primeiro byte.
  • Atualizações em runtime: o API server monitora o diretório e aplica mudanças atomicamente, sem restart. Se a nova versão falhar, a configuração anterior permanece em vigor.
  • Imutabilidade via API: qualquer tentativa de deletar ou alterar uma política estática pela API é rejeitada. Nem o cluster-admin consegue — é preciso acesso direto ao sistema de arquivos.

O termo ".static.k8s.io" não é cosmético — é uma âncora de identidade que o API server usa para distinguir políticas de disco das políticas efêmeras da API. Sem esse sufixo, o manifesto é ignorado.

Exemplo prático: namespaces com dono obrigatório

Imagine que você quer garantir que todo namespace tenha um label owner preenchido. Com um manifesto estático, a política fica assim:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: enforce-ns-labels.static.k8s.io
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["namespaces"]
  validations:
  - expression: "has(object.metadata.labels.owner) && object.metadata.labels.owner != ''"
    message: "Every namespace must have a non-empty owner label."

E o binding correspondente — que ativa a política para todos os namespaces — também vive no mesmo diretório estático:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: enforce-ns-labels-binding.static.k8s.io
spec:
  policyName: enforce-ns-labels.static.k8s.io
  validationActions: [Deny]
  matchResources:
    namespaceSelector: {}

Uma vez no disco, essa política está no ar antes de qualquer workload e não pode ser removida pela API.

Por que isso é uma virada técnica — e estratégica

O cluster já nasce blindado

Acabou aquele intervalo de segundos com o cluster "pelado". As políticas estão ativas antes do primeiro comando administrativo ou da primeira implantação. Para clusters de produção que precisam de conformidade desde o instante zero, isso não é luxo — é requisito.

Políticas que protegem a si mesmas

Agora é possível criar uma ValidatingAdmissionPolicy que valida operações sobre outras políticas de admissão e webhooks. Como essa regra vive no disco, ela é imune a remoções pela API. A pergunta milenar — "quem vigia os vigias?" — finalmente tem resposta no ecossistema Kubernetes.

Recuperação sem beco sem saída

Se uma política defeituosa travar o cluster, basta corrigir o arquivo no disco. Não é necessário acessar a API — que poderia estar inacessível justamente por causa da regra problemática. Fim do loop de dependência circular que sempre apavorou administradores.

Modelo descentralizado e robusto

Cada instância do API server carrega seus próprios manifestos. Não há sincronização automática entre réplicas — semelhante ao modelo de encryption-at-rest. Isso exige cuidado extra em ambientes multi-master, mas também elimina problemas de consistência distribuída na carga inicial.

A regra que protege as outras regras não pode ser apagada. A segurança passa a ser garantida pelo sistema de arquivos, não por RBAC.

O que muda para times de plataforma e para o mercado

ImpactoDetalhamento
Segurança nativa fortalecidaRedução da dependência de ferramentas externas como OPA/Gatekeeper e Kyverno para políticas baseline imutáveis.
Adoção de CEL aceleradaPolíticas baseadas em Common Expression Language ganham apelo massivo ao serem imutáveis e ativas o tempo todo.
Maturidade multi-tenantPlataformas compartilhadas podem garantir que políticas de isolamento e conformidade nunca sejam removidas — nem por admins.
Conformidade regulatóriaAuditorias podem verificar que políticas críticas estão em disco — imutáveis por definição — e não apenas na API, onde seriam efêmeras.

Cuidados e limitações que você precisa conhecer

A funcionalidade é poderosa, mas ainda está em alpha no v1.36. Isso significa que você deve testar exaustivamente antes de pensar em produção. Além disso, há restrições importantes:

  • Sem sincronização entre API servers: cada nó master vê seu próprio conjunto de arquivos. Sem um sistema externo de gerenciamento, pode ocorrer drift de configuração entre réplicas.
  • Sem paramKind: não é possível parametrizar políticas com outros objetos. Apenas expressões CEL autocontidas.
  • Webhooks estáticos só aceitam URL: referências a Services internos do cluster não são permitidas para webhooks carregados do disco.
  • Bindings limitados: bindings estáticos só conseguem referenciar políticas do mesmo conjunto de manifestos.
  • Resgate exige acesso ao disco: se um administrador remoto não tiver SSH ou acesso ao sistema de arquivos, corrigir uma política problemática pode ser um drama real.
  • Carga inicial rígida: um YAML inválido impede a subida do API server. Teste os manifestos em ambiente isolado antes de aplicá-los.

Em ambientes multi-master, a recomendação atual é usar sistemas de arquivos compartilhados ou ferramentas de provisionamento que mantenham os manifestos idênticos entre todas as instâncias do API server.

Na prática: blindando webhooks com uma política que não se deleta

Quer um caso real? Suponha que você precisa garantir que nenhum MutatingWebhookConfiguration seja removido acidentalmente — ou maliciosamente. Com um manifesto estático, você cria uma regra que bloqueia qualquer DELETE nesse tipo de recurso:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: protect-webhooks.static.k8s.io
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: ["admissionregistration.k8s.io"]
      apiVersions: ["v1"]
      operations: ["DELETE"]
      resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
  validations:
  - expression: "false"
    message: "Deletion of admission webhook configurations is not allowed via API. Use disk manifest changes."

Com essa política no disco, ninguém — absolutamente ninguém via API — pode remover webhooks de admissão. A única forma de alterar a regra é acessando o sistema de arquivos do API server. A segurança baseline finalmente ganha a rigidez que os ambientes críticos sempre exigiram.

Visão de quem vê além: o Kubernetes como sistema operacional da nuvem

O Kubernetes está se consolidando como o sistema operacional da nuvem. Em qualquer SO, mecanismos fundamentais de segurança não podem ser opcionais ou removíveis — eles precisam estar no kernel. O controle de admissão baseado em manifestos é um passo firme nessa direção.

O que esperar nos próximos ciclos?

  • Integração nativa com GitOps: operadores que sincronizam repositórios Git diretamente para o disco do API server, mantendo rastreabilidade e trilhas de auditoria impecáveis.
  • Sincronização cross-instância: sistemas de arquivos compartilhados ou controladores de consenso simplificando a vida de quem opera múltiplos masters.
  • Expansão de funcionalidades: suporte a paramKind e referências a Services em versões estáveis, aumentando a flexibilidade sem perder a imutabilidade.

Resumo prático: a era das políticas de segurança que podem ser removidas por qualquer descuido está chegando ao fim. O Kubernetes v1.36 não é apenas mais um release — é um marco de maturidade. A segurança baseline finalmente ganha a rigidez que os ambientes críticos sempre exigiram.

Quer experimentar essa novidade? Suba um cluster com kind ou minikube ativando a feature gate --feature-gates="ValidatingAdmissionPolicyStaticManifests=true" no API server. Mas lembre-se: é alpha. Teste com curiosidade, responsabilidade e — acima de tudo — em ambiente isolado.