Kubernetes Namespace Best Practices
Kubernetes Namespace Best Practices
Learn how to effectively organize and manage Kubernetes namespaces for multi-tenant environments, resource isolation, and security.
Table of Contents
- What Are Namespaces
- When to Use Namespaces
- Namespace Organization Strategies
- Resource Quotas
- Network Policies
- RBAC per Namespace
- Common Mistakes
What Are Namespaces
Namespaces provide logical separation within a single cluster. They're not hard isolation — they're organizational boundaries with optional resource and access controls.
# List all namespaces
kubectl get namespaces
# Built-in namespaces
NAME STATUS AGE
default Active 30d # default for everything without -n
kube-system Active 30d # cluster components (DNS, proxy)
kube-public Active 30d # publicly readable data
kube-node-lease Active 30d # node heartbeats
When to Use Namespaces
Good reasons:
- Separate environments (dev / staging / prod)
- Separate teams on a shared cluster
- Separate applications with different resource needs
- Apply different RBAC policies per boundary
Bad reasons:
- One namespace per microservice in a small team — over-engineering
- Namespaces as a security boundary alone — they need RBAC + NetworkPolicies + ResourceQuotas to mean anything
Namespace Organization Strategies
Strategy 1: By Environment (most common)
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production
Pros: simple, matches CI/CD pipelines, clear blast radius.
Strategy 2: By Team
kubectl create namespace team-payments
kubectl create namespace team-frontend
Pros: teams own their namespaces, quotas per team.
Strategy 3: By Environment + Team (larger orgs)
payments-dev, payments-prod
frontend-dev, frontend-prod
Resource Quotas
Prevent one team/environment from consuming the whole cluster:
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
persistentvolumeclaims: "10"
services.loadbalancers: "2"
kubectl apply -f quota.yaml
kubectl describe quota -n dev
LimitRange — Default Per-Container Limits
Without defaults, a single container can request everything:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: dev
spec:
limits:
- type: Container
default: # limit if unspecified
cpu: "500m"
memory: "512Mi"
defaultRequest: # request if unspecified
cpu: "100m"
memory: "128Mi"
max:
cpu: "2"
memory: "2Gi"
min:
cpu: "50m"
memory: "64Mi"
Network Policies
Namespaces alone do NOT isolate network traffic. Add NetworkPolicies:
# Deny all cross-namespace traffic by default
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-cross-namespace
namespace: production
spec:
podSelector: {} # applies to all pods in production
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # only pods in the same namespace
# Allow monitoring namespace to scrape metrics
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports:
- port: 9090
RBAC per Namespace
Give teams access only to their namespaces:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: payments-dev
name: developer
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["pods", "deployments", "jobs", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developers
namespace: payments-dev
subjects:
- kind: Group
name: payments-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
Common Mistakes
1. Everything in default
Deploying everything to default means no quotas, no RBAC isolation, and messy resource management. Create real namespaces from day one.
2. Assuming namespaces = security
Namespaces are organizational, not a security boundary. Combine with RBAC + NetworkPolicy + PodSecurityStandards:
# Enforce restricted pod security per namespace
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted
3. Forgetting resource defaults
Pods without requests/limits can starve a namespace. Always pair namespaces with LimitRange.
4. Namespace sprawl
Dozens of near-empty namespaces are harder to manage. Keep the scheme simple and documented.
Useful Commands
# Create with labels (useful for NetworkPolicy selectors)
kubectl create namespace monitoring
kubectl label namespace monitoring environment=observability
# Set default namespace for your context
kubectl config set-context --current --namespace=dev
# See everything in a namespace
kubectl get all -n production
# Delete a namespace (deletes EVERYTHING inside)
kubectl delete namespace old-env
Related Articles
Last Updated: October 2026
Author: CloudOpsGuide Team
Difficulty: Beginner
Estimated Reading Time: 9 minutes