Kubernetes Entry Created: 05 Apr 2026 Updated: 05 Apr 2026

Understanding Kubernetes Namespaces

Overview

Imagine a large office building shared by several companies. Each company has its own floor, its own reception desk, and its own set of employees — completely isolated from the others, yet all under the same roof. Namespaces in Kubernetes work exactly the same way.

A namespace is a virtual partition inside a single Kubernetes cluster. Resources such as Pods, Deployments, Services, and ConfigMaps live inside a namespace. Resources in different namespaces are isolated from each other by name, which means you can have a Deployment called web-api in both the development namespace and the production namespace without any conflict.

Namespaces are the primary mechanism Kubernetes provides for multi-tenancy and environment separation within a cluster. They also serve as the boundary for applying resource quotas, network policies, and role-based access control (RBAC).

Core Concepts

Why Use Namespaces?

In a small hobby project with one developer and one environment, a single namespace is perfectly fine. However, in real-world organisations you typically need to:

  1. Separate environments (development, staging, production) on the same cluster
  2. Give different teams their own isolated workspace
  3. Limit how many CPU, memory, and storage resources a team can consume
  4. Apply different security policies per environment
  5. Organise hundreds of microservices so they do not collide by name

Namespaces solve all of these problems without requiring multiple physical clusters.

Built-in Namespaces

Every Kubernetes cluster ships with four namespaces created automatically. You should understand what each one is for before creating your own.

NamespacePurposeShould you deploy workloads here?
defaultThe fallback namespace when no namespace is specifiedOnly for quick demos — avoid in production
kube-systemCore Kubernetes system components (DNS, scheduler, controller manager)No — managed by Kubernetes itself
kube-publicPublicly readable data; cluster info accessible without authenticationNo
kube-node-leaseNode heartbeat Lease objects used by the node lifecycle controllerNo

Namespace Scope vs. Cluster Scope

Not every Kubernetes resource lives inside a namespace. Resources are either namespace-scoped or cluster-scoped.

  1. Namespace-scoped: Pods, Deployments, Services, ConfigMaps, Secrets, ReplicaSets, Jobs, CronJobs
  2. Cluster-scoped: Nodes, PersistentVolumes, ClusterRoles, ClusterRoleBindings, Namespaces themselves

A cluster-scoped resource is visible and accessible from every namespace. A namespace-scoped resource is only visible inside the namespace it belongs to.

Cross-Namespace DNS

Services inside the same namespace can reach each other by short name, for example http://catalog-service. To reach a Service in a different namespace you must use the full DNS name: http://<service-name>.<namespace>.svc.cluster.local.

For example, the order-api Service in the production namespace is reachable at http://order-api.production.svc.cluster.local from any other namespace.

Resource Quotas and LimitRanges

Once you have separate namespaces, you can attach a ResourceQuota to cap the total CPU, memory, and object count a namespace may consume. You can also attach a LimitRange to set default resource requests and limits for every Pod created in that namespace, preventing runaway containers from starving other workloads.

Namespace Manifest

Creating a namespace declaratively is straightforward. Save the following file as ecommerce-dev-namespace.yaml and apply it:

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

Save the following file as ecommerce-prod-namespace.yaml for the production environment:

apiVersion: v1
kind: Namespace
metadata:
name: ecommerce-prod
labels:
environment: production
team: ecommerce
kubectl apply -f ecommerce-prod-namespace.yaml

Deploying a Workload Into a Namespace

There are two ways to target a namespace when creating a resource:

  1. Set metadata.namespace inside the YAML manifest and use kubectl apply. This approach is recommended for production workflows because the namespace is part of the definition and is always explicit.
  2. Use the -n <namespace> flag with kubectl apply. The flag overrides any namespace specified (or absent) in the manifest.

The Deployment below runs a simple ASP.NET Core 10 catalog API inside the ecommerce-dev namespace. Save it as catalog-api-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-api
namespace: ecommerce-dev
labels:
app: catalog-api
environment: development
spec:
replicas: 2
selector:
matchLabels:
app: catalog-api
template:
metadata:
labels:
app: catalog-api
environment: development
spec:
containers:
- name: catalog-api
image: mcr.microsoft.com/dotnet/aspnet:10.0
ports:
- containerPort: 8080
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
kubectl apply -f catalog-api-deployment.yaml

The Service that exposes this Deployment inside the ecommerce-dev namespace. Save it as catalog-api-service.yaml:

apiVersion: v1
kind: Service
metadata:
name: catalog-api
namespace: ecommerce-dev
spec:
type: ClusterIP
selector:
app: catalog-api
ports:
- port: 80
targetPort: 8080
kubectl apply -f catalog-api-service.yaml

ResourceQuota for a Namespace

Attach a quota to the ecommerce-dev namespace to prevent developers from accidentally consuming too many cluster resources. Save it as ecommerce-dev-quota.yaml:

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

Hands-On: Kubernetes Commands

List all namespaces

Show every namespace in the cluster along with its status and age:

kubectl get namespaces

Short form:

kubectl get ns

Create a namespace imperatively

Create a namespace directly from the command line without a YAML file:

kubectl create namespace ecommerce-dev

Describe a namespace

View details about a namespace including its resource quotas and limit ranges:

kubectl describe namespace ecommerce-dev

List resources in a specific namespace

Use -n to scope any kubectl get command to a single namespace:

kubectl get pods -n ecommerce-dev
kubectl get deployments -n ecommerce-dev
kubectl get services -n ecommerce-dev

List resources across all namespaces

Use -A (or --all-namespaces) to see resources in every namespace at once:

kubectl get pods -A
kubectl get deployments -A

Set a default namespace for your session

Typing -n ecommerce-dev on every command becomes repetitive. Set it as the default for your current context instead:

kubectl config set-context --current --namespace=ecommerce-dev

Now every subsequent kubectl command targets ecommerce-dev automatically.

View resource quotas in a namespace

Check how much of the quota has been consumed:

kubectl get resourcequota -n ecommerce-dev
kubectl describe resourcequota ecommerce-dev-quota -n ecommerce-dev

Delete a namespace

Deleting a namespace deletes all resources inside it. This operation is irreversible — use it with care:

kubectl delete namespace ecommerce-dev

Step-by-Step Example

Scenario: Separating Development and Production on One Cluster

Your team runs a small e-commerce platform. You want to deploy the same application stack to both a development environment (where developers experiment freely) and a production environment (where real customers shop) — all on the same Kubernetes cluster. You will use namespaces to keep them completely isolated.

Step 1 — Create the two namespaces

Apply both namespace manifests:

kubectl apply -f ecommerce-dev-namespace.yaml
kubectl apply -f ecommerce-prod-namespace.yaml

Verify they were created:

kubectl get namespaces

Expected output (abbreviated):

NAME STATUS AGE
default Active 5d
ecommerce-dev Active 5s
ecommerce-prod Active 4s
kube-system Active 5d

Step 2 — Deploy the catalog API into development

kubectl apply -f catalog-api-deployment.yaml
kubectl apply -f catalog-api-service.yaml

Check that the Pods are running in the correct namespace:

kubectl get pods -n ecommerce-dev

Confirm the Pods are not visible in the production namespace:

kubectl get pods -n ecommerce-prod

Expected output:

No resources found in ecommerce-prod namespace.

Step 3 — Attach a resource quota to development

kubectl apply -f ecommerce-dev-quota.yaml

View the quota and how much has been used so far:

kubectl describe resourcequota ecommerce-dev-quota -n ecommerce-dev

You will see columns for Resource, Used, and Hard limits.

Step 4 — Set the development namespace as your default

kubectl config set-context --current --namespace=ecommerce-dev

From now on you can omit -n ecommerce-dev from every command:

kubectl get pods

Step 5 — Cross-namespace DNS resolution

Deploy a temporary debug Pod in the ecommerce-prod namespace and try to reach the catalog-api Service that lives in ecommerce-dev:

kubectl run debug --image=busybox:1.37 --restart=Never -n ecommerce-prod -- \
wget -qO- http://catalog-api.ecommerce-dev.svc.cluster.local

This demonstrates that cross-namespace communication is possible through the full DNS name, while the short name catalog-api would resolve only within ecommerce-dev.

Step 6 — Clean up the debug Pod

kubectl delete pod debug -n ecommerce-prod

Summary

Namespaces are virtual partitions inside a Kubernetes cluster that isolate resources by name. They are the foundation for multi-tenancy, environment separation, and access control in real-world Kubernetes deployments.

  1. Four built-in namespaces exist in every cluster: default, kube-system, kube-public, and kube-node-lease.
  2. Always declare the namespace in your YAML manifests using metadata.namespace for predictable deployments.
  3. Use kubectl get <resource> -n <namespace> to work within a specific namespace, or -A to see all namespaces at once.
  4. Set a default namespace per context with kubectl config set-context --current --namespace=<ns>.
  5. Apply ResourceQuota objects to cap CPU, memory, and object counts per namespace.
  6. Reach Services across namespaces using the full DNS name: <service>.<namespace>.svc.cluster.local.
  7. Deleting a namespace removes all resources inside it — always double-check before deleting.


Share this lesson: