4.3 Creating and Switching Namespaces
Right, so you’ve decided you don’t want all your stuff in one big, messy room. Good call. Welcome to namespaces, the single most effective tool for organizing the glorious chaos of a Kubernetes cluster. Think of a namespace as a virtual cluster inside your actual cluster. It’s a way to slice up the resources—pods, services, deployments, the whole lot—into logically separated groups. This is your first, best step towards multi-tenancy, where you can have separate ‘dev’, ‘staging’, and ‘production’ environments all humming along on the same physical hardware without the dev team accidentally deleting the production database. (It happens more than you’d think.)
Now, let’s get our hands dirty. The most common way you’ll create a namespace is by applying a YAML file, because that’s how we do things properly in Kubernetes. It’s about as simple as it gets.
# my-first-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
# You can add labels here too, like 'team: frontend'
Apply it with the trusty kubectl apply:
kubectl apply -f my-first-namespace.yaml
And just like that, you’ve carved out a shiny new space called ‘development’. You can verify it’s there by asking Kubernetes to list all namespaces:
kubectl get namespaces
You’ll see your new development namespace sitting right there next to the built-in ones like default and kube-system. Speaking of which, a quick but vital aside: never, ever mess with kube-system. That’s where the cluster’s own control plane components live. Poking around in there is like performing open-heart surgery on yourself. Just don’t.
The kubectl create namespace Shortcut
Look, I get it. Sometimes you’re in a hurry and whipping up a YAML file feels like overkill. For those moments, there’s a handy imperative command:
kubectl create namespace staging
Boom. Done. It’s fast, it’s easy, and it’s perfectly valid for quick and dirty work. But a word of caution: this method is less auditable and reproducible. If you need to remember how you created that namespace six months from now, that command is lost to history, whereas the YAML file can be stored in Git. Prefer the declarative approach (kubectl apply -f) for anything you care about long-term.
Actually Doing Stuff In Your New Namespace
Creating the namespace is only half the battle. Now you need to actually use it. You have three main ways to tell kubectl which sandbox you want to play in.
The most explicit way is to use the --namespace (or -n) flag with every command. This is precise and leaves no room for error.
kubectl -n development create deployment nginx --image=nginx
kubectl -n development get pods
This is great for one-offs, but typing -n development fifty times a day will get old fast.
The second way is to set a context. This is like changing your working directory. You tell kubectl, “Hey, from now on, assume I want to work in this namespace unless I say otherwise.”
kubectl config set-context --current --namespace=development
You can verify this worked by checking your current context:
kubectl config get-contexts
See the asterisk (*) next to your context? The NAMESPACE column should now say development. Now, any subsequent kubectl get pods will implicitly look in the development namespace. This is incredibly useful, but also a classic pitfall. You’ll forget you set it, run a command expecting to see resources in default, see nothing, and spend ten minutes thinking your cluster is broken. It’s not. You just forgot where you were. I’ve done it. Everyone has.
The third, and most robust, method is to define the namespace directly in your resource YAML files. This is a best practice you should adopt whenever possible.
# my-deployment-in-dev.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: development # <-- This is the key line
spec:
...
When you apply this file with kubectl apply -f my-deployment-in-dev.yaml, the resource will be created in the specified namespace, regardless of what your current context is. This makes your configuration self-contained and portable.
The Fine Print and Quirks
Here’s where the designers made a choice you should know about: namespaces provide organizational isolation, but not always hard network or security isolation. By default, a pod in the development namespace can still communicate with a service in the staging namespace if it knows the service’s DNS name (which is <service-name>.<namespace-name>.svc.cluster.local). For real hard isolation, you need to deploy Kubernetes Network Policies. Don’t assume a namespace is a security boundary on its own.
Also, some things are just cluster-scoped and don’t belong to any namespace. Run kubectl api-resources --namespaced=false to see them. Things like Nodes, PersistentVolumes, and StorageClasses are global entities. You can’t put a Node in your development namespace, thankfully.
So, to wrap it up: use namespaces relentlessly. Define them declaratively in YAML. Be explicit in your commands or your context, and always, always know which one you’re in. It’s the simplest way to keep your cluster from becoming a digital hoarder’s basement.