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 organisation, 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.
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¶
Namespaces sit logically above workloads. The API server enforces quotas at admission time; the scheduler respects requests and limits on each node.
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¶
Create a workspace for this tutorial.
mkdir -p ~/rebash-kubernetes/namespaces-and-resource-management && cd ~/rebash-kubernetes/namespaces-and-resource-management
Focus: Isolate workloads and set namespace-level resource budgets
Step 1 – Create namespace with ResourceQuota and LimitRange¶
kubectl create namespace rebash-lab
cat > budget.yaml <<'EOF'
apiVersion: v1
kind: ResourceQuota
metadata:
name: lab-quota
namespace: rebash-lab
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
pods: "10"
---
apiVersion: v1
kind: LimitRange
metadata:
name: lab-limits
namespace: rebash-lab
spec:
limits:
- type: Container
default:
cpu: 100m
memory: 128Mi
defaultRequest:
cpu: 50m
memory: 64Mi
EOF
kubectl apply -f budget.yaml
kubectl -n rebash-lab describe resourcequota lab-quota
Step 2 – Schedule a Pod and observe quota usage¶
kubectl -n rebash-lab run quota-pod --image=nginx:1.27-alpine
kubectl -n rebash-lab get pod quota-pod -o jsonpath='{.spec.containers[0].resources}{"
"}'
kubectl -n rebash-lab describe resourcequota lab-quota
Final step – Cleanup note¶
kubectl delete namespace rebash-lab --ignore-not-found
# Workspace kept for notes; remove with: rm -rf "$(pwd)" when finished
Validation¶
Confirm the lab before moving on:
- Re-run the critical commands from the Hands-on Lab and compare them to the expected output in each step.
- Check that you can explain why each successful result matters (not only that it printed).
- Note any warnings or unexpected output — resolve them using Troubleshooting before continuing.
| Check | Pass criteria |
|---|---|
| Namespace | Lab namespace exists and is used for subsequent commands |
| Quota/limit | ResourceQuota and/or LimitRange applied and enforced as documented |
| Isolation | Resources in one namespace do not appear in another without -A |
| Cleanup | Lab namespace deleted |
Code Walkthrough¶
| 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
Security Considerations¶
- Use namespaces as security and quota boundaries, not only organisational labels
- Apply ResourceQuotas and LimitRanges so tenants cannot exhaust the cluster
- Prefer RoleBindings scoped to a namespace over ClusterRoleBindings for app teams
- NetworkPolicy default-deny within sensitive namespaces
- Label namespaces for Pod Security admission (enforce/restricted) early
- Delete unused namespaces — leftover RBAC and Secrets accumulate risk
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 — behaviour 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¶
- How do ResourceQuota and LimitRange differ?
- What happens when a new Pod would exceed a ResourceQuota?
- Why set default requests via LimitRange?
- How can quotas be abused or misconfigured to cause denial of service for a team?
- When would you use multiple namespaces per team versus one shared namespace?
Sample answer — question 2
Admission rejects Pods that would break the quota. Teams see create failures until they free capacity or request a quota increase.
Sample answer — question 4
Quotas that are too tight block legitimate work; quotas that are too loose allow noisy neighbours. Review usage, set fair shares, and separate critical platforms into their own namespaces.
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
- Cheat sheet: Kubernetes Cheat Sheet
- Interview prep: Kubernetes Interview Prep
- Learning path: DevOps Engineer