O que Todo Dev Deve Saber sobre Pod Security Standards em Kubernetes: Restricted, Baseline e Privileged Já leu

Pod Security Standards no Kubernetes: Proteção em Camadas Pod Security Standards (PSS) é um mecanismo nativo do Kubernetes que define três níveis de restrição de segurança para Pods. Diferente de políticas antigas como Pod Security Policy (descontinuada desde a v1.25), o PSS utiliza admission controllers e labels nos namespaces para regular o que cada Pod pode fazer. Essa abordagem elimina complexidades anteriores e oferece uma solução simples mas robusta. O Kubernetes, por padrão, permite que containers rodem com privilégios elevados, acessem filesystems do host, e façam operações perigosas. O PSS resolve esse problema estabelecendo três perfis: Restricted (máxima segurança), Baseline (segurança mínima compatível com padrões), e Privileged (sem restrições). Cada um deles é aplicado no nível do namespace, não requerendo instalação de recursos externos. Os Três Níveis de Segurança Restricted: Máxima Segurança O nível Restricted implementa as melhores práticas de segurança conforme recomendações da indústria. Um Pod sob este padrão não pode rodar como root, não pode acessar o filesystem

Pod Security Standards no Kubernetes: Proteção em Camadas

Pod Security Standards (PSS) é um mecanismo nativo do Kubernetes que define três níveis de restrição de segurança para Pods. Diferente de políticas antigas como Pod Security Policy (descontinuada desde a v1.25), o PSS utiliza admission controllers e labels nos namespaces para regular o que cada Pod pode fazer. Essa abordagem elimina complexidades anteriores e oferece uma solução simples mas robusta.

O Kubernetes, por padrão, permite que containers rodem com privilégios elevados, acessem filesystems do host, e façam operações perigosas. O PSS resolve esse problema estabelecendo três perfis: Restricted (máxima segurança), Baseline (segurança mínima compatível com padrões), e Privileged (sem restrições). Cada um deles é aplicado no nível do namespace, não requerendo instalação de recursos externos.

Os Três Níveis de Segurança

Restricted: Máxima Segurança

O nível Restricted implementa as melhores práticas de segurança conforme recomendações da indústria. Um Pod sob este padrão não pode rodar como root, não pode acessar o filesystem do host, não pode escalar privilégios, e deve declarar limites de recursos. É ideal para ambientes críticos e produção.

As principais restrições do Restricted incluem:

  • Containers devem rodar com runAsNonRoot: true
  • Linux capabilities devem ser removidas (exceto NET_BIND_SERVICE)
  • Filesystem raiz deve ser somente-leitura (readOnlyRootFilesystem: true)
  • Não é permitido privileged: true ou allowPrivilegeEscalation: true
  • seccomp deve ser configurado com RuntimeDefault ou um perfil customizado
  • SELinux deve usar restricted como tipo

Aqui está um exemplo de um Deployment que está em conformidade com o Restricted:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: secure-app
  template:
    metadata:
      labels:
        app: secure-app
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: app
        image: nginx:1.21-alpine
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
          capabilities:
            drop:
            - ALL
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        volumeMounts:
        - name: cache
          mountPath: /tmp
        - name: var-cache
          mountPath: /var/cache/nginx
      volumes:
      - name: cache
        emptyDir: {}
      - name: var-cache
        emptyDir: {}

Baseline: Segurança Mínima Viável

O Baseline representa o nível mínimo de segurança sem restringir aplicações legadas comuns. Ele permite muitas operações que o Restricted proíbe, mas ainda bloqueia os riscos mais óbvios como containers com ALL capabilities ou hosts que usam privilégios inseguros do host. É apropriado para aplicações que você conhece e confia, mas que não podem cumprir os requisitos do Restricted.

As principais características do Baseline:

  • Permite runAsRoot (usuário 0), mas bloqueia alguns casos privilegiados
  • Permite a maioria das Linux capabilities, exceto SYS_ADMIN, SYS_RAWIO, etc.
  • Não requer readOnlyRootFilesystem
  • Permite allowPrivilegeEscalation: true
  • Não força seccomp ou SELinux

Um exemplo típico de aplicação Baseline:

apiVersion: v1
kind: Pod
metadata:
  name: legacy-app
  namespace: development
spec:
  containers:
  - name: web-server
    image: apache:2.4
    securityContext:
      runAsUser: 0
      allowPrivilegeEscalation: true
    ports:
    - containerPort: 80
    volumeMounts:
    - name: www
      mountPath: /var/www/html
  volumes:
  - name: www
    hostPath:
      path: /data/www
      type: Directory

Este Pod funcionará sob o Baseline, mas falhará no Restricted porque executa como root e permite escalação de privilégios.

Privileged: Sem Restrições

O nível Privileged desabilita completamente as verificações de segurança do PSS. É necessário apenas em casos muito específicos: container runtimes, CNI plugins, ou ferramentas de monitoramento do host que genuinamente precisam de acesso privilegiado. Você deve evitar este nível para aplicações normais.

Um exemplo de uso legítimo do Privileged seria um daemonset que monitora o host:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: host-monitor
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: host-monitor
  template:
    metadata:
      labels:
        app: host-monitor
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: monitor
        image: prometheus-node-exporter:latest
        securityContext:
          privileged: true
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: sys
          mountPath: /host/sys
          readOnly: true
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys

Aplicando Pod Security Standards aos Namespaces

Para ativar o Pod Security Standards em um namespace, você usa labels. Existem três tipos de labels que controlam o comportamento do enforcement:

  • pod-security.kubernetes.io/enforce: bloqueia Pods que violam o padrão (modo enforcement)
  • pod-security.kubernetes.io/audit: registra Pods que violam, mas permite (modo auditoria)
  • pod-security.kubernetes.io/warn: avisa o usuário mas permite (modo warning)

Cada um desses labels recebe um valor: baseline, restricted ou privileged.

Configurando um Namespace com Restricted

Para forçar que todos os Pods em um namespace sigam o padrão Restricted:

apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Depois de aplicar este namespace, qualquer tentativa de criar um Pod que não esteja em conformidade com Restricted resultará em um erro. Por exemplo, tentar criar um Pod que roda como root será rejeitado:

$ kubectl apply -f pod-root.yaml -n production

Error from server (Forbidden): error when creating "pod-root.yaml": pods "test-pod" is forbidden: 
violates PodSecurityPolicy: runAsNonRoot

Modo Auditoria e Warning

Se você quer migrar gradualmente para padrões mais restritos, use auditoria e warnings primeiro:

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

Nesta configuração, Pods podem violar o Restricted, mas:
- Serão registrados nos logs de auditoria
- Exibirão um aviso ao usuário
- Mas ainda serão criados com sucesso

Isso permite identificar quais aplicações precisam de ajustes antes de enforçar Restricted completamente.

Exceções com Versões de API

O PSS evolui com novas versões do Kubernetes. Use labels de versão para aceitar comportamentos antigos:

apiVersion: v1
kind: Namespace
metadata:
  name: legacy-support
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.24
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: latest

Migração Prática: Do Privileged para Restricted

Uma estratégia real de migração segue passos claros. Começamos examinando Pods existentes, aplicamos labels de auditoria, identificamos violações, corrigimos manifests, e finalmente ativamos enforcement.

Passo 1: Auditar Aplicações Existentes

Aplique auditoria sem enforcement em namespaces importantes:

kubectl label namespace my-app \
  pod-security.kubernetes.io/audit=restricted \
  --overwrite

Passo 2: Identificar Violações

Verifique os logs de auditoria para encontrar quais Pods violam o padrão:

kubectl get events -n my-app --sort-by='.lastTimestamp' | grep "PodSecurity"

Passo 3: Corrigir Manifests

Para cada aplicação que viola, atualize o manifest. Exemplo de correção de uma aplicação que roda como root:

Antes (violação):

containers:
- name: app
  image: myapp:latest

Depois (correto):

securityContext:
  runAsNonRoot: true
  runAsUser: 1001
  fsGroup: 2001
containers:
- name: app
  image: myapp:latest
  securityContext:
    allowPrivilegeEscalation: false
    readOnlyRootFilesystem: true
    capabilities:
      drop:
      - ALL

Passo 4: Ativar Enforcement

Apenas depois que todas as aplicações foram testadas e corrigidas:

kubectl label namespace my-app \
  pod-security.kubernetes.io/enforce=restricted \
  --overwrite

Conclusão

Aprendemos que Pod Security Standards oferece três níveis distintos — Restricted para máxima segurança, Baseline para compatibilidade, e Privileged para casos raros — sem complexidades de gerenciamento de políticas externas. A aplicação é simples: use labels no namespace e o admission controller nativo do Kubernetes garante conformidade. A migração é gradual e segura: implemente auditoria primeiro, identifique problemas, corrija Pods, então enforce — permitindo transições sem downtime.

Referências


Artigos relacionados