Foundations organization

Namespaces & Resource Isolation

● Beginner ⏱ 10 min read organization

A Kubernetes cluster is a single shared environment, but teams, projects, and environments need logical separation. Namespaces divide a cluster into virtual sub-clusters, giving each workload its own naming scope, resource budget, and access controls — all within the same physical infrastructure.

What Are Namespaces?

Namespaces are a mechanism for logically isolating groups of resources within a single cluster. They provide:

⚠️
Namespaces are not security boundaries

Without Network Policies, pods in different namespaces can freely communicate. Without PodSecurity admission, a privileged pod in any namespace can escape to the host. Namespaces are an organisational tool; hard multi-tenancy requires additional controls.

Default Namespaces

A fresh cluster ships with four namespaces:

Namespace Purpose
default Where resources land when you don't specify a namespace. Fine for exploration; avoid it for production workloads.
kube-system Kubernetes control plane components: the API server, scheduler, controller manager, CoreDNS, kube-proxy, and cloud-controller.
kube-public Readable by all users, including unauthenticated ones. Used for cluster-info and bootstrap tokens.
kube-node-lease Stores Lease objects that the kubelet updates as heartbeats; allows the control plane to detect node failure efficiently.
💡
Never deploy workloads into kube-system

Cluster add-ons (Ingress controllers, cert-manager, monitoring agents) sometimes install into kube-system. Prefer dedicated namespaces like ingress-nginx or cert-manager so their resources are clearly separated from core cluster components.

Scoped vs. Cluster-wide Resources

Not every Kubernetes resource lives inside a namespace. Resources fall into two categories:

Namespace-scoped Cluster-scoped
Pods, Deployments, Services Nodes
ConfigMaps, Secrets PersistentVolumes
ServiceAccounts, Roles, RoleBindings ClusterRoles, ClusterRoleBindings
Ingresses, NetworkPolicies StorageClasses, IngressClasses
ResourceQuotas, LimitRanges CustomResourceDefinitions (CRDs)

Check whether a resource is namespace-scoped with:

kubectl api-resources --namespaced=true   # namespace-scoped resources
kubectl api-resources --namespaced=false  # cluster-scoped resources

Working with Namespaces

Creating a namespace

namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: team-alpha
  labels:
    team: alpha
    env: production

Or imperatively:

kubectl create namespace team-alpha

Using a namespace in manifests

Set the namespace in the resource's metadata:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: team-alpha   # explicit namespace
spec:
  containers:
  - name: app
    image: nginx:1.27

Setting a default namespace for your kubectl session

Typing -n team-alpha on every command is tedious. Set a permanent default for the current context:

# set default namespace for the current context
kubectl config set-context --current --namespace=team-alpha

# verify
kubectl config view --minify | grep namespace

DNS within and across namespaces

A Service named api in namespace team-alpha is reachable:

From Address
Same namespace api or api.team-alpha
Different namespace api.team-alpha.svc.cluster.local

Resource Quotas

A ResourceQuota caps the total resources (CPU, memory, object counts) a namespace may consume. This prevents one team from starving the rest of the cluster.

quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-alpha-quota
  namespace: team-alpha
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "20"
    services: "10"

Check quota usage:

kubectl describe resourcequota team-alpha-quota -n team-alpha

A companion object, LimitRange, sets default and maximum CPU/memory per container in a namespace — useful when developers forget to set resource requests:

limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-alpha
spec:
  limits:
  - type: Container
    default:
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    max:
      cpu: "2"
      memory: "2Gi"

When to Use Multiple Namespaces

A single default namespace is fine for a solo developer experimenting on a laptop cluster. For anything else, plan namespace boundaries around one or more of these axes:

Strategy Example namespaces Best for
By environment dev, staging, prod Separate environments in one cluster
By team team-frontend, team-backend, team-data Org-level isolation and chargeback
By application payments, auth, notifications Microservices with distinct lifecycle and ownership
By component tier monitoring, ingress-nginx, cert-manager Infrastructure add-ons separated from app workloads
💡
Namespace deletion is irreversible

Deleting a namespace cascades to every resource inside it — pods, services, secrets, configmaps, and more. There is no recycle bin. Always double-check before running kubectl delete namespace <name>.