Multi-tenancy no Kubernetes: isolamento com namespaces e RBAC
1. Introdução ao Multi-tenancy no Kubernetes
1.1. Conceitos fundamentais
Multi-tenancy em Kubernetes refere-se à capacidade de hospedar múltiplos usuários, equipes ou aplicações (tenants) em um único cluster, garantindo isolamento entre eles. Em ambientes DevOps, isso é essencial para otimizar custos de infraestrutura, simplificar a gestão e permitir que diferentes squads compartilhem recursos sem interferência. Cada tenant opera como se tivesse seu próprio cluster, mas utilizando o mesmo plano de controle.
1.2. Desafios de isolamento
Os principais desafios incluem:
- Segurança: impedir que um tenant acesse recursos de outro
- Performance: evitar que um workload consuma recursos excessivos e impacte vizinhos
- Governança: aplicar políticas consistentes sem centralizar decisões
- Auditoria: rastrear ações de cada tenant individualmente
1.3. Ferramentas nativas do Kubernetes
O Kubernetes oferece recursos nativos para implementar multi-tenancy:
| Recurso | Função |
|---|---|
| Namespaces | Isolamento lógico de recursos |
| RBAC | Controle de acesso baseado em papéis |
| NetworkPolicies | Isolamento de rede |
| ResourceQuotas | Limites de recursos por namespace |
| LimitRanges | Defaults e limites para pods/containers |
2. Namespaces como unidade de isolamento lógico
2.1. Estrutura e criação
Namespaces são a primeira camada de isolamento. Eles agrupam recursos como Pods, Services, Deployments e ConfigMaps. Para criar um namespace:
kubectl create namespace equipe-frontend
kubectl create namespace equipe-backend
kubectl create namespace equipe-dados
2.2. Práticas de nomenclatura
Adote convenções claras para facilitar a gestão:
- {tenant}-{ambiente}: frontend-prod, backend-dev
- {projeto}-{equipe}: ecommerce-pagamento, ecommerce-catalogo
- Evite nomes genéricos como dev ou test sem contexto
2.3. Limitações dos namespaces
Namespaces não isolam:
- Nós do cluster (nodes)
- StorageClasses (a menos que configurado com RBAC)
- ClusterRoles e ClusterRoleBindings
- Recursos de cluster como Nodes, PersistentVolumes e Namespaces
Para esses recursos, é necessário combinar com RBAC e políticas mais restritivas.
3. RBAC para controle de acesso granular
3.1. Componentes do RBAC
O RBAC do Kubernetes possui quatro elementos principais:
- Role: define permissões dentro de um namespace
- ClusterRole: define permissões em todo o cluster
- RoleBinding: associa uma Role a usuários/grupos em um namespace
- ClusterRoleBinding: associa uma ClusterRole em todo o cluster
- ServiceAccount: identidade para processos dentro de pods
3.2. Configuração de permissões por tenant
Cada tenant deve ter permissões restritas ao seu namespace. Exemplo de Role para desenvolvedores:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: equipe-frontend
name: dev-role
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
3.3. Exemplo prático: roles para diferentes perfis
Role para operadores (admin do namespace):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: equipe-frontend
name: operator-role
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
Role para auditores (apenas leitura):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: equipe-frontend
name: auditor-role
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
RoleBinding associando um usuário ao papel de desenvolvedor:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: equipe-frontend
name: dev-binding
subjects:
- kind: User
name: maria.dev@empresa.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: dev-role
apiGroup: rbac.authorization.k8s.io
4. ResourceQuotas e LimitRanges para governança de recursos
4.1. Definindo limites por namespace
ResourceQuotas garantem que um tenant não consuma recursos além do acordado:
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota-frontend
namespace: equipe-frontend
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
persistentvolumeclaims: "5"
pods: "20"
services: "10"
4.2. LimitRanges para defaults e limites
LimitRanges definem limites mínimos e máximos para pods e containers individuais:
apiVersion: v1
kind: LimitRange
metadata:
name: limits-frontend
namespace: equipe-frontend
spec:
limits:
- max:
cpu: "2"
memory: "4Gi"
min:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "200m"
memory: "256Mi"
type: Container
4.3. Estratégias de planejamento
- Calcule a capacidade total do cluster e divida entre tenants
- Deixe 20-30% de folga para picos de demanda
- Use
kubectl describe quota -n <namespace>para monitorar consumo - Considere usar o Vertical Pod Autoscaler para ajuste dinâmico
5. NetworkPolicies para isolamento de rede entre tenants
5.1. Controle de tráfego entre namespaces
NetworkPolicies permitem ou bloqueiam comunicação entre pods, baseadas em labels e namespaces. Por padrão, todo tráfego é permitido.
5.2. Exemplos de políticas
Isolamento total (bloquear todo tráfego externo ao namespace):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: equipe-frontend
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Permitir apenas tráfego do namespace backend:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend
namespace: equipe-frontend
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: equipe-backend
ports:
- protocol: TCP
port: 8080
5.3. Integração com Service Mesh
Para isolamento avançado, considere usar Istio ou Linkerd. Eles oferecem:
- Autenticação mútua TLS (mTLS) entre serviços
- Políticas de tráfego baseadas em identidade
- Observabilidade detalhada por tenant
6. Boas práticas de segurança e auditoria
6.1. PodSecurityAdmission
A partir do Kubernetes 1.23, o PodSecurityAdmission substitui os PodSecurityPolicies. Defina perfis por namespace:
apiVersion: v1
kind: Namespace
metadata:
name: equipe-frontend
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: baseline
pod-security.kubernetes.io/warn: baseline
6.2. Auditoria de ações
Habilite audit logs no cluster:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
users: ["maria.dev@empresa.com"]
resources:
- group: ""
resources: ["secrets", "configmaps"]
6.3. Ferramentas complementares
- OPA/Gatekeeper: políticas declarativas customizadas (ex.: "todo deployment deve ter resource limits")
- Kyverno: políticas Kubernetes nativas, sem linguagem adicional
- Kube-bench: verificação de conformidade CIS Benchmark
7. Exemplo prático: implementando multi-tenancy em um cluster compartilhado
7.1. Cenário
Três equipes compartilham um cluster Kubernetes:
- Frontend: aplicação web React + API Node.js
- Backend: microsserviços Java + PostgreSQL
- Dados: pipelines Python + Spark + S3
7.2. Passo a passo
1. Criar namespaces:
kubectl create namespace frontend
kubectl create namespace backend
kubectl create namespace dados
2. Aplicar ResourceQuotas:
kubectl apply -f quota-frontend.yaml -n frontend
kubectl apply -f quota-backend.yaml -n backend
kubectl apply -f quota-dados.yaml -n dados
3. Configurar RBAC:
kubectl apply -f roles.yaml
kubectl apply -f rolebindings.yaml
4. Aplicar NetworkPolicies:
kubectl apply -f network-policies.yaml
5. Verificar isolamento:
# Testar acesso entre namespaces (deve falhar)
kubectl exec -n frontend deploy/web -- curl http://backend-service.backend:8080
# Verificar quotas
kubectl describe quota -n frontend
# Testar RBAC
kubectl auth can-i list pods --as=maria.dev@empresa.com -n frontend
kubectl auth can-i delete pods --as=maria.dev@empresa.com -n backend
7.3. Resultados esperados
- Desenvolvedores do frontend gerenciam apenas recursos no namespace
frontend - Operadores têm acesso administrativo apenas aos seus namespaces
- Tráfego de rede é bloqueado entre tenants, exceto onde explicitamente permitido
- Cada equipe tem garantia de recursos mínimos e máximos
8. Considerações finais e próximos passos
8.1. Monitoramento de tenants
Use Prometheus com labels de namespace para criar dashboards no Grafana:
sum(rate(container_cpu_usage_seconds_total{namespace="frontend"}[5m]))
8.2. Exposição segura de serviços
Combine External DNS com Ingress Controllers (NGINX, Traefik) e certificados Let's Encrypt para expor serviços de cada tenant com domínios próprios:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
namespace: frontend
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- app.frontend.empresa.com
secretName: frontend-tls
rules:
- host: app.frontend.empresa.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
8.3. Preparação para o próximo artigo
No próximo artigo, exploraremos um pipeline completo de CI/CD com Docker e Kubernetes, integrando GitHub Actions, Docker Hub e Helm Charts para deploy automatizado em ambientes multi-tenant.
Referências
- Kubernetes Official Documentation: Multi-tenancy — Guia oficial sobre conceitos e estratégias de multi-tenancy no Kubernetes
- Kubernetes RBAC Documentation — Documentação completa sobre Role-Based Access Control, incluindo exemplos de Roles e RoleBindings
- Kubernetes Network Policies — Referência oficial para criação e gerenciamento de políticas de rede
- Kubernetes Resource Quotas — Documentação sobre ResourceQuotas e LimitRanges para governança de recursos
- Pod Security Standards — Guia oficial sobre PodSecurityAdmission e perfis de segurança para namespaces
- Kyverno: Kubernetes Native Policy Management — Documentação do Kyverno para políticas de segurança e compliance em clusters multi-tenant
- Gatekeeper: OPA Integration for Kubernetes — Tutorial e referência do OPA Gatekeeper para políticas customizadas em ambientes multi-tenant