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