Imagine you're working on a team that builds web applications. Your team develops new features, tests them, and eventually releases them to customers. Now, picture this scenario: a developer accidentally deploys an untested version of the application to production, causing an outage for thousands of users. This happens more often than you'd think, and it's exactly the kind of problem that Kubernetes namespaces help prevent.
Organizations typically run multiple versions of their applications simultaneously — one for developers to experiment with (dev), one for testing (staging), and one that serves real customers (prod). Without a way to logically separate these environments, it's easy to mix them up. In this lesson, you'll learn how to use Kubernetes namespaces to create isolated environments within a single cluster, providing organizational clarity and a foundation for access control policies.
A namespace in Kubernetes is like a virtual cluster within your physical cluster. It provides a way to divide cluster resources among multiple users, teams, or environments. Think of namespaces as separate folders on your computer — files in one folder don't interfere with files in another folder, even if they have the same name. Similarly, you can have a deployment called web-app in your dev namespace and another deployment also called web-app in your prod namespace, and they won't conflict with each other.
When you first set up a Kubernetes cluster, several namespaces already exist by default. The default namespace is where resources go if you don't specify a namespace. The kube-system namespace contains resources created by Kubernetes itself, like CoreDNS (the DNS service), kube-proxy, and other core components. If you've installed optional tools like the Kubernetes Dashboard, they typically also run in this namespace. The kube-public namespace is readable by all users and is typically used for resources that should be publicly accessible across the cluster. The kube-node-lease namespace holds lease objects associated with each node, which help the control plane detect node failures. You generally won't interact with these system namespaces directly — instead, you'll create your own namespaces to organize your applications.
Namespaces provide logical isolation, which means they separate resources organizationally but not physically. Pods in different namespaces can still communicate with each other if you configure networking properly. The key benefit is organizational clarity and access control — you can set different permissions for different namespaces, ensuring that developers working in the dev namespace can't accidentally modify resources in production.
Creating a namespace in Kubernetes is straightforward. Like most Kubernetes resources, namespaces are defined using YAML files. Let's start by creating a namespace for our development environment. Here's what the YAML file looks like:
This file is remarkably simple compared to other Kubernetes resources. The apiVersion field tells Kubernetes which version of the API to use for this resource. For namespaces, it's just v1. The kind field specifies that we're creating a Namespace resource. The metadata section contains information about the namespace itself, and the most important field here is name, which defines what we'll call this namespace. In this case, we're calling it dev for development.
Let's save this file as namespace-dev.yaml and create a similar one for production:
Save this second file as namespace-prod.yaml. Now, you have two namespace definitions ready to deploy. To actually create these namespaces in your Kubernetes cluster, you use the kubectl apply command:
When you run this command, you should see output like:
Now, create the production namespace:
Sometimes you need to clean up and remove a namespace you no longer need. Kubernetes makes this straightforward, but it's important to understand what happens when you delete a namespace. When you delete a namespace, all resources inside that namespace are automatically deleted — this includes deployments, pods, services, config maps, secrets, and everything else. This cascading deletion is a powerful cleanup mechanism, but it also means you need to be careful.
To delete a namespace, use the kubectl delete namespace command. For example, if you wanted to delete the dev namespace we created earlier:
You would see output like:
Behind the scenes, Kubernetes first marks the namespace for deletion, then systematically removes all resources within it, and finally removes the namespace itself. This process can take a few moments, especially if the namespace contains many resources. You can watch the deletion progress by trying to list resources in that namespace — they'll gradually disappear until the namespace itself is gone.
Warning: Be extremely careful when deleting namespaces, especially in shared or production environments. There's no confirmation prompt, and once you execute the command, all resources in that namespace will be deleted. This is why many organizations implement RBAC policies that restrict who can delete namespaces, particularly for critical environments like production.
If you accidentally set a namespace as your default and then delete it, kubectl will start returning errors when you run commands. You can fix this by setting a different namespace as your default, such as returning to the default namespace:
In practice environments like CodeSignal, deleting namespaces is safe and often useful for starting fresh or cleaning up after experiments.
Now that we have our namespaces set up, let's deploy an application to one of them. The key to deploying resources into a specific namespace is adding the namespace field to the resource's metadata. Here's a deployment configuration for a simple web application using nginx:
The crucial line here is namespace: dev in the metadata section. This tells Kubernetes to create this deployment in the dev namespace rather than the default namespace. Without this line, the deployment would go into whichever namespace is currently set as your default (usually the default namespace).
Let's look at the rest of the deployment configuration:
The replicas field specifies that we want two copies of our application running. The selector tells the deployment which pods it should manage (those with the label app: web-app). The template section defines what each pod should look like — in this case, a single container running nginx version 1.25, listening on port . This is a standard web server that will serve a default welcome page.
Now comes the interesting part: observing how namespace isolation actually works. When you want to view resources in a specific namespace, you need to use the -n flag (short for --namespace) with kubectl commands. Let's check which deployments exist in our dev namespace:
You'll see output like:
This shows our web-app deployment with 2 out of 2 replicas ready. Now, let's check the prod namespace:
The output will be:
This demonstrates namespace isolation in action. Even though we created a deployment, it only exists in the dev namespace. The prod namespace is empty because we haven't deployed anything there yet. This isolation is exactly what prevents accidental changes to the wrong environment — you must explicitly specify which namespace you're working with.
Let's look at the actual pods running in the dev namespace:
You'll see something like:
Typing -n dev or -n prod every time you run a kubectl command can get tedious, especially when you're working primarily in one namespace. Kubernetes allows you to set a default namespace for your current context, which means kubectl will use that namespace automatically unless you explicitly specify a different one. Here's how to set the dev namespace as your default:
When you run this command, you'll see:
The exact context name might be different depending on your Kubernetes setup, but the message confirms that your context has been updated. Now, when you run kubectl commands without the -n flag, they'll automatically operate on the dev namespace. Let's test this:
You'll see:
Notice that we didn't use the -n dev flag, but kubectl still showed us the deployments in the dev namespace. This is because dev is now our default namespace. However, you can still explicitly specify a different namespace when needed:
In this lesson, you've learned how to organize Kubernetes resources using namespaces to create logical separation between environments and teams. We started by understanding why namespaces matter — they prevent accidental deployments to the wrong environment and provide organizational clarity. You created dev and prod namespaces using simple YAML configurations and deployed a web application specifically to the dev namespace.
You explored how namespace isolation works by attempting to view resources in different namespaces and observed that resources in one namespace don't appear when viewing another. You learned how to set a default namespace to make your workflow more efficient, and you discovered how to safely delete namespaces and the cascading effects on resources within them. The key takeaway is that namespaces are a fundamental organizational tool in Kubernetes — they're not just about separation, but about making multi-environment management safe and manageable. Now you're ready to practice these concepts hands-on by creating your own namespaces and deploying applications to different isolated environments.
