Multi-tenancy no Kubernetes: namespace, RBAC, NetworkPolicy e quota

Namespace não é fronteira de segurança. As camadas que realmente isolam times no mesmo cluster, o que namespace não protege e quando separar clusters.

Equipe Solvefy 7 min de leitura

"Cada time no seu namespace" é a resposta padrão quando se pergunta como separar equipes no mesmo cluster. É um bom começo e é uma resposta perigosa se parar aí, porque contém uma suposição falsa: namespace não é uma fronteira de segurança.

Namespace é um agrupamento de nomes. Ele separa objetos e permite aplicar políticas — mas, sozinho, não impede que um pod de um namespace converse com outro, consuma todos os recursos do cluster ou alcance o nó por baixo.

O isolamento real vem de camadas que precisam ser configuradas explicitamente. Este texto cobre quais são, e onde está o limite do que dá para fazer em um cluster só.

As camadas

CamadaMecanismoSem ela
Nomes e objetosNamespaceColisão e confusão
PermissãoRBACQualquer um lê e altera tudo
RedeNetworkPolicyTodo pod fala com todo pod
RecursosResourceQuota, LimitRangeUm time consome o cluster
ExecuçãoPod Security, políticas de admissãoPod privilegiado alcança o nó
NósTaints, tolerations, afinidadeCargas dividem hardware sem controle

Falhar em qualquer uma compromete o conjunto. E a mais subestimada é a de rede, porque o padrão do Kubernetes é permitir tudo.

Rede: o padrão é o pior possível

Em cluster sem NetworkPolicy, qualquer pod alcança qualquer outro pod, em qualquer namespace. O banco de dados do time A é acessível a partir de um pod do time B. Um pod comprometido varre o cluster inteiro sem obstáculo.

O desenho correto começa por negar:

  1. Política padrão de negação de entrada em todo namespace. Nada entra a menos que uma política permita.
  2. Liberações explícitas: o namespace da aplicação pode alcançar o do banco, na porta específica.
  3. Negação de saída para destinos sensíveis, no mínimo. Bloquear a saída completa é mais trabalhoso — exige liberar DNS, registry e serviços externos — e é o que de fato contém um pod comprometido.
  4. Bloqueio de acesso aos endereços do plano de controle e aos serviços de metadados do provedor de nuvem. Este último é um caminho clássico de escalonamento de privilégio.

Uma advertência importante: NetworkPolicy exige suporte do plugin de rede. Alguns plugins aceitam os objetos e não os aplicam — você cria a política, ela aparece na listagem, e o tráfego continua passando. Verifique, com teste real, que a política surte efeito. É um dos achados mais comuns em auditoria de cluster.

Permissão: o cluster é mais que namespaces

RBAC no Kubernetes tem dois escopos, e a confusão entre eles é a fonte dos erros:

  • Papel de namespace, que vale dentro dele.
  • Papel de cluster, que vale em todo lugar.

E há uma armadilha específica: vincular um papel de cluster a um sujeito, com escopo de cluster, dá acesso a todos os namespaces. É fácil fazer isso por engano ao copiar um exemplo.

O desenho para múltiplos times:

  • Um grupo por time, vindo do provedor de identidade, nunca usuários individuais.
  • Papel por função dentro do namespace: desenvolvedor, operador, leitor.
  • Permissão mínima. Desenvolvedor não precisa criar objetos que alteram o comportamento do cluster.
  • Nada de acesso a recursos de escopo de cluster para times de aplicação: nós, volumes persistentes, definições de recursos personalizados, classes de prioridade.
  • Contas de serviço por aplicação, com permissão própria e mínima — e não a conta padrão do namespace.

Dois cuidados que valem regra explícita: ninguém de time de aplicação cria definição de recurso personalizado ou webhook de admissão, porque ambos afetam o cluster inteiro; e acesso à leitura de segredos precisa ser deliberado, já que quem lê segredo de um namespace tem as credenciais daquele time.

Recursos: quota é isolamento

Sem limite, um time consome o cluster inteiro — por erro, por autoscaling mal configurado ou por um vazamento.

  • ResourceQuota por namespace, limitando CPU, memória, armazenamento e quantidade de objetos. O limite de quantidade importa: um controlador em laço criando pods sem parar é um incidente real.
  • LimitRange por namespace, com padrões para quem não declarou e tetos por container. É o que elimina o pod sem requests, que cairia na classe de despejo mais frágil.
  • Classes de prioridade controladas pela plataforma, não pelos times. Se qualquer um pode marcar a própria carga como prioritária, a prioridade deixa de significar algo.

E vale monitorar a relação entre reservado e usado por namespace, porque quota generosa com uso baixo é capacidade travada que poderia estar servindo outro time.

Execução: o que impede alcançar o nó

A camada que separa isolamento fraco de isolamento sério.

Sem política de admissão, um manifesto pode pedir pod privilegiado, montar o sistema de arquivos do host, usar a rede do host ou rodar como root — e, a partir daí, o comprometimento do pod é o comprometimento do nó, e do cluster.

O que precisa estar aplicado:

  • Padrões de segurança de pod no nível restrito para namespaces de aplicação, aplicados pelo mecanismo nativo de admissão.
  • Proibição explícita de pod privilegiado, rede do host, sistema de arquivos do host e escalonamento de privilégio.
  • Execução sem root, com capacidades do kernel removidas e raiz somente leitura.
  • Um motor de políticas para as regras que o mecanismo nativo não cobre: registries permitidos, rótulos obrigatórios, limites de tolerância, proibição de tags móveis.

Este último é o que permite governança real em cluster compartilhado, e é o investimento que mais reduz o risco de manifesto mal escrito virar incidente.

O limite honesto: quando um cluster não basta

Vale ser direto, porque é onde muita arquitetura se ilude.

Multi-tenancy em um cluster funciona bem para times da mesma organização, que confiam uns nos outros e compartilham a mesma política de segurança. Chamamos isso de tenancy branda, e é o caso da grande maioria das empresas.

Não funciona bem para inquilinos que não confiam uns nos outros — clientes externos, código de terceiro, cargas de origem desconhecida. Os motivos são estruturais:

  • O kernel é compartilhado. Uma vulnerabilidade de escapada de container atinge todos os pods do nó.
  • O plano de controle é compartilhado. Um time consumindo a API agressivamente afeta todos.
  • Definições de recursos personalizados e webhooks são globais e alteram o comportamento de todos.
  • Alguns componentes de infraestrutura não são isoláveis por namespace.

Para inquilinos sem confiança mútua, as respostas reais são: cluster por inquilino, nós dedicados por inquilino com taints e afinidade, ou VM por inquilino rodando o cluster dele. Em provedor de cloud, a regra que aplicamos é a mesma da virtualização: carga de cliente roda em VM, não em container compartilhando kernel com a de outro cliente.

O caminho de adoção

  1. Namespace por time, com convenção de nomes.
  2. Grupos do provedor de identidade mapeados a papéis por namespace.
  3. LimitRange e ResourceQuota em todos os namespaces.
  4. Padrões de segurança de pod no nível restrito.
  5. NetworkPolicy de negação padrão, com liberações explícitas — testadas de verdade.
  6. Motor de políticas para as regras adicionais.
  7. Nós dedicados, se houver requisito de separação de hardware.
  8. Revisão periódica de permissões e de quotas.

A ordem importa: quota e política de segurança antes da rede, porque são menos propensas a quebrar aplicação em produção e já eliminam boa parte do risco.

Erros comuns

  • Tratar namespace como fronteira de segurança.
  • Nenhuma NetworkPolicy, com todo pod alcançando todo pod.
  • Criar NetworkPolicy sem verificar se o plugin de rede a aplica.
  • Vincular papel de cluster com escopo de cluster por engano.
  • Time de aplicação com acesso a recursos de escopo de cluster.
  • Permitir criação de definições personalizadas e webhooks por times de aplicação.
  • Usar a conta de serviço padrão do namespace nas aplicações.
  • Namespace sem ResourceQuota nem LimitRange.
  • Sem limite de quantidade de objetos, e controlador em laço criando pods.
  • Times definindo a própria classe de prioridade.
  • Nenhuma política de admissão, permitindo pod privilegiado.
  • Não bloquear o serviço de metadados do provedor de nuvem.
  • Colocar clientes externos no mesmo cluster, compartilhando kernel.
  • Nunca revisar permissões concedidas.

Onde a Solvefy/Cloud entra

Implantamos multi-tenancy em camadas, na ordem que reduz risco sem quebrar produção: quotas e limites, padrões de segurança de pod, RBAC por grupo do seu provedor de identidade, NetworkPolicy com negação padrão e verificação real de que o plugin aplica as regras, e motor de políticas para a governança adicional. Também ajudamos a tomar a decisão difícil — quando o requisito de isolamento exige cluster separado, nós dedicados ou VM por inquilino, que é o desenho que recomendamos para quem opera para clientes externos.

Um pod comprometido no seu cluster alcançaria o banco do outro time? Diagnóstico gratuito, sem compromisso, em solvefy.cloud.

Solvefy/Cloud — Infraestrutura que cresce com você.

Faça agora o seu diagnóstico e orçamento

Inicie com um diagnóstico gratuito da sua infraestrutura e receba uma proposta personalizada, com escopo, cronograma e valores.