Kubernetes — runtime seguro
O cluster Kubernetes é um sistema operacional distribuído: RBAC, admission controllers e policies regem o que cada pod pode fazer, montar e expor.
O que é
Kubernetes não é só um orquestrador de containers, é um sistema operacional distribuído com própria: API, etcd, rede de pods, secrets e volumes. Cada camada traz controles: RBAC diz quem pode pedir o quê à API, admission controllers dizem o que pode entrar no cluster, NetworkPolicies dizem o que cada pod pode falar com os outros, e o kubelet diz o que cada container pode fazer no nó.
Tratar Kubernetes como 'só um deploy runner' é o erro que vaza tokens em logs, abre portas para a internet e roda containers como root com sistemas de arquivos graváveis. Defender o cluster exige os quatro controles combinados, não um só.
RBAC: a primeira cerca
RBAC (Role-Based Access Control) liga um sujeito (ServiceAccount, User, Group) a um papel, e o papel a um conjunto de verbos sobre recursos. Funciona em dois níveis: Role + RoleBinding (escopo de namespace) e ClusterRole + ClusterRoleBinding (escopo de cluster inteiro).
O erro clássico é abrir cluster-admin para a esteira de CI ou para um service account de aplicação. Funciona, o deploy passa, e qualquer RCE num pod vira controle total do cluster, incluindo leitura de todos os secrets em todos os namespaces.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ci-deployer-all
subjects:
- kind: ServiceAccount
name: ci-runner
namespace: ci
roleRef:
kind: ClusterRole
name: cluster-admin # poder total, em todo o cluster
apiGroup: rbac.authorization.k8s.ioapiVersion: v1
kind: Namespace
metadata:
name: payments
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: payments
rules:
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-deployer
namespace: payments
subjects:
- kind: ServiceAccount
name: ci-runner
namespace: ci
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.ioNetworkPolicies: o firewall dos pods
Por padrão, todo pod fala com todo pod em todo namespace. NetworkPolicies corrigem isso: são seletores de pod que dizem quem pode entrar e sair, na semântica de allowlist (o que não está permitido está bloqueado).
A primeira política sempre é a de deny-by-default no namespace. Sem ela, abrir uma porta nova num pod é abrir uma porta nova em todo o cluster. A segunda vem com allow explícito para o tráfego legítimo (ingress do ingress controller, saída para APIs externas, pod-to-pod na mesma app).
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: payments
spec:
podSelector: {} # vale para todos os pods do namespace
policyTypes:
- Ingress
- Egress
ingress: [] # nada entra
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53 # DNS para resolver serviços externosAdmission control: política antes do pod subir
Admission controllers ficam entre o aceite da request e a persistência no etcd. Eles podem validar (rejeitar) ou mutar (reescrever) o manifesto. O Kubernetes traz o Pod Security Admission (PSA) embutido desde 1.23, com profiles privileged, baseline e restricted. Para lógica mais fina, entram os policy engines:
- Gatekeeper: usa Rego, sintaxe de policy como código, ideal para times com cultura de engenharia de policy
- Kyverno: YAML puro, lê como um manifesto normal de Kubernetes, ideal para times que querem escrever policies sem aprender outra linguagem
- Pod Security Admission: nativo, sem dependência extra, profiles baseline e restricted cobrem 80% dos casos
- ValidatingAdmissionPolicy (KEP-3485): admission declarativo em cel, estabilizando em versões recentes
Segredos em etcd: criptografia em repouso
Por padrão, secrets no etcd são guardados em texto puro (apenas base64 no YAML). Quem tem acesso de leitura ao etcd, ou a um backup dele, lê todos os tokens, senhas e chaves. Encryption at rest resolve isso: cada chave do etcd é criptografada com uma chave embrulhada por .
O preço é gerenciar uma chave (rotação, revogação), e o que se ganha é : mesmo um dump do etcd vira dado inerte sem o KMS.
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- kms:
name: aws-kms
endpoint: unix:///var/run/kms-provider/socket
cachesize: 100
keyid: arn:aws:kms:us-east-1:111122223333:key/abcd-...
- identity: {} # fallback para leitura de dados antigosOnde entra
Kubernetes é a fronteira entre o que o pipeline produziu e o que vai rodar em produção. Toda defesa que falhou antes (imagem sem scan, manifesto sem policy) cai aqui: admission control rejeita, NetworkPolicy isola, RBAC limita o estrago. Por outro lado, é a última chance de corrigir o que passou: PSP/PSA pega manifesto frouxo, OPA pega labels errados, secrets em KMS pega dump de etcd.
Pontos fortes
- controles nativos do Kubernetes já cobrem RBAC, NetworkPolicy, PSA, encryption at rest: não precisa comprar nada
- (Kyverno, Gatekeeper) vira coisa de PR, com review e teste, não de ticket urgente
- namespaces viram unidades de isolamento barato, dando limite de sem precisar de clusters separados
Limitações
- RBAC, NetworkPolicy e admission são controles default-deny: precisam ser configurados antes de qualquer coisa rodar, e o caminho de migração para um cluster existente é manual
- o cluster inteiro é tão seguro quanto o nó: um kubelet exposto ou um container com privilégios quebra as garantias dos layers acima
- operar policies em escala (X clusters, Y namespaces) vira trabalho de plataforma, não de app, e sem alguém responsável vira bagunça
conexões no mapa
- CSPM — postura cloudaudita a posturaKubernetes — runtime seguro
- CWPP — proteção de workloaddetecta comportamentoKubernetes — runtime seguro
atualizado em 14/10/2026 · fontes para aprofundar · reportar erro
Estude antes
teste o que entendeu
Carregando perguntas…