Kubernetes namespaces logically isolate groups of related objects inside a cluster. You can use them to distinguish among objects belonging to different deployments, teams, and organizations. Namespace-level controls let you set resource limits and access control rules that span all the namespace’s objects, providing a consistent management experience.
In this article you’ll learn how namespaces work, when to create a new one, and what best practices to follow. It also covers practical techniques for interacting with namespaces using kubectl.
What Are Namespaces?
A namespace is a collection of Kubernetes objects that share a logical relationship. Namespaces have a similar role to the namespacing concept found in several programming languages. As well as grouping objects together, namespaces scope object names to avoid collisions.
Most object types, such as pods, deployments, and jobs, can be added to a namespace. Some kinds of resources can’t be namespaced, though, while others, like Role, ClusterRole, RoleBinding, and ClusterRoleBinding, require you to use a different variant depending on whether you’re scoping to a namespace or not.
Objects that can’t exist in a namespace are said to be cluster-wide. Namespaces fit into this category themselves. You can’t create hierarchies of namespaces because it’s not possible to nest them within each other.
Namespace Use Cases
Namespaces enable more efficient use of Kubernetes clusters. Dividing one cluster into several namespaces for your projects and teams is usually easier to manage than multiple clusters. Using namespaces offers the following benefits when you’re administering Kubernetes:
Prevent Naming Conflicts
Namespaces address the naming conflicts that would occur if all objects existed in one global namespace. Kubernetes requires that new objects have a unique name, but this rule is scoped to the namespace the object belongs to.
It’s forbidden to create two pods called
api in the
app-1 namespace, but a pod called
api in the
app-1 namespace can coexist with another one that exists in
app-2. This scoping of names helps teams work efficiently without interfering with each other.
Partition Application Environments (Development, Staging, Production)
Namespaces are often used to deploy multiple instances of an application. You can colocate your development, staging, and production environments in your cluster by creating a namespace for each one.
Setting up different namespaces lets you use resource quotas to allocate available CPU and memory on a per-environment basis. Setting a stringent quota on your development namespace will prevent poorly optimized code from affecting your production environment, for example.
Partition Applications and Their Services
Namespaces can be used to partition the components of a single application. This is particularly common for large microservices architectures where each service could comprise many interconnected components.
Creating a namespace for each of those services, such as
photos, lets you focus on each part in isolation. You can apply resource quotas to individual pieces, ensuring high-priority services have a higher chance of remaining stable. The model facilitates more powerful access control rules, too, such as restricting interactions with the
payments namespace to a specific set of users.
Divide Cluster Resources Among Teams
Partitioning your cluster so it replicates your organization’s team structure is another way to use namespaces. It’s especially useful for shared development clusters that multiple teams deploy to concurrently.
Namespaces let you assign each team its own space in the cluster. This prevents new deployments from causing side effects for other teams. You can use resource quotas to equally share out the cluster’s capacity, guaranteeing each team always has the resources it needs to stay productive.
Limit Processes to Certain Namespaces
Object count quotas specify the total number of objects of a certain type that a namespace can simultaneously contain. This mechanism can be used to enforce the kinds of processes each namespace is used for.
Setting the Secrets object count to
0 prevents sensitive data from being accidentally written to a widely accessible namespace. Similarly, you might want to prevent NodePort services from being added to a namespace, as these are the least secure form of Kubernetes networking. Creating an object count quota with
services.nodeports set to
0 will defend against mistakes.
All Kubernetes clusters have four predefined namespaces:
defaultnamespace is where your objects get created if you don’t specify anything else. Kubectl interacts with the
defaultnamespace when you run a command without the
kube-public: This is a reserved namespace that’s used for Kubernetes objects that must be globally accessible throughout your cluster. Its contents can be read by any client that’s connected to the Kubernetes API. The
cluster-infoConfigMap is stored here, so all clients can establish your cluster’s identity.
kube-system: This namespace contains all the Kubernetes control plane components, including kube-apiserver, kube-controller-manager, and kube-scheduler. You shouldn’t add your own objects to this namespace.
kube-node-lease: This is a reserved namespace that stores objects used by the node lease process. It collects node heartbeats to detect when nodes become unhealthy. This is another namespace you should not manage manually.
Let’s walk through how to manage namespaces and their objects using kubectl.
Creating a Namespace
kubectl create namespace command adds a namespace. It takes the name of the new namespace as its argument:
$ kubectl create namespace demo-namespace namespace/demo-namespace created
Listing Objects in a Namespace
To list objects in a namespace, include the
--namespace flag with the
kubectl get command:
$ kubectl get pods --namespace demo-namespace No resources found in demo-namespace namespace
If you omit the flag, kubectl uses the
$ kubectl get pods No resources found in default namespace
To list all the objects in a namespace, try running the following command. It retrieves the list of namespaced object types from your Kubernetes cluster and then runs
kubectl get for each one inside a loop:
$ kubectl api-resources --verbs=list --namespaced -o name | \ xargs -n 1 echo $1 kubectl get --show-kind --ignore-not-found -n demo-namespace
Creating Objects in a Namespace
You can use the
--namespace flag with commands like
kubectl create and
kubectl run. The flag causes the action to be performed in the context of the specified namespace. This example creates a new pod called
nginx that’s added to the
$ kubectl run nginx --image nginx:latest --namespace demo-namespace pod/nginx created
Listing the objects in the namespace confirms the new pod has been scoped correctly:
$ kubectl get pods --namespace demo-namespace NAME READY STATUS RESTARTS AGE nginx 0/1 Running 0 5s
You don’t need to use the flag if you’re applying an object manifest from a YAML file. Instead, you should set the
metadata.namespace field inside the manifest:
apiVersion: v1 kind: Pod metadata: name: nginx namespace: demo-namespace spec: containers: - name: nginx image: nginx:latest
Save the YAML to
nginx.yaml and try running
kubectl apply with it. The pod will be added to
$ kubectl apply -f nginx.yaml pod/nginx created $ kubectl get pods --namespace demo-namespace NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 5s
Deleting Objects from a Namespace
kubectl delete command with the
--namespace flag to delete an object that’s scoped to a namespace:
$ kubectl delete pod nginx --namespace demo-namespace pod "nginx" deleted
Always check you’ve entered the correct namespace. You could delete the wrong object if several items share the same name but exist in different namespaces.
Deleting an Entire Namespace
Namespace deletions are supported by the
kubectl delete command:
$ kubectl delete namespace demo-namespace namespace "demo-namespace" deleted
It will first delete the items inside the namespace and then remove the namespace itself. The process can appear to hang because Kubernetes allows the namespace’s objects a grace period before they’re terminated. You can unsafely skip this grace period and force immediate deletion using the following command variant:
$ kubectl delete namespace demo-namespace --grace-period 0 --force namespace "demo-namespace" deleted
Quickly Switching Between Namespaces
kubens plugin for kubectl lets you quickly switch between namespaces without repeating the
--namespace flag for each command. Install the Krew plugin manager if required, and then run the following command to get
$ kubectl krew install ns
The plugin lets you list the namespaces in your cluster by running the custom
kubectl ns command:
$ kubectl ns default demo-namespace kube-node-lease kube-public kube-system
Your active namespace will be highlighted. To change the active namespace, run
kubectl ns and supply the new namespace name as an argument:
$ kubectl ns demo-namespace
All subsequent kubectl commands will target the active namespace unless you override it with the
Applying a Resource Quota to a Namespace
Resource quotas cap the amount of a certain resource that a namespace is allowed to use. They let you evenly distribute your cluster’s capacity among several namespaces, preventing one group’s objects from using a disproportionate amount.
There are quotas for CPU consumption, memory usage, storage access, and object counts. Users cannot create new objects in the namespace if they would breach any of the quotas you’ve defined. When CPU and memory quotas are configured, every pod you create must have a corresponding resource request so Kubernetes can match it to the quota.
The following YAML manifest defines a resource quota that restricts the memory usage of
demo-namespace to a maximum of 4 Gi:
apiVersion: v1 kind: ResourceQuota metadata: name: resource-quota namespace: demo-namespace spec: hard: memory: 4Gi
Save the manifest to
quota.yaml and use kubectl to apply it to your cluster:
$ kubectl apply -f quota.yaml resourcequota/resource-quota created
Next, save the following YAML manifest to
apiVersion: v1 kind: Pod metadata: name: nginx namespace: demo-namespace spec: containers: - name: nginx image: nginx:latest resources: requests: memory: 8Gi
The pod requests 8 Gi of memory, which exceeds the allowance in the namespace’s quota. You’ll get an
exceeded quota error when you try to apply the manifest:
$ kubectl apply -f pod.yaml Error from server (Forbidden): error when creating "nginx.yaml": pods "nginx" is forbidden: exceeded quota: memory-quota, requested: memory=8Gi, used: memory=0, limited: memory=4Gi
Communicating Between Namespaces
Namespaces are not fully isolated. It can be tempting to think of them as virtual clusters, but this analogy is limited in depth. Namespaces are siblings in a single cluster, and services within them can freely communicate.
Kubernetes automatically creates DNS entries for new services using the format
<service-name>.<namespace-name>.svc.cluster.local. If you have a service called
database in your
api namespace, it can be reached by any pod using the
database.api.svc.cluster.local hostname. This will resolve correctly even when the pod exists in a different namespace.
Cross-namespace communication is most useful when you’re partitioning a microservices architecture so that each service gets its own namespace. Services can still contact the other services they depend on because there are no hard barriers between them.
Kubernetes Namespaces Best Practices
Namespaces are a powerful pattern for controlling Kubernetes utilization, but they can cause problems when used incorrectly or without supporting features. Here are three best practices you should follow to get the most benefits.
Know When to Use a Namespace
Namespaces aren’t always the right choice. They’re optimal when you want to accommodate several teams, projects, or environments inside one Kubernetes cluster. You might not need to use multiple namespaces if you only have a small number of workloads. Conversely, namespaces aren’t suitable when you’ve got many objects that require strong physical separation from each other.
The decision to use a namespace should be based on whether you need its functionality. This could be setting resource quotas, configuring access control restrictions, or avoiding naming collisions across different services. If you’re not looking for any of these benefits, there’s no advantage to creating another namespace.
Limit Namespace Resource Usage
All namespaces should be allocated a resource quota that defines the resources its objects can use. This prevents one namespace from consuming all the cluster’s capacity, leaving none left for others.
Aside from resource quotas, you can use limit ranges to restrict the resources available to individual pods and containers within the namespace. Without a limit range, a single pod could use 100 percent of the namespace’s resource quota. Limit ranges increase granularity by distributing the quota among the namespace’s objects.
Use Role-Based Access Control to Manage Namespace Access
Use the Kubernetes role-based access control (RBAC) system to limit user access to your namespaces. RBAC lets you designate namespaces for particular users, teams, or environments. It prevents unauthorized users from interacting with objects inside the namespace.
The following sample role allows users that possess it to retrieve the details of pods in the
demo-namespace namespace. They cannot interact with pods in any other namespace:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: get-pods namespace: demo-namespace rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"]
Namespaces let you split your cluster into logical groups of objects. They’re used whenever you want multiple applications, teams, or tenants to share a single cluster. Creating a namespace for each group lets you avoid naming collisions, set resource limits, and enforce access control rules.
Creating a namespace provides a thin isolation layer, as services in different namespaces can still communicate with each other. You shouldn’t rely on namespaces to safely separate critical deployments from low-priority ones, such as production and development. There are also limitations on the scope of isolation that namespaces provide: some objects, like StorageClass, IngressClass, and CustomResourceDefinition (CRD), are cluster-wide, so new additions will be available in all your namespaces.
Sometimes, there’s no alternative to creating another cluster. This is usually when you require physical separation of environments, such as the production and development examples mentioned earlier. In other situations, such as multiple engineering teams working in parallel, you can use namespaces within a single cluster to assign each team its own working space more efficiently.