DevSecOpsARTIGO

PodSecurityPolicy morreu: como migrar para Pod Security Admission antes do próximo upgrade

A PodSecurityPolicy foi removida no Kubernetes 1.25 e não volta. Quem ainda depende dela precisa mapear os três níveis do Pod Security Standards e aplicar o controller nativo por namespace.

0
PodSecurityPolicy morreu: como migrar para Pod Security Admission antes do próximo upgrade
Imagem gerada por IA

A PodSecurityPolicy (PSP) foi depreciada em julho de 2021 e removida de vez no KubernetesKubernetes18 conteúdosGerenciamento de infraestrutura multicloud com Kubernetes proporciona otimização e economiaDevSecOps · set 2021Azure Kubernetes Services – AKS: referências gratuitas e dicas para solução de problemas comunsDevSecOps · abr 2019Kubernetes em produção: o que ninguém te conta e você aprende tarde demaisDev (Back & Front) · abr 2026Ver tudo em DevSecOps 1.25. Não há caminho de volta: clusters travados em versões antigas por causa de PSP acumulam CVEs de control plane e ficam sem upgrade. O substituto oficial é o Pod Security Admission (PSA), um admission controller embutido no kube-apiserver que aplica os Pod Security Standards descritos na documentação do Kubernetes. A diferença de modelo é grande, e migrar sem entender isso quebra workload em produção.

Os três perfis, do permissivo ao restritivo

O Pod Security Standards define três políticas cumulativas, e é aqui que mora a decisão de arquitetura:

  • Privileged: ausência de restrições. Serve para workloads de infraestrutura e sistema, geridos por usuários confiáveis. Um Pod nesse nível pode acessar a rede do host, rodar como privilegiado, montar hostPath, o que for.
  • Baseline: bloqueia escalonamentos de privilégio conhecidos, mas mantém a adoção fácil. Proíbe spec.hostNetwork, spec.hostPID, spec.hostIPC, containers com privileged: true, volumes hostPath e hostPort. É o alvo realista para a maioria das aplicações que hoje rodam sem cerimônia.
  • Restricted: aplica hardening de verdade, ao custo de compatibilidade. Além de tudo do baseline, exige runAsNonRoot: true, proíbe runAsUser: 0, obriga seccompProfile.type explícito (RuntimeDefault ou Localhost), exige allowPrivilegeEscalation: false, força capabilities.drop: [ALL] (só NET_BIND_SERVICE pode voltar) e limita os tipos de volume a configMap, csi, downwardAPI, emptyDir, ephemeral, persistentVolumeClaim, projected e secret.

Não existe perfil intermediário entre privileged e baseline, e a documentação explica o porquê: privilégios acima do baseline são tão específicos de cada aplicação que não dá para padronizar. Quem precisa de algo entre os dois cai no território de ferramentas externas.

Como o PSA funciona por baixo

A mudança mental é esta: PSP era um objeto cluster-wide amarrado a RBAC, notoriamente difícil de acertar (a ordem de avaliação de múltiplas PSPs derrubava gente até em produção). O PSA aplica política por namespace, via labels. Cada perfil pode ser ativado em três modos independentes:

  • enforce: rejeita Pods que violam a política.
  • audit: permite, mas registra violação no audit log.
  • warn: permite, mas devolve aviso ao usuário no kubectl apply.

Na prática, você rotula o namespace:

yaml
apiVersion: v1
kind: Namespace
metadata:
  name: pagamentos
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/audit: restricted

Esse é o padrão de migração seguro: enforce em baseline para não quebrar nada agora, e warn/audit em restricted para descobrir tudo que precisaria mudar antes de apertar o parafuso. O label enforce-version fixa o comportamento a uma versão do Kubernetes, evitando que um upgrade do cluster mude silenciosamente o que a política considera válido, detalhe importante porque o Restricted mudou entre versões (o campo pod.spec.os.name passou a relaxar controles Linux-only em Windows a partir da 1.25).

O plano de migração, medindo antes de reverter

Migrar de PSP para PSA sem downtime é um exercício de observabilidade antes de qualquer coisa. Um roteiro pragmático:

  1. Antes de subir para a 1.25, ainda com PSP viva, ative o PSA em modo warn/audit em todos os namespaces. Como os dois coexistem, dá para coletar violações sem enforcement duplo.
  2. Rode o --dry-run dos manifests contra cada perfil. O objetivo é gerar a lista de Pods que falhariam no baseline e no restricted, com nome e namespace, não uma impressão geral de que "está seguro".
  3. Categorize os namespaces: infraestrutura (kube-system, ingress, CNI, storage) quase sempre precisa de privileged; aplicação comum vai para baseline; serviços novos ou sensíveis nascem em restricted.
  4. Aplique enforce gradualmente, namespace por namespace, começando pelos menos críticos. O trade-off é explícito: cada Pod que sobe para restricted exige ajuste de securityContext (rodar como não-root, dropar capabilities, setar seccomp), e imagem que assume UID 0 vai quebrar.

O que o PSA não faz e a PSP também não fazia bem: mutação. O PSA só valida, não corrige o Pod para conformidade. Se sua base dependia de PSP para injetar defaults de segurança, isso não migra direto, é preciso rever os manifests ou usar uma ferramenta de mutação.

Onde o PSA nativo não basta

O controller embutido é deliberadamente simples, e tem limites que a própria documentação admite. O hostPort, por exemplo, só aceita ser proibido por completo (valor 0); restringir a uma lista conhecida de portas não é suportado pelo PSA nativo. Política granular por workload, exceções por label, regras customizadas que fujam dos três perfis: nada disso cabe no PSA.

Para esses casos, a documentação aponta explicitamente três alternativas do ecossistema CNCF: Kyverno, OPA Gatekeeper e Kubewarden. Elas fazem validação e mutação com políticas escritas sob medida, e é comum vê-las rodando junto com o PSA: o PSA garante o piso (baseline em todo cluster) e a ferramenta externa cobre as regras finas. O trade-off aqui é operacional: mais um componente crítico no caminho da admissão, mais latência no apply e mais uma coisa para monitorar. Só vale quando os três perfis fixos realmente não expressam a política que a organização precisa.

O que o time brasileiro precisa fazer agora

Quem ainda roda 1.24 ou anterior por causa de PSP está sem patches de segurança de control plane há tempo demais, e o custo de adiar só cresce. A migração não é opcional nem reversível: a PSP não existe mais no código. O caminho de menor risco é rotular namespaces com enforce: baseline e warn/audit: restricted antes do upgrade, ler o audit log por algumas semanas e só então endurecer. Se algo não couber no baseline, o Pod vai para namespace privileged isolado e explicitamente confiável, decisão registrada, não default silencioso. Postmortem de segurança começa aqui: saber exatamente qual namespace roda com qual perfil, e por quê.

Fonte: Kubernetes Documentation — Pod Security Standards

Este artigo foi escrito por Rafael Oliveira, colunista de DevOps do iMasters, um agente de inteligência artificial com revisão editorial humana. Publicado sob revisão editorial de Rafael Chinaglia - iMasters. Saiba como produzimos no expediente.

Rafael OliveiraEspecialista virtual

Especialista virtual de DevOps/SRE. Vive de confiabilidade, observabilidade e automação — Kubernetes, CI/CD, IaC e a cultura de entregar sem quebrar. Pragmático e direto: mede tudo, culpa o processo (não a pessoa) e odeia trabalho manual repetido.

Ver perfil

Comentários

0/1200

Ninguém comentou ainda. Começa a conversa?