Segurança em Kubernetes
Esta aula aborda os fundamentos de segurança em Kubernetes, incluindo RBAC para controle de acesso, Network Policies para isolamento de rede, Secrets para gerenciamento de informações sensíveis e Pod Security para proteção de pods. O conteúdo é prático, com exemplos de configuração YAML e boas práticas.
A segurança em Kubernetes é um tópico crítico para garantir que ambientes conteinerizados estejam protegidos contra acessos não autorizados, vazamento de dados e execução de cargas maliciosas. Nesta aula, exploraremos quatro pilares essenciais: RBAC (controle de acesso baseado em papéis), Network Policies (políticas de rede), Secrets (segredos) e Pod Security (segurança de pods). Cada um desses componentes desempenha um papel fundamental na defesa em profundidade de um cluster Kubernetes.
Vamos aprender como configurar cada um deles, entender seus conceitos e aplicar boas práticas. Todo o conteúdo é baseado na documentação oficial do Kubernetes e em cenários reais de uso.
RBAC
RBAC (Role-Based Access Control) é o mecanismo padrão do Kubernetes para controlar quem pode acessar quais recursos e quais ações podem realizar. Ele permite definir papéis (Roles) que contêm um conjunto de permissões, e vincular esses papéis a usuários ou grupos através de RoleBindings ou ClusterRoleBindings.
Existem dois tipos de papéis: Role, que é namespace-específico, e ClusterRole, que é global. As permissões são definidas usando verbos como get, list, watch, create, update, delete, entre outros, aplicados a recursos como pods, services, deployments, etc.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioNo exemplo acima, um usuário chamado jane recebe permissão para ler pods no namespace default. Para permissões cluster-wide, use ClusterRole e ClusterRoleBinding. Boa prática: sempre seguir o princípio do menor privilégio, concedendo apenas as permissões necessárias.
Network Policies
Network Policies são regras que controlam o tráfego de rede entre pods e entre pods e serviços externos. Por padrão, todos os pods podem se comunicar entre si sem restrições. Ao aplicar uma Network Policy, você isola os pods que correspondem aos seletores especificados, e apenas o tráfego permitido pelas regras é autorizado.
As políticas podem filtrar tráfego de entrada (ingress) e saída (egress) com base em labels de pods, namespaces, endereços IP ou portas. É importante lembrar que o plugin de rede (como Calico, Cilium ou Weave) deve suportar Network Policies para que funcionem.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: default
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- port: 80
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- port: 443Neste exemplo, pods com label app=frontend aceitam tráfego apenas de pods com label app=backend na porta 80, e podem enviar tráfego apenas para o range 10.0.0.0/24 na porta 443. Boa prática: por padrão, negue todo o tráfego e depois libere apenas o necessário, seguindo o modelo de defesa em profundidade.
Secrets
Secrets são objetos do Kubernetes usados para armazenar informações sensíveis como senhas, tokens e chaves SSH. Eles são codificados em base64, mas não são criptografados por padrão no etcd. Para maior segurança, é recomendável habilitar a criptografia em repouso e usar ferramentas externas como HashiCorp Vault ou AWS Secrets Manager integradas ao cluster.
Os Secrets podem ser montados como volumes ou expostos como variáveis de ambiente nos pods. É importante evitar armazenar Secrets em arquivos de manifesto versionados em Git; em vez disso, use ferramentas como Sealed Secrets ou External Secrets Operator.
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: nginx
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: passwordNo exemplo, um Secret contém username e password em base64. O pod injeta esses valores como variáveis de ambiente. Para criar o Secret, use kubectl create secret generic db-secret --from-literal=username=admin --from-literal=password=1f2d1e2e67df. Boa prática: evite Secrets grandes e considere usar Service Accounts com tokens automáticos.
Pod Security
Pod Security é um conjunto de políticas que controlam aspectos de segurança dos pods, como execução como root, uso de capabilities, filesystems read-only, e volumes hostPath. O Kubernetes oferece o Pod Security Admission (PSA) que substituiu o antigo PodSecurityPolicy (PSP) a partir da versão 1.25.
PSA define três níveis de segurança: privileged, baseline e restricted. O nível privileged permite tudo (sem restrições), baseline aplica restrições mínimas (como proibir containers privileged), e restricted é o mais restritivo (exige read-only root filesystem, não root, etc.). Você pode aplicar esses níveis a namespaces usando labels.
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: baseline
pod-security.kubernetes.io/warn: baselineCom essa configuração, pods no namespace my-namespace que violarem o nível restricted serão rejeitados (enforce), enquanto violações de baseline geram logs de auditoria e avisos (audit e warn). Para verificar se um pod atende a um nível, use kubectl label --dry-run=server pod my-pod pod-security.kubernetes.io/enforce=restricted. Boa prática: use o nível restricted sempre que possível, e apenas exceções justificadas devem usar baseline ou privileged.
Boas Práticas e Observações Finais
Além dos quatro pilares, considere: manter o Kubernetes atualizado, usar namespaces para isolar ambientes, monitorar logs de auditoria, implementar políticas de segurança com ferramentas como OPA/Gatekeeper ou Kyverno, e realizar scans de vulnerabilidades nas imagens dos containers. A segurança é um processo contínuo e deve ser integrada ao ciclo de vida das aplicações.
Referências
- Documentação oficial RBAC
- Documentação oficial Network Policies
- Documentação oficial Secrets
- Documentação oficial Pod Security Admission
- Guia de segurança de cluster Kubernetes
- Blog sobre deprecação do PSP e introdução ao PSA
Exercícios
Crie um ClusterRole chamado pod-admin que permita todas as operações (get, list, watch, create, update, delete) em pods, e um ClusterRoleBinding que associe esse papel a um usuário chamado dev-user.
✓ Resposta:apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pod-admin rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch", "create", "update", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: dev-user-pod-admin subjects: - kind: User name: dev-user apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: pod-admin apiGroup: rbac.authorization.k8s.ioCrie uma Network Policy que permita tráfego de entrada apenas na porta 8080 vindo de pods com label app=web, e bloqueie todo o tráfego de saída.
✓ Resposta:apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-web-only spec: podSelector: {} policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: web ports: - port: 8080 egress: []Crie um Secret chamado api-key com a chave key=abc123 e monte-o como volume em um pod nginx no caminho /etc/secret.
✓ Resposta:# Primeiro, crie o Secret (use kubectl ou manifesto) kubectl create secret generic api-key --from-literal=key=abc123 # Ou via manifesto: apiVersion: v1 kind: Secret metadata: name: api-key type: Opaque data: key: YWJjMTIz --- apiVersion: v1 kind: Pod metadata: name: nginx-secret spec: containers: - name: nginx image: nginx volumeMounts: - name: secret-volume mountPath: /etc/secret volumes: - name: secret-volume secret: secretName: api-keyConfigure um namespace chamado secure-ns para rejeitar pods que não atendam ao nível restricted do Pod Security Admission.
✓ Resposta:apiVersion: v1 kind: Namespace metadata: name: secure-ns labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: latestExplique a diferença entre Role e ClusterRole e dê um exemplo de quando usar cada um.
✓ Resposta:Role é namespace-específico, ou seja, concede permissões apenas dentro de um namespace específico. ClusterRole é global, concedendo permissões em todo o cluster (incluindo recursos não-namespaced como nodes). Use Role para conceder acesso a recursos dentro de um namespace (ex: ler pods no namespace default). Use ClusterRole para conceder acesso a recursos cluster-wide (ex: gerenciar nodes) ou para reutilizar em múltiplos namespaces via RoleBinding (ex: leitura de pods em qualquer namespace).