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

Exercícios

  1. 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
  2. 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
  3. 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
  4. 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: baseline

    O 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.

  5. 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.