Namespaces and Resource Management¶
Overview¶
A production Kubernetes cluster rarely runs a single application in isolation. Platform teams host dozens of teams — each with staging, production, and experimental workloads — on shared infrastructure. Namespaces are Kubernetes' primary mechanism for partitioning a cluster: they scope object names, enable RBAC boundaries, and anchor resource policies. Without namespaces, every Service name must be globally unique and a runaway batch job in one team can exhaust cluster memory for everyone.
This tutorial covers namespace design, ResourceQuota and LimitRange enforcement, label-based organization, and kubectl context workflows. You will learn how SRE and platform engineers prevent noisy-neighbor problems while keeping developer self-service intact.
This is Tutorial 11 in Module 4: Networking & Operations of the REBASH Academy Kubernetes series. Complete Ingress and External Access first — external routing and namespace-scoped Ingress rules go hand in hand. This tutorial follows our documentation standards.
Prerequisites¶
- Completed Ingress and External Access — understand Services, Ingress, and how traffic reaches pods
- A running Kubernetes cluster with
kubectlconfigured (minikube, kind, k3s, or managed EKS/GKE/AKS) - Ability to create Deployments and Services from YAML or imperative commands
- Basic understanding of CPU and memory units (
100m,256Mi,1Gi) - Comfort reading
kubectl getandkubectl describeoutput
Learning Objectives¶
By the end of this tutorial, you will be able to:
- Explain what a namespace is and when to create one vs using labels
- Design a namespace layout for dev, staging, and production workloads
- Apply ResourceQuota to cap aggregate resource consumption per namespace
- Use LimitRange to set default and maximum container resource requests and limits
- Switch kubectl context and namespace efficiently for multi-team operations
- Diagnose pod scheduling failures caused by quota exhaustion
- Apply labels and annotations for cost allocation and governance
Architecture Diagram¶
Namespaces sit logically above workloads. The API server enforces quotas at admission time; the scheduler respects requests and limits on each node.
flowchart TB
subgraph Cluster["Kubernetes Cluster"]
subgraph NS_DEV["Namespace: dev"]
D1[Deployment web]
S1[Service web-svc]
Q1[ResourceQuota dev-quota]
end
subgraph NS_PROD["Namespace: production"]
D2[Deployment web]
S2[Service web-svc]
Q2[ResourceQuota prod-quota]
end
subgraph NS_SYS["Namespace: kube-system"]
K["kube-proxy / CoreDNS"]
end
end
API[API Server + Admission]
SCH[Scheduler]
API --> NS_DEV
API --> NS_PROD
API --> NS_SYS
D1 --> SCH
D2 --> SCH
Q1 -.->|enforces| D1
Q2 -.->|enforces| D2 Theory¶
What Is a Namespace?¶
A namespace is a virtual cluster inside a physical cluster. Object names are unique within a namespace but can repeat across namespaces — web-svc in dev and web-svc in production are distinct resources. The API server stores objects with a fully qualified name: namespace/name.
Kubernetes ships with built-in namespaces:
| Namespace | Purpose |
|---|---|
default | Workloads without an explicit namespace land here |
kube-system | Core control plane and add-on components (CoreDNS, kube-proxy) |
kube-public | Publicly readable metadata (rarely used) |
kube-node-lease | Node heartbeat leases for health detection |
Most user workloads should not live in default or kube-system. Treat default as a sandbox; production apps belong in purpose-named namespaces.
Namespace vs Labels¶
Namespaces provide hard boundaries for RBAC, quotas, and DNS (service-name.namespace.svc.cluster.local). Labels provide soft grouping across namespaces — for example, team=payments on Deployments in both staging and production.
| Mechanism | Best for |
|---|---|
| Namespace | RBAC isolation, quotas, network policies scoped to a tenant |
| Label | Cross-cutting queries, cost tags, feature flags, GitOps selectors |
Use namespaces for tenancy boundaries; use labels for metadata and filtering.
Resource Requests, Limits, and Quality of Service¶
Every container should declare requests (guaranteed minimum) and limits (maximum allowed):
The scheduler uses requests to find a node with enough allocatable capacity. The kubelet uses limits to enforce cgroup ceilings. Pods without requests are harder to schedule predictably and receive BestEffort QoS — the first evicted under memory pressure.
| QoS Class | Condition |
|---|---|
| Guaranteed | Every container has equal requests and limits for CPU and memory |
| Burstable | At least one container has requests or limits set |
| BestEffort | No requests or limits on any container |
ResourceQuota¶
A ResourceQuota caps aggregate consumption in a namespace. Common quota scopes:
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: payments
spec:
hard:
pods: "20"
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
persistentvolumeclaims: "5"
services.loadbalancers: "2"
When a team tries to create a Pod that would exceed the quota, the API server rejects it with a clear error. Quotas require that affected resources specify requests/limits — otherwise LimitRange defaults apply.
LimitRange¶
LimitRange sets defaults and constraints per Pod or container in a namespace:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: payments
spec:
limits:
- type: Container
default:
cpu: "200m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "2"
memory: 2Gi
min:
cpu: "50m"
memory: "64Mi"
LimitRange ensures every Pod entering the namespace has sane resource declarations — critical before enabling ResourceQuota.
Multi-Tenancy Patterns¶
Common namespace strategies:
| Pattern | Layout | Trade-off |
|---|---|---|
| Env per namespace | payments-dev, payments-prod | Simple RBAC; many namespaces at scale |
| Team per namespace | payments, catalog with env labels | Fewer namespaces; quotas per team not env |
| Env + team | dev-payments, prod-payments | Clear isolation; operational overhead |
Platform teams often combine namespace-per-environment for small orgs and namespace-per-team with labels for larger ones.
DNS and Service Discovery Within Namespaces¶
Services are reachable as:
- Same namespace:
http://web-svc - Cross namespace:
http://web-svc.production.svc.cluster.local
NetworkPolicies (covered in later security tutorials) restrict cross-namespace traffic. Ingress rules reference Services in their own namespace unless using ExternalName or multi-namespace controllers.
Hands-on Lab¶
Use a local cluster or cloud sandbox. Commands assume you can create namespaces freely.
Step 1 – Inspect existing namespaces¶
Command:
kubectl get namespaces
kubectl get all -n kube-system | head -10
kubectl config view --minify | grep namespace
Explanation: Observe system namespaces and your current default namespace in kubeconfig. Most tutorials use default; production workflows set a namespace per context.
Expected output:
NAME STATUS AGE
default Active 7d
kube-node-lease Active 7d
kube-public Active 7d
kube-system Active 7d
Step 2 – Create team namespaces¶
Command:
kubectl create namespace payments-dev
kubectl create namespace payments-prod
kubectl label namespace payments-dev team=payments environment=dev
kubectl label namespace payments-prod team=payments environment=prod cost-center=CC-1042
kubectl get ns --show-labels | grep payments
Explanation: Namespaces are first-class API objects. Labels enable cost allocation queries and GitOps selectors without changing DNS names.
Expected output:
payments-dev Active 5s environment=dev,team=payments
payments-prod Active 3s cost-center=CC-1042,environment=prod,team=payments
Step 3 – Deploy a sample app in dev¶
Command:
kubectl create deployment web \
--image=nginx:1.25-alpine \
--replicas=2 \
-n payments-dev
kubectl expose deployment web \
--port=80 \
--name=web-svc \
-n payments-dev
kubectl get pods,svc -n payments-dev
Explanation: The same Deployment name web can exist in both namespaces independently. Service DNS inside payments-dev resolves web-svc to dev pods only.
Expected output:
NAME READY STATUS RESTARTS AGE
web-7d4b8c9f6-xxxxx 1/1 Running 0 20s
web-7d4b8c9f6-yyyyy 1/1 Running 0 20s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web-svc ClusterIP 10.96.45.123 <none> 80/TCP 10s
Step 4 – Apply LimitRange defaults¶
Command:
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: payments-dev
spec:
limits:
- type: Container
default:
cpu: "200m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "1"
memory: 1Gi
EOF
kubectl describe limitrange default-limits -n payments-dev
Explanation: New containers without resource fields inherit defaults. Pods exceeding max are rejected at creation.
Expected output:
Type Resource Min Max Default Request Default Limit
Container cpu 50m 1 100m 200m
Container memory 64Mi 1Gi 128Mi 256Mi
Step 5 – Apply ResourceQuota and test enforcement¶
Command:
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: payments-dev
spec:
hard:
pods: "5"
requests.cpu: "500m"
requests.memory: 512Mi
EOF
kubectl describe resourcequota dev-quota -n payments-dev
kubectl run quota-test --image=nginx:1.25-alpine \
--requests=cpu=400m,memory=400Mi \
-n payments-dev --dry-run=server -o yaml | head -20
Explanation: dry-run=server asks the API server to validate admission without persisting. Exceeding quota returns Forbidden with quota details.
Expected output:
Name: dev-quota
Namespace: payments-dev
Resource Used Hard
-------- ---- ----
pods 2 5
requests.cpu 200m 500m
Step 6 – Configure kubectl namespace context¶
Command:
kubectl config set-context --current --namespace=payments-dev
kubectl config get-contexts
kubectl get deploy
kubectl config set-context --current --namespace=default
Explanation: Setting namespace on the context avoids typing -n on every command. CI pipelines and humans use separate contexts per environment.
Expected output:
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* minikube minikube minikube payments-dev
NAME READY UP-TO-DATE AVAILABLE AGE
web 2/2 2 2 3m
Step 7 – Clean up lab resources¶
Command:
kubectl delete namespace payments-dev payments-prod --wait=false
kubectl get ns | grep payments || echo "Namespaces terminating"
Explanation: Deleting a namespace cascades to all objects inside it. Termination can take minutes if finalizers exist — normal in production teardown workflows.
Commands & Code¶
| Command | Description | Example |
|---|---|---|
kubectl get ns | List namespaces | kubectl get ns --show-labels |
kubectl create ns | Create namespace | kubectl create ns staging |
kubectl config set-context | Set default namespace | kubectl config set-context --current --namespace=staging |
kubectl describe quota | Inspect ResourceQuota usage | kubectl describe quota -n payments-dev |
kubectl describe limitrange | View LimitRange rules | kubectl describe limitrange -n payments-dev |
kubectl get all -A | List resources all namespaces | kubectl get pods -A -l app=web |
Namespace bootstrap manifest¶
Save as namespace-bootstrap.yaml for platform onboarding:
apiVersion: v1
kind: Namespace
metadata:
name: payments-prod
labels:
team: payments
environment: prod
---
apiVersion: v1
kind: LimitRange
metadata:
name: defaults
namespace: payments-prod
spec:
limits:
- type: Container
defaultRequest:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: payments-prod
spec:
hard:
pods: "50"
requests.cpu: "10"
requests.memory: 20Gi
Apply: kubectl apply -f namespace-bootstrap.yaml
Common Mistakes¶
Running production workloads in default
The default namespace has no quota guardrails and confusing RBAC. Every production Deployment should live in a named namespace with quotas and LimitRange applied.
Enabling ResourceQuota without LimitRange
Quotas count requests and limits. Pods without resource fields may be rejected or count as zero — behavior depends on quota scope. Always pair quotas with LimitRange defaults.
Identical Service names across namespaces without DNS awareness
curl http://api only resolves within the current namespace. Cross-namespace calls require the FQDN api.other-ns.svc.cluster.local or an Ingress rule.
Deleting kube-system or kube-public
System namespaces host critical cluster components. Restrict namespace deletion to platform admins via RBAC.
Best Practices¶
One namespace per environment minimum
Even small teams benefit from separating dev, staging, and prod namespaces. Pair with RBAC so developers cannot deploy to production accidentally.
Document quota rationale in annotations
Add kubectl annotate quota dev-quota description="2 dev pods per engineer, max 5" so future platform engineers understand sizing decisions.
Use --dry-run=server before bulk deploys
Validate quota and admission policies without creating objects. Integrate server-side dry-run in CI pipelines.
Monitor quota utilization
Alert when namespace quota usage exceeds 80%. Proactive quota increases prevent deployment failures during releases.
Troubleshooting¶
| Issue | Cause | Solution |
|---|---|---|
Forbidden: exceeded quota | Namespace ResourceQuota exhausted | kubectl describe quota -n <ns>; scale down or raise limits |
| Pod stuck Pending, events mention resources | Node lacks allocatable CPU/memory | Check kubectl describe node; reduce requests or add nodes |
must specify limits admission error | LimitRange requires limits; none set | Add resources block or fix LimitRange defaults |
| Wrong Service reached | DNS resolves same-namespace only | Use FQDN or verify -n flag and kubeconfig context |
| Namespace stuck Terminating | Finalizers on resources inside namespace | Identify blocking objects; remove finalizers only with care |
| Quota shows zero used but pods exist | Pods lack requests/limits | Update Deployments; ensure LimitRange injects defaults |
Summary¶
- Namespaces partition a cluster for tenancy, RBAC, DNS, and policy enforcement without separate physical clusters
- ResourceQuota caps aggregate namespace consumption; LimitRange sets per-container defaults and bounds
- Requests drive scheduling; limits enforce runtime ceilings and affect QoS eviction order
- Design namespace layouts deliberately — per team, per environment, or hybrid — and use labels for cross-cutting metadata
- Configure kubectl context namespace to reduce operator error during multi-namespace work
- Pair quotas with monitoring and documented sizing so teams understand capacity boundaries before incidents
Interview Questions¶
- What problem do Kubernetes namespaces solve, and how do they differ from labels?
- Explain the difference between resource requests and limits. Which component consumes each?
- What happens when a Pod creation would exceed a ResourceQuota?
- Why should LimitRange be applied before or alongside ResourceQuota?
- Describe the three QoS classes and which pods the kubelet evicts first under memory pressure.
- How does DNS resolution differ for a Service in the same namespace vs a different namespace?
- Name three resources commonly limited in a ResourceQuota besides CPU and memory.
- What are the risks of deploying production workloads to the
defaultnamespace? - How would you structure namespaces for three teams each with dev and prod environments?
- What is
kubectl --dry-run=serverand why is it useful for quota validation?
Sample Answers (Questions 2, 4, and 7)
Q2 — Requests vs limits: Requests declare the minimum guaranteed resources a container needs. The scheduler sums requests across pods to find a node with enough allocatable capacity. Limits cap maximum usage at runtime — the kubelet enforces them via cgroups. A container can burst above its request up to its limit (for CPU, it may be throttled rather than killed).
Q4 — LimitRange before quota: ResourceQuota tracks aggregate requests and limits. If pods omit resource fields, admission behavior is inconsistent — some quotas reject them, others count zero usage allowing unbounded pods. LimitRange injects defaults so every pod has predictable resource declarations before quota enforcement is meaningful.
Q7 — Other quota resources: Common hard limits include pods, persistentvolumeclaims, services.loadbalancers, services.nodeports, count/deployments.apps, and requests.storage for total PVC storage claims.
Related Tutorials¶
- Kubernetes – Category Overview
- Ingress and External Access (previous — Module 4)
- Health Checks, Probes, and Self-Healing (next in Module 4)
- RBAC and Kubernetes Security Basics
- Docker – Introduction to Containers — cgroups foundation