Kosli raises $3.1 M USD in seed funding backed by Heavybit - Read more
New White Paper: Supply Chain Levels for Software Artifacts (SLSA) - Download now

How to Use Kubernetes Namespaces: A Guide with Examples

James Walker
Author James Walker
Published January 26, 2023 in technology
clock icon 11 min read

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 auth, payments, and 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.

Default Namespaces

All Kubernetes clusters have four predefined namespaces:

  • default: The default namespace is where your objects get created if you don’t specify anything else. Kubectl interacts with the default namespace when you run a command without the --namespace argument.
  • 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-info ConfigMap 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.

Manage Namespaces

Let’s walk through how to manage namespaces and their objects using kubectl.

Creating a Namespace

The 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 -n or --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 default namespace:

$ 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 -n or --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 demo-namespace namespace:

$ 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 demo-namespace automatically:

$ 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

Use the kubectl delete command with the -n or --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

The 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 kubens:

$ 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 --namespace flag.

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 pod.yaml:

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"]

Conclusion

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.


ABOUT THIS ARTICLE

Published January 26, 2023, in technology

AUTHOR

Stay in the loop with the Kosli newsletter

Get the latest updates, tutorials, news and more, delivered right to your inbox
Kosli is committed to protecting and respecting your privacy. By submitting this newsletter request, I consent to Kosli sending me marketing communications via email. I may opt out at any time. For information about our privacy practices, please visit Kosli's privacy policy.
Kosli team reading the newsletter

Got a question about Kosli?

We’re here to help, our customers range from larges fintechs, medtechs and regulated business all looking to streamline their DevOps audit trails

Contact us
Developers using Kosli