Manage Namespaces for Isolation
Learn to manage Kubernetes namespaces for environment isolation, including creation, labeling, and resource quotas, with hands-on practice and troubleshooting.
Focus: manage namespaces for isolation
Ever deployed a team's microservice only to have it accidentally overwrite another team's ConfigMap? In a shared Kubernetes cluster without isolation, one namespace becomes a free-for-all where teams step on each other's resources. Kubernetes namespaces are the primary mechanism for creating logical isolation boundaries — allowing multiple teams, environments, or applications to coexist safely within the same physical cluster.
The problem this lesson solves
A single Kubernetes cluster is powerful, but without isolation, it quickly becomes chaotic. Imagine:
- Resource name collisions: Two teams deploy a
frontenddeployment — one overwrites the other. - Accidental access: A pod in staging can read secrets meant for production.
- Uncontrolled resource consumption: One noisy neighbor hogs all CPU, starving critical workloads.
Kubernetes namespaces solve these problems by partitioning the cluster into virtual sub-clusters. Each namespace has its own scope for names, policies, and resource quotas. This lesson teaches you to design, create, and manage namespaces for effective isolation — a skill essential for any multi-tenant or multi-environment cluster.
Core concept / mental model
Think of a Kubernetes cluster as a large apartment building. Each namespace is a separate apartment unit:
- Each unit has independent boundaries (walls) — resources in one namespace are invisible to others unless explicitly shared.
- Each unit has separate utility meters — resource quotas limit CPU, memory, and storage per namespace.
- The building's common areas (cluster-wide resources like Nodes) are shared but can be restricted by policies.
Key definitions:
- Namespace: A virtual cluster within a physical Kubernetes cluster. Used to group related resources and enforce isolation.
- ResourceQuota: A set of constraints that limits resource consumption (CPU, memory, etc.) within a namespace.
- NetworkPolicy: A rule that controls traffic flow between pods, often tied to namespaces.
- RoleBinding / ClusterRoleBinding: Assigns permissions that can be scoped to a namespace.
Namespaces are not a security boundary per se — they rely on RBAC and NetworkPolicies for real security. But they provide the logical scaffold for applying those controls.
How it works step by step
-
Decide on a naming convention: Common patterns include environment-based (
dev,staging,prod) or team-based (backend,data-platform). Consistency prevents confusion. -
Create the namespace: Use
kubectl create namespace <name>or a YAML manifest. The namespace object is simple — just a metadata block. -
Isolate by applying policies: - ResourceQuota to cap total resources. - NetworkPolicy to block/all traffic between namespaces. - RBAC to restrict who can act within the namespace.
-
Place workloads in the namespace: Most
kubectl applycommands accept a-n <namespace>flag. Deployments, Services, and Pods become part of that namespace. -
Query resources within the namespace: Always use
kubectl get pods -n <namespace>— the default namespace isdefault, which is rarely what you want in a multi-namespace setup.
Hands-on walkthrough
Let's create two namespaces — one for development, one for production — and isolate them.
Step 1: Create the namespaces
kubectl create namespace dev-team
kubectl create namespace production
Verify they exist:
kubectl get namespaces
# Output:
# NAME STATUS AGE
# default Active 10m
# dev-team Active 5s
# production Active 4s
# kube-node-lease Active 10m
# kube-public Active 10m
# kube-system Active 10m
Step 2: Deploy an Nginx pod into each namespace
kubectl run nginx-dev --image=nginx -n dev-team
kubectl run nginx-prod --image=nginx -n production
Step 3: Apply a ResourceQuota to the dev-team namespace
Create a file quota-dev.yaml:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev-team
spec:
hard:
requests.cpu: "2"
requests.memory: "4Gi"
limits.cpu: "4"
limits.memory: "8Gi"
persistentvolumeclaims: "2"
pods: "10"
Apply it:
kubectl apply -f quota-dev.yaml
Now check the quota:
kubectl describe quota dev-quota -n dev-team
# Output includes Used and Hard sections
Step 4: Try to exceed the quota
Attempt to create 11 pods:
for i in {1..11}; do
kubectl run pod-$i --image=nginx -n dev-team
done
You'll see an error on the 11th pod:
Error from server (Forbidden): pods "pod-11" is forbidden: exceeded quota: dev-quota, requested: pods=1, used: pods=10, limited: pods=10
Pro tip: ResourceQuotas enforce eagerly — they prevent creation, not just throttle. This is great for cost control.
Step 5: Isolate traffic with a NetworkPolicy
Create deny-all-dev.yaml to block all ingress to dev-team:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: dev-team
spec:
podSelector: {}
policyTypes:
- Ingress
Apply it:
kubectl apply -f deny-all-dev.yaml
Now pods in dev-team cannot receive traffic from outside the namespace. To allow specific traffic, you'd add an ingress rule.
Compare options / when to choose what
| Isolation approach | Use case | Complexity | Overhead |
|---|---|---|---|
| Namespace + ResourceQuota | Simple resource capping per team/environment | Low | Minimal |
| Namespace + NetworkPolicy | Restrict network access between teams | Medium | Per-policy compute |
| Separate clusters | Full isolation (security, upgrades) | High | Management overhead |
| Virtual clusters (vcluster) | Isolated control planes on same cluster | Medium | Additional API calls |
When to choose what:
- Single team, multiple environments: Use namespaces with ResourceQuotas. It's lightweight and easy.
- Multiple teams sharing a cluster: Add NetworkPolicies and RBAC to prevent cross-team interference.
- Regulatory or PCI compliance: Prefer separate clusters or virtual clusters for hard isolation.
Troubleshooting & edge cases
My resource quotas are not being enforced.
- Ensure the
ResourceQuotaobject exists and is in the correct namespace:
bash
kubectl get quota -n <namespace>
- Quotas only apply to resources created after the quota is applied. Old resources are grandfathered.
Cannot create a pod because of quota, but quota shows plenty of free resources.
- Check if a LimitRange is defined in the namespace. LimitRanges set default resource requests/limits. If your pod doesn't specify any, and there's a LimitRange with a non-zero request, the pod may exceed the quota indirectly.
bash
kubectl get limitrange -n <namespace>
Pods in different namespaces can still communicate.
- By default, Kubernetes allows all traffic between all pods, regardless of namespace. You must explicitly create NetworkPolicies to restrict it. A
deny-allpolicy in each namespace is the starting point.
I deleted a namespace, but some resources remain.
- Deleting a namespace deletes all resources inside it (pods, services, configmaps, etc.). However, cluster-scoped resources like PersistentVolumes and StorageClasses survive. Check:
bash
kubectl get pv
What you learned & what's next
You now understand how to manage namespaces for isolation in Kubernetes. You learned:
- Namespaces create logical boundaries for resources and naming.
- ResourceQuotas prevent resource starvation by capping consumption per namespace.
- NetworkPolicies enforce traffic isolation — but must be explicitly defined.
- Best practices for naming conventions and combining isolation mechanisms.
Next up: Network Policies: Restrict Pod-to-Pod Traffic, where you'll dive deep into crafting fine-grained network rules to secure multi-namespace clusters.
Practice recap
Create a third namespace called audit and apply a ResourceQuota that limits it to 2 CPU and 4 Gi memory total. Deploy three nginx pods — expect the third to be rejected. Then write a NetworkPolicy that denies all ingress traffic to audit. Verify by attempting to curl from another namespace's pod — curl should timeout.
Common mistakes
- Forgetting to scope RBAC roles to a namespace. A Role in the
defaultnamespace will not grant access to thedev-teamnamespace — you must create a separate RoleBinding per namespace. - Assuming namespace deletion cleans up all associated resources. PersistentVolumes are cluster-scoped and remain after namespace deletion, potentially causing orphaned resources.
- Not defining a NetworkPolicy and then wondering why pods in different namespaces can talk. By default, all pods can reach each other — isolation is opt-in.
- Setting CPU or memory requests too low in a ResourceQuota. If the quota is smaller than a pod's request, the pod will fail to create even though quota has capacity — always leave headroom.
Variations
- Use
kubectl create namespacevs a YAML manifest. Manifests are repeatable and can be version-controlled, making them better for CI/CD pipelines. - For advanced isolation, explore virtual clusters (vcluster) that spin up isolated Kubernetes control planes within a namespace, providing near-cluster-level isolation without separate clusters.
- Combine namespaces with
PodTopologySpreadConstraintsto ensure pods from different namespaces are spread across nodes for fault tolerance.
Real-world use cases
- A SaaS company runs staging and production in the same cluster using namespaces + ResourceQuotas to prevent staging experiments from starving production traffic.
- A fintech startup isolates dev teams (payment, fraud, analytics) into separate namespaces with NetworkPolicies so a compromised payment microservice cannot sniff fraud data.
- An e-commerce platform uses namespaces for each customer's dedicated environment (ephemeral namespaces) for per-tenant testing, with automated cleanup via CronJobs.
Key takeaways
- Namespaces partition a cluster into logical environments for isolation — they are not security boundaries on their own.
- Always specify a namespace with the
-nflag when creating or querying resources; the default namespace is a trap. - Apply ResourceQuotas to every namespace that hosts non-trivial workloads to prevent resource overcommit.
- NetworkPolicies must be explicitly applied to block cross-namespace traffic — the default policy is allow-all.
- Deleting a namespace removes all namespace-scoped resources but not cluster-scoped ones like PersistentVolumes.
- Combine namespaces with RBAC and ResourceQuotas for layered isolation that scales with your team structure.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.