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:
- Separate environments (development, staging, production) on the same cluster
- Give different teams their own isolated workspace
- Limit how many CPU, memory, and storage resources a team can consume
- Apply different security policies per environment
- 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.
| Namespace | Purpose | Should you deploy workloads here? |
|---|---|---|
default | The fallback namespace when no namespace is specified | Only for quick demos — avoid in production |
kube-system | Core Kubernetes system components (DNS, scheduler, controller manager) | No — managed by Kubernetes itself |
kube-public | Publicly readable data; cluster info accessible without authentication | No |
kube-node-lease | Node heartbeat Lease objects used by the node lifecycle controller | No |
Namespace Scope vs. Cluster Scope
Not every Kubernetes resource lives inside a namespace. Resources are either namespace-scoped or cluster-scoped.
- Namespace-scoped: Pods, Deployments, Services, ConfigMaps, Secrets, ReplicaSets, Jobs, CronJobs
- 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:
Save the following file as ecommerce-prod-namespace.yaml for the production environment:
Deploying a Workload Into a Namespace
There are two ways to target a namespace when creating a resource:
- Set
metadata.namespaceinside the YAML manifest and usekubectl apply. This approach is recommended for production workflows because the namespace is part of the definition and is always explicit. - Use the
-n <namespace>flag withkubectl 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:
The Service that exposes this Deployment inside the ecommerce-dev namespace. Save it as 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:
Hands-On: Kubernetes Commands
List all namespaces
Show every namespace in the cluster along with its status and age:
Short form:
Create a namespace imperatively
Create a namespace directly from the command line without a YAML file:
Describe a namespace
View details about a namespace including its resource quotas and limit ranges:
List resources in a specific namespace
Use -n to scope any kubectl get command to a single namespace:
List resources across all namespaces
Use -A (or --all-namespaces) to see resources in every namespace at once:
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:
Now every subsequent kubectl command targets ecommerce-dev automatically.
View resource quotas in a namespace
Check how much of the quota has been consumed:
Delete a namespace
Deleting a namespace deletes all resources inside it. This operation is irreversible — use it with care:
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:
Verify they were created:
Expected output (abbreviated):
Step 2 — Deploy the catalog API into development
Check that the Pods are running in the correct namespace:
Confirm the Pods are not visible in the production namespace:
Expected output:
Step 3 — Attach a resource quota to development
View the quota and how much has been used so far:
You will see columns for Resource, Used, and Hard limits.
Step 4 — Set the development namespace as your default
From now on you can omit -n ecommerce-dev from every command:
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:
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
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.
- Four built-in namespaces exist in every cluster:
default,kube-system,kube-public, andkube-node-lease. - Always declare the namespace in your YAML manifests using
metadata.namespacefor predictable deployments. - Use
kubectl get <resource> -n <namespace>to work within a specific namespace, or-Ato see all namespaces at once. - Set a default namespace per context with
kubectl config set-context --current --namespace=<ns>. - Apply
ResourceQuotaobjects to cap CPU, memory, and object counts per namespace. - Reach Services across namespaces using the full DNS name:
<service>.<namespace>.svc.cluster.local. - Deleting a namespace removes all resources inside it — always double-check before deleting.