Segurança em Kubernetes
Esta aula aborda a segurança em Kubernetes, cobrindo RBAC para controle de acesso, Network Policies para segmentação de rede, Secrets para gerenciamento de dados sensíveis e Pod Security Standards para restrições de pods. Aprenda a implementar essas práticas com exemplos práticos e referências oficiais.
A segurança em Kubernetes é um tópico crítico para qualquer ambiente de produção. Com a adoção crescente de contêineres e orquestração, garantir que apenas usuários e serviços autorizados possam acessar recursos, que o tráfego de rede seja controlado e que dados sensíveis sejam protegidos é essencial. Nesta aula, exploraremos quatro pilares fundamentais da segurança no Kubernetes: RBAC (Role-Based Access Control), Network Policies, Secrets e Pod Security. Cada um desses componentes desempenha um papel vital na defesa em profundidade do cluster.
Dominar esses conceitos permite que você implemente uma postura de segurança robusta, minimizando riscos de acesso não autorizado, vazamento de dados e movimentação lateral dentro do cluster. Vamos mergulhar em cada tópico com exemplos práticos e boas práticas.
RBAC
RBAC (Role-Based Access Control) é o mecanismo padrão do Kubernetes para controlar quem pode acessar quais recursos e quais ações podem executar. Ele funciona através de objetos como Role, ClusterRole, RoleBinding e ClusterRoleBinding. Uma Role define permissões dentro de um namespace específico, enquanto ClusterRole é aplicável a todo o cluster. As permissões são concedidas através de verbos como get, list, create, update, delete, etc., aplicados a recursos como pods, services, deployments, entre outros.
Para implementar RBAC, você cria uma Role (ou ClusterRole) com as regras desejadas e, em seguida, vincula essa Role a um usuário, grupo ou conta de serviço por meio de um RoleBinding (ou ClusterRoleBinding). Por exemplo, para permitir que um usuário visualize pods no namespace 'default', você pode criar a seguinte Role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
Em seguida, um RoleBinding associa essa Role a um usuário:
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.io
É importante seguir o princípio do menor privilégio, concedendo apenas as permissões estritamente necessárias. Além disso, evite usar ClusterRoleBindings a menos que seja absolutamente necessário, pois elas concedem permissões em todo o cluster.
Network Policies
Network Policies são recursos do Kubernetes que controlam o tráfego de rede entre pods, bem como entre pods e serviços externos. Por padrão, todos os pods podem se comunicar entre si sem restrições. As Network Policies permitem definir regras de entrada (ingress) e saída (egress) baseadas em labels de pods, namespaces e endereços IP. Elas são implementadas por plugins de rede como Calico, Cilium ou Weave Net.
Para criar uma Network Policy, você especifica um seletor de pods (podSelector) e as regras de tráfego. Por exemplo, para permitir que apenas pods com o label 'role: frontend' acessem pods com o label 'role: backend' na porta 80, você pode usar:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
spec:
podSelector:
matchLabels:
role: backend
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 80
Network Policies são cumulativas: se houver múltiplas políticas selecionando o mesmo pod, todas as regras são combinadas (união). Além disso, se nenhuma política for aplicada, todo o tráfego é permitido. Para isolar completamente um grupo de pods, crie uma política que negue todo o tráfego de entrada e saída, e depois adicione exceções específicas.
Secrets
Secrets são objetos do Kubernetes projetados para armazenar informações sensíveis, como senhas, tokens e chaves SSH. Eles são armazenados no etcd e podem ser montados como volumes ou expostos como variáveis de ambiente nos pods. Embora o Kubernetes codifique os dados em base64, isso não é criptografia — qualquer pessoa com acesso à API pode decodificá-los. Por isso, é essencial habilitar a criptografia em repouso no etcd e usar políticas de RBAC rigorosas.
Para criar um Secret manualmente, você pode usar o comando kubectl:
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=secret123
Ou declarativamente em YAML:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4=
password: c2VjcmV0MTIz
Para usar o Secret em um pod, monte-o como volume ou variável de ambiente:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: myimage
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
Boas práticas incluem usar ferramentas externas como HashiCorp Vault ou Sealed Secrets para gerenciar secrets de forma mais segura, e nunca versionar secrets em repositórios de código.
Pod Security
Pod Security se refere a um conjunto de políticas que controlam as permissões e capacidades dos contêineres. No Kubernetes, isso é feito através do Admission Controller PodSecurity (substituto do PodSecurityPolicy) e dos Pod Security Standards (PSS), que definem três níveis de segurança: privileged, baseline e restricted. O nível 'restricted' é o mais seguro, impedindo execução como root, uso de volumes hostPath, capabilities desnecessárias, entre outros.
Para aplicar Pod Security Standards, você pode usar labels em namespaces para definir o nível de segurança desejado. Por exemplo, para aplicar o nível 'restricted' ao namespace 'prod', use:
apiVersion: v1
kind: Namespace
metadata:
name: prod
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Isso fará com que o Kubernetes rejeite pods que não estejam em conformidade com o nível 'restricted' (enforce), registre violações (audit) e exiba avisos (warn). Você também pode configurar essas políticas globalmente usando um AdmissionConfiguration.
Além disso, é fundamental executar contêineres como usuário não root (runAsNonRoot: true) e remover capabilities desnecessárias (drop: ["ALL"]). Exemplo de um pod com segurança restrita:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: mycontainer
image: myimage
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
Referências
- Documentação oficial do Kubernetes sobre RBAC
- Documentação oficial sobre Network Policies
- Documentação oficial sobre Secrets
- Pod Security Standards
- Configurando Security Context para Pods e Contêineres
- Visão geral de segurança em Kubernetes
- Blog do Kubernetes sobre Pod Security Admission (beta)
Exercícios
-
Crie uma Role chamada 'pod-manager' no namespace 'dev' que permita criar, listar e deletar pods. Em seguida, crie um RoleBinding associando essa Role à ServiceAccount 'deployer' no mesmo namespace.
✓ Resposta:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: dev name: pod-manager rules: - apiGroups: [""] resources: ["pods"] verbs: ["create", "list", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-manager-binding namespace: dev subjects: - kind: ServiceAccount name: deployer namespace: dev roleRef: kind: Role name: pod-manager apiGroup: rbac.authorization.k8s.io -
Escreva uma Network Policy que permita apenas tráfego de entrada (ingress) para pods com label 'app: web' na porta 80, vindo de pods com label 'app: frontend'. O namespace é 'production'.
✓ Resposta:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: web-ingress namespace: production spec: podSelector: matchLabels: app: web ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 80 -
Crie um Secret do tipo Opaque chamado 'api-keys' com as chaves 'api-key' e 'api-secret' (valores fictícios). Depois, monte esse Secret como variáveis de ambiente em um pod chamado 'api-consumer'.
✓ Resposta:
# Secret apiVersion: v1 kind: Secret metadata: name: api-keys type: Opaque data: api-key: YXBpLWtleS12YWx1ZQ== api-secret: YXBpLXNlY3JldC12YWx1ZQ== --- # Pod apiVersion: v1 kind: Pod metadata: name: api-consumer spec: containers: - name: consumer image: busybox command: ["/bin/sh", "-c", "echo $API_KEY && sleep 3600"] env: - name: API_KEY valueFrom: secretKeyRef: name: api-keys key: api-key - name: API_SECRET valueFrom: secretKeyRef: name: api-keys key: api-secret -
Aplique o Pod Security Standard 'baseline' no namespace 'staging' usando labels. Explique o que esse nível restringe.
✓ Resposta:
Para aplicar o nível baseline, adicione os seguintes labels ao namespace:
apiVersion: v1 kind: Namespace metadata: name: staging labels: pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/audit: baseline pod-security.kubernetes.io/warn: baselineO nível baseline restringe práticas potencialmente inseguras, mas não tão rigorosas quanto restricted. Ele proíbe, por exemplo, execução como root, uso de hostPID, hostIPC, hostNetwork, volumes hostPath, capabilities como NET_RAW, e permite algumas capacidades padrão. É um bom equilíbrio entre segurança e compatibilidade.
-
Crie um Pod que execute como usuário não root (UID 1000), com o sistema de arquivos root somente leitura e que elimine todas as capabilities.
✓ Resposta:
apiVersion: v1 kind: Pod metadata: name: secure-pod spec: securityContext: runAsUser: 1000 runAsNonRoot: true fsGroup: 2000 containers: - name: mycontainer image: busybox command: ["sleep", "3600"] securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"]
Boas Práticas Finais
Além dos tópicos abordados, considere as seguintes práticas para fortalecer a segurança do seu cluster Kubernetes: mantenha o Kubernetes e seus componentes atualizados, use imagens de contêineres de fontes confiáveis e escaneie-as em busca de vulnerabilidades, implemente políticas de rede por padrão (default deny), utilize namespaces para isolar ambientes, e monitore atividades suspeitas com ferramentas de observabilidade. A segurança é um processo contínuo; revise e atualize suas políticas regularmente.