<h2>Namespaces em Kubernetes: Isolamento, ResourceQuotas e LimitRanges</h2>
<p>Namespaces são um dos conceitos fundamentais do Kubernetes, funcionando como partições lógicas dentro de um cluster. Eles permitem que múltiplos projetos, times ou ambientes (desenvolvimento, staging, produção) coexistam no mesmo cluster físico sem conflitos. Cada namespace possui seu próprio escopo de nomes para recursos como Pods, Services e Deployments, e pode ter políticas de acesso, quotas de recursos e restrições independentes.</p>
<p>O grande diferencial dos namespaces é que eles não são apenas uma questão de organização visual — eles implementam um verdadeiro isolamento lógico. Um desenvolvedor trabalhando no namespace <code>dev</code> não consegue acessar nem ver recursos do namespace <code>prod</code> sem permissões explícitas. Isso é essencial em ambientes corporativos onde segurança e separação de responsabilidades são críticas.</p>
<h3>Por que usar Namespaces?</h3>
<p>Quando você trabalha com Kubernetes em produção, é raro ter apenas um projeto ou um único time. A maioria das organizações enfrenta o desafio de múltiplas aplicações compartilhando a mesma infraestrutura. Sem namespaces, teríamos conflitos de nomenclatura (dois serviços com o mesmo nome), gerenciamento caótico de permissões, e seria impossível aplicar políticas diferenciadas por projeto.</p>
<p>Namespaces resolvem esse problema oferecendo isolamento de nomes, separação de recursos, controle de acesso granular (via RBAC) e a possibilidade de aplicar quotas e limites específicos por projeto. Além disso, facilitam a limpeza — deletar um namespace remove automaticamente todos os seus recursos.</p>
<h2>Isolamento Através de Namespaces</h2>
<h3>Criação e Gerenciamento Básico</h3>
<p>Criar um namespace em Kubernetes é direto. Você pode fazer isso via YAML ou comando kubectl:</p>
<pre><code class="language-bash">kubectl create namespace producao
kubectl create namespace desenvolvimento
kubectl create namespace staging</code></pre>
<p>O equivalente em YAML (mais recomendado para ambientes de produção) seria:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Namespace
metadata:
name: producao
labels:
ambiente: produção
criticidade: alta
---
apiVersion: v1
kind: Namespace
metadata:
name: desenvolvimento
labels:
ambiente: dev
criticidade: baixa</code></pre>
<p>Você pode listar, descrever e deletar namespaces normalmente:</p>
<pre><code class="language-bash">kubectl get namespaces
kubectl describe namespace producao
kubectl delete namespace desenvolvimento</code></pre>
<h3>Isolamento de Nomes e Acesso</h3>
<p>O isolamento começa com nomes: um Pod chamado <code>api-server</code> no namespace <code>producao</code> é completamente diferente de um Pod <code>api-server</code> no namespace <code>desenvolvimento</code>. Internamente, o Kubernetes qualifica nomes como <code>api-server.producao.svc.cluster.local</code>, garantindo unicidade.</p>
<p>Para acessar um serviço em outro namespace, você usa:</p>
<pre><code class="language-bash"># Dentro do mesmo namespace
curl http://api-server:8080
De outro namespace
curl http://api-server.producao.svc.cluster.local:8080</code></pre>
<p>Esse isolamento de nomes é apenas o primeiro nível. O acesso real é controlado por RBAC (Role-Based Access Control). Por exemplo, um usuário pode ter permissão para listar Pods apenas no namespace <code>desenvolvimento</code>, mas não em <code>producao</code>. Aqui está um exemplo prático:</p>
<pre><code class="language-yaml">apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dev-reader
namespace: desenvolvimento
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-reader-binding
namespace: desenvolvimento
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dev-reader
subjects:
- kind: User
name: desenvolvedor@empresa.com
apiGroup: rbac.authorization.k8s.io</code></pre>
<p>Com essa configuração, <code>desenvolvedor@empresa.com</code> pode fazer <code>kubectl get pods -n desenvolvimento</code>, mas <code>kubectl get pods -n producao</code> resultará em "forbidden".</p>
<h2>ResourceQuotas: Controlando Consumo de Recursos</h2>
<h3>O Problema da Falta de Limites</h3>
<p>Sem controle, um desenvolvedor desatento pode deployar uma aplicação com bug que consome toda a memória do cluster, prejudicando outros projetos. ResourceQuotas são o mecanismo que previne isso, estabelecendo limites de consumo total por namespace.</p>
<p>Uma ResourceQuota define quantos recursos (CPU, memória, número de Pods, etc.) um namespace inteiro pode usar. Diferentemente de um LimitRange (que veremos depois), a quota é um total para todo o namespace. Se você definir uma quota de 10 Gi de memória, qualquer tentativa de deployar Pods que ultrapassem esse total será rejeitada.</p>
<h3>Criando e Aplicando Quotas</h3>
<p>Aqui está um exemplo prático de ResourceQuota para um namespace de desenvolvimento:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: desenvolvimento
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
pods: "100"
services: "10"
persistentvolumeclaims: "5"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["default"]</code></pre>
<p>Essa quota significa:</p>
<ul>
<li>O namespace pode ter no máximo 100 Pods</li>
<li>A soma de todos os <code>requests.cpu</code> dos Pods não pode exceder 10 unidades</li>
<li>A soma de todos os <code>requests.memory</code> dos Pods não pode exceder 20 Gi</li>
<li>A soma de todos os <code>limits.cpu</code> não pode exceder 20 unidades</li>
<li>A soma de todos os <code>limits.memory</code> não pode exceder 40 Gi</li>
<li>No máximo 10 Services e 5 PersistentVolumeClaims</li>
</ul>
<p>Vamos criar um Deployment que respeita essa quota:</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
name: api-app
namespace: desenvolvimento
spec:
replicas: 3
selector:
matchLabels:
app: api-app
template:
metadata:
labels:
app: api-app
spec:
containers:
- name: api
image: nginx:latest
resources:
requests:
cpu: "500m" # 0.5 unidades de CPU
memory: "256Mi" # 256 MiB de memória
limits:
cpu: "1000m" # Máximo 1 unidade de CPU
memory: "512Mi" # Máximo 512 MiB</code></pre>
<p>Com 3 replicas, esse Deployment consumirá:</p>
<ul>
<li>Requests: 1.5 CPUs e 768 Mi de memória</li>
<li>Limits: 3 CPUs e 1.5 Gi de memória</li>
</ul>
<p>Ainda dentro da quota. Mas se tentarmos escalar para 15 replicas, o scheduler rejeitará os Pods por exceder a quota.</p>
<h3>Verificando Quota</h3>
<pre><code class="language-bash">kubectl describe resourcequota dev-quota -n desenvolvimento</code></pre>
<p>Você verá algo como:</p>
<pre><code>Used Hard
---- ----
limits.cpu 3 20
limits.memory 1500Mi 40Gi
pods 3 100
requests.cpu 1500m 10
requests.memory 768Mi 20Gi
services 1 10</code></pre>
<h2>LimitRanges: Impondo Restrições Individuais</h2>
<h3>Quando ResourceQuota Não é Suficiente</h3>
<p>ResourceQuota controla o total consumido por um namespace, mas não impede que um único Pod use recursos excessivos. Imagine um namespace com quota de 20 Gi de memória: um único container poderia consumir 19 Gi, deixando 1 Gi para todos os outros Pods. LimitRange resolve isso definindo limites e requests padrão, mínimos e máximos por Pod ou container.</p>
<p>LimitRange é uma política de sanidade. Ela garante que nenhum container seja extremamente ganancioso, e que desenvolvedores que se esqueçam de especificar recursos recebam defaults sensatos. É uma camada adicional de proteção que funciona em conjunto com ResourceQuota.</p>
<h3>Implementando LimitRanges</h3>
<p>Aqui está um LimitRange bem estruturado para um namespace de desenvolvimento:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: desenvolvimento
spec:
limits:
Limites para containers
- type: Container
max:
cpu: "2000m"
memory: "2Gi"
min:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "250m"
memory: "256Mi"
maxLimitRequestRatio:
cpu: "2"
memory: "2"
Limites para Pods (soma de todos os containers)
- type: Pod
max:
cpu: "4000m"
memory: "4Gi"
min:
cpu: "200m"
memory: "256Mi"
Limites para PersistentVolumeClaims
- type: PersistentVolumeClaim
max:
storage: "10Gi"
min:
storage: "1Gi"</code></pre>
<p>Isso significa:</p>
<ul>
<li><strong>Cada container</strong> pode ter no máximo 2 CPUs e 2 Gi de memória, mínimo 100m de CPU e 128 Mi de memória</li>
<li>Se um container não especificar recursos, recebe defaults: 500m CPU e 512 Mi memória</li>
<li>A razão entre limit e request não pode exceder 2 (ex: se request é 500m, limit máximo é 1000m)</li>
<li><strong>Cada Pod</strong> (soma de todos os containers) pode ter no máximo 4 CPUs e 4 Gi, mínimo 200m e 256 Mi</li>
<li><strong>Cada PersistentVolumeClaim</strong> deve estar entre 1 Gi e 10 Gi</li>
</ul>
<h3>Comportamento com LimitRange</h3>
<p>Quando você tenta criar um Pod sem especificar recursos:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
name: app-sem-recursos
namespace: desenvolvimento
spec:
containers:
- name: app
image: nginx:latest
Sem spec de resources</code></pre>
<p>O LimitRange automaticamente injeta os defaults:</p>
<pre><code class="language-yaml">resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"</code></pre>
<p>Se você tentar criar um Pod que viola o LimitRange:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Pod
metadata:
name: app-excessivo
namespace: desenvolvimento
spec:
containers:
- name: app
image: nginx:latest
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "5000m" # Viola o máximo de 2000m
memory: "2Gi"</code></pre>
<p>Você receberá um erro: <code>Pod violates LimitRange: limits.cpu: Invalid value: "5000m": must be less than or equal to 2000m</code></p>
<h2>Exemplo Completo: Configurando um Ambiente Multi-tenant</h2>
<p>Vamos combinar tudo em um cenário real: uma empresa com três ambientes (desenvolvimento, staging, produção) e políticas diferenciadas para cada um.</p>
<pre><code class="language-yaml">---
NAMESPACE DESENVOLVIMENTO
apiVersion: v1
kind: Namespace
metadata:
name: desenvolvimento
labels:
ambiente: dev
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: desenvolvimento
spec:
hard:
requests.cpu: "5"
requests.memory: "10Gi"
limits.cpu: "10"
limits.memory: "20Gi"
pods: "50"
---
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: desenvolvimento
spec:
limits:
- type: Container
max:
cpu: "1000m"
memory: "1Gi"
min:
cpu: "100m"
memory: "128Mi"
defaultRequest:
cpu: "250m"
memory: "256Mi"
---
NAMESPACE STAGING
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
ambiente: staging
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: staging-quota
namespace: staging
spec:
hard:
requests.cpu: "20"
requests.memory: "50Gi"
limits.cpu: "40"
limits.memory: "100Gi"
pods: "100"
---
apiVersion: v1
kind: LimitRange
metadata:
name: staging-limits
namespace: staging
spec:
limits:
- type: Container
max:
cpu: "4000m"
memory: "4Gi"
min:
cpu: "100m"
memory: "128Mi"
defaultRequest:
cpu: "500m"
memory: "512Mi"
---
NAMESPACE PRODUÇÃO
apiVersion: v1
kind: Namespace
metadata:
name: producao
labels:
ambiente: prod
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: prod-quota
namespace: producao
spec:
hard:
requests.cpu: "100"
requests.memory: "200Gi"
limits.cpu: "200"
limits.memory: "400Gi"
pods: "500"
---
apiVersion: v1
kind: LimitRange
metadata:
name: prod-limits
namespace: producao
spec:
limits:
- type: Container
max:
cpu: "8000m"
memory: "8Gi"
min:
cpu: "100m"
memory: "128Mi"
defaultRequest:
cpu: "1000m"
memory: "1Gi"</code></pre>
<p>Agora você pode deployar aplicações em cada namespace com confiança:</p>
<pre><code class="language-bash">kubectl apply -f namespaces.yaml
kubectl get resourcequotas -n desenvolvimento
kubectl describe limitrange dev-limits -n desenvolvimento</code></pre>
<h2>Conclusão</h2>
<p>Os três conceitos apresentados trabalham em camadas complementares: <strong>Namespaces</strong> fornecem isolamento lógico e segurança no nível de controle de acesso, <strong>ResourceQuotas</strong> garantem que um namespace não consuma mais que sua parcela justa de recursos do cluster, e <strong>LimitRanges</strong> protegem contra containers individuais problemáticos e estabelecem defaults sensatos. Juntos, eles são a base de uma estratégia sólida de multi-tenancy em Kubernetes, permitindo que múltiplos projetos coexistam pacificamente em um cluster compartilhado sem risco de um prejudicar o outro.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/" target="_blank" rel="noopener noreferrer">Kubernetes Documentation: Namespaces</a></li>
<li><a href="https://kubernetes.io/docs/concepts/policy/resource-quotas/" target="_blank" rel="noopener noreferrer">Kubernetes Documentation: Resource Quotas</a></li>
<li><a href="https://kubernetes.io/docs/concepts/policy/limit-range/" target="_blank" rel="noopener noreferrer">Kubernetes Documentation: Limit Ranges</a></li>
<li><a href="https://kubernetes.io/docs/concepts/configuration/overview/" target="_blank" rel="noopener noreferrer">Kubernetes Best Practices: Resource Management</a></li>
<li><a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" target="_blank" rel="noopener noreferrer">Managing Resources for Containers - Kubernetes Official</a></li>
</ul>
<p><!-- FIM --></p>