Namespaces

3 minute read

As your Kubernetes cluster grows with multiple teams and applications, you need a way to organize and isolate resources. Namespaces provide a mechanism for dividing cluster resources between multiple users, teams, or projects.

What is a Namespace?

A Namespace is a virtual cluster within a physical Kubernetes cluster. It provides:

  • Resource isolation — separate workloads logically
  • Name scoping — the same resource name can exist in different namespaces
  • Access control — apply RBAC policies per namespace
  • Resource quotas — limit CPU/memory per namespace

Think of namespaces like folders on a computer — they organize and separate resources without needing separate clusters.

Default Namespaces

Every Kubernetes cluster comes with four namespaces:

Namespace Purpose
default Where resources go if no namespace is specified
kube-system Kubernetes system components (API server, scheduler, etc.)
kube-public Publicly readable data (cluster info, ConfigMaps)
kube-node-lease Node heartbeat data for node health monitoring
# List all namespaces
kubectl get namespaces
# or: kubectl get ns

Output:

NAME              STATUS   AGE
default           Active   2d
kube-node-lease   Active   2d
kube-public       Active   2d
kube-system       Active   2d

Creating Namespaces

Imperative

kubectl create namespace development
kubectl create namespace staging
kubectl create namespace production

Declarative

apiVersion: v1
kind: Namespace
metadata:
  name: development
  labels:
    environment: dev
    team: platform
kubectl apply -f namespace.yaml

Working with Namespaces

Specify Namespace in Commands

# Create a Deployment in a specific namespace
kubectl create deployment nginx --image=nginx -n development

# List Pods in a namespace
kubectl get pods -n development

# List Pods across ALL namespaces
kubectl get pods --all-namespaces
# or: kubectl get pods -A

Specify Namespace in YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: development      # ← specify namespace here
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27

Set Default Namespace

Tired of typing -n development every time? Set a default:

# Set default namespace for current context
kubectl config set-context --current --namespace=development

# Verify
kubectl config view --minify | grep namespace

# Now all commands default to "development"
kubectl get pods    # Shows Pods in "development" namespace

Cross-Namespace Communication

Pods in different namespaces can communicate using the full DNS name:

<service-name>.<namespace>.svc.cluster.local
# Pod in "development" namespace accessing a service in "production"
curl http://api-service.production.svc.cluster.local

# Short form (within the same cluster)
curl http://api-service.production

Important: Namespaces don’t provide network isolation by default. Any Pod can talk to any other Pod across namespaces. To enforce network isolation, use Network Policies (covered in Chapter 17).

Resource Quotas

Limit the total resources a namespace can consume:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: development
spec:
  hard:
    pods: "20"
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    services: "10"
    persistentvolumeclaims: "5"
kubectl apply -f quota.yaml

# Check quota usage
kubectl describe resourcequota dev-quota -n development

LimitRanges

Set default resource requests/limits for Pods in a namespace:

apiVersion: v1
kind: LimitRange
metadata:
  name: dev-limits
  namespace: development
spec:
  limits:
  - type: Container
    default:           # Default limits
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:    # Default requests
      cpu: "100m"
      memory: "128Mi"
    max:               # Maximum allowed
      cpu: "2"
      memory: "1Gi"
    min:               # Minimum required
      cpu: "50m"
      memory: "64Mi"

This ensures every Pod in the development namespace has resource constraints, even if the developer forgets to set them.

Namespace-Scoped vs. Cluster-Scoped Resources

Not all Kubernetes resources live inside a namespace:

Namespace-scoped (exist within a namespace):

  • Pods, Deployments, Services, ConfigMaps, Secrets, ReplicaSets, Jobs, Ingress

Cluster-scoped (exist cluster-wide):

  • Nodes, Namespaces, PersistentVolumes, ClusterRoles, ClusterRoleBindings, StorageClasses
# See all namespace-scoped resources
kubectl api-resources --namespaced=true

# See all cluster-scoped resources
kubectl api-resources --namespaced=false

Best Practices

Namespace Strategy for Organizations

Pattern Example When to Use
By environment dev, staging, prod Simple applications
By team team-alpha, team-beta Multi-team organizations
By project project-x, project-y Multi-project clusters
Combined team-alpha-dev, team-alpha-prod Large organizations

Naming Conventions

# Good
kubectl create ns frontend-dev
kubectl create ns backend-staging
kubectl create ns data-pipeline-prod

# Avoid
kubectl create ns my-stuff         # Not descriptive
kubectl create ns PRODUCTION        # Must be lowercase
kubectl create ns a                 # Too short

Clean Up

# Delete a namespace (deletes ALL resources inside it!)
kubectl delete namespace development

Warning: Deleting a namespace removes everything in it — Pods, Deployments, Services, ConfigMaps, Secrets — all gone. Be very careful in production.

Summary

  • Namespaces provide logical isolation within a cluster
  • Use them to separate environments, teams, or projects
  • Resource Quotas limit total resource usage per namespace
  • LimitRanges set default resource constraints for Pods
  • Cross-namespace communication works via DNS: <service>.<namespace>.svc.cluster.local
  • Namespaces don’t enforce network isolation by default (use Network Policies)

What’s Next?

Now let’s learn about ConfigMaps — a way to externalize configuration from your application code, making your containers truly portable.

Next: ConfigMaps →

Updated: