Namespace: resource isolation
How a cluster is split into areas, which resources fall outside them, and the rules kubectl uses to pick a namespace.
How a cluster is split into areas, which resources fall outside them, and what rules kubectl follows to pick a namespace. The lesson on your first Pod helps here.
Why you need a namespace
A namespace is an area inside a cluster that isolates resources from each other. Inside one namespace, names of resources of the same type are unique.
Different teams, environments, and projects share one cluster. Without
namespaces their names would collide fast. Team A has its own Service
api, team B also has api: without a boundary that's a conflict. A
Service is an object that gives a permanent address to a group of Pods. A
namespace is the boundary inside which team A's api doesn't get in the
way of team B's api.
Other settings attach to a namespace too. RBAC sets who can do what inside it. You can cap a team's total CPU and memory (ResourceQuota) and the traffic allowed between Pods (NetworkPolicy); separate lessons cover those.
In production, a namespace is a unit of administration: its own team, its own permissions, its own limits.
What lives in a namespace, and what doesn't
Not every resource lives inside a namespace.
Inside a namespace (namespaced): Pod, Deployment, Service, ConfigMap, Secret, Role, Job.
Outside a namespace, at the whole-cluster level (cluster-scoped): Node, Namespace, PersistentVolume, ClusterRole, StorageClass.
| Namespaced | Cluster-scoped |
|---|---|
| Pod, Deployment, Service | Node, Namespace |
| ConfigMap, Secret | PersistentVolume, StorageClass |
| Role, Job | ClusterRole |
You can check which group a resource belongs to:
kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=false
A Node is a cluster machine; it belongs to the whole cluster, so it sits outside any namespace. A Pod runs on a node, but it's tied to a namespace.
Standard namespaces
A fresh cluster already ships with a few namespaces.
default: everything lands here if you don't name a namespace. Not used in production.kube-system: Kubernetes system components. Don't touch it directly.kube-public: readable by everyone, even without authentication. It holds the ConfigMapcluster-infowith public cluster data.kube-node-lease: housekeeping data about node state.
Local-cluster tools add their own. kind, for example, also adds
local-path-storage:
kubectl get ns
NAME STATUS AGE
default Active 97s
kube-node-lease Active 94s
kube-public Active 99s
kube-system Active 100s
local-path-storage Active 46s
How to create a namespace
Imperatively, with one command:
kubectl create ns team-a
ns is short for namespace.
Declaratively, with a manifest:
apiVersion: v1
kind: Namespace
metadata:
name: team-a
You can also name the namespace right in a resource's manifest:
apiVersion: v1
kind: Pod
metadata:
name: pinger
namespace: team-a
spec:
containers:
- name: pinger
image: busybox:1.36.1
command: ["sleep", "3600"]
If the namespace doesn't exist yet, apply fails:
Error from server (NotFound): error when creating "pod.yaml": namespaces "team-a" not found
That's why you create the namespace first, then put resources into it.
The -n flag
By default kubectl works in the namespace from the current context
(usually default). To reach a different namespace, add the -n flag:
kubectl get pod -n team-a
kubectl apply -f pod.yaml -n team-a
kubectl logs pinger -n team-a
The -A flag (or --all-namespaces) shows resources from every namespace
at once:
kubectl get pod -A
To change the default namespace for the current context:
kubectl config set-context --current --namespace=team-a
After that, kubectl get pod with no flags looks inside team-a. The
command only changes the kubeconfig file; the cluster knows nothing about
it. To see which namespace is selected right now:
kubectl config view --minify -o jsonpath='{..namespace}'
Empty output means default.
Reaching across namespaces
Every Service gets a DNS name of this shape:
<service>.<namespace>.svc.cluster.local
From a Pod in your own namespace, you can reach a Service by its short
name: api. From another namespace you need the address with the
namespace: api.team-a.svc.cluster.local or shorter, api.team-a.
You can see why in any Pod's /etc/resolv.conf. Here's a Pod from
team-b:
kubectl exec -n team-b deploy/api -- cat /etc/resolv.conf
search team-b.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
The search line lists the domains the DNS client appends to a short
name. Your own namespace's domain comes first. That's why api from
team-b turns into api.team-b.svc.cluster.local, while api.team-a
turns into api.team-a.svc.cluster.local.
For example, a Pod in team-b calls team A's Service api:
curl http://api.team-a.svc.cluster.local:8080/health
The busybox image has no curl; there, the same thing is
wget -qO- http://api.team-a.svc.cluster.local:8080.
Which namespace kubectl picks
When kubectl creates or looks up a resource, it picks a namespace this way.
- If the manifest has
metadata.namespace, it uses that. - Otherwise, if the
-nflag is set, it uses that. - Otherwise it uses the namespace from the current context.
- Otherwise
default.
A conflict is a separate case. If the manifest has namespace: team-a
written in it, but the command runs as
kubectl apply -f pod.yaml -n team-b, kubectl doesn't silently pick one of
the two. It returns an error and creates nothing:
error: the namespace from the provided object "team-a" does not match the namespace "team-b". You must pass '--namespace=team-a' to perform this operation.
If -n matches the manifest, there's no error. The rule is simple: set the
namespace either in the manifest or with the flag, never different ones in
both places. One manifest without metadata.namespace can be applied into
several namespaces with the -n flag.
Deleting a namespace
kubectl delete ns team-a deletes everything inside it. That's handy for
cleaning up a learning cluster and dangerous in production. The deletion is
asynchronous: the namespace moves into the Terminating phase and waits
for all its resources to free up.
NAME STATUS AGE
team-a Terminating 9s
If it gets stuck, the usual cause is a finalizer on some resource. A finalizer is a marker on an object that blocks deletion until cleanup finishes.
Common mistakes
- A resource "disappears": it's actually in another namespace, and
kubectl getonly looks at the context's namespace. Search with-A. applywithout-nfor a manifest with nometadata.namespace: the object lands indefaultor the context's namespace, not where you meant it to go.- A Service's short name from another namespace. DNS looks for it in your
own namespace and doesn't find it. You need
<service>.<namespace>. namespaces "..." not found: the namespace wasn't created before the resources.- Different namespaces in the manifest and in
-n: kubectl refuses to run the command. kubectl delete nsin production without checking its contents: it deletes everything inside.
What you'll need for the tasks
kubectl get ns,kubectl get <resource> -A.kubectl create ns <name>.kubectl apply -f <file> -n <namespace>.kubectl config set-context --current --namespace=<namespace>andkubectl config view --minify.- A Service's DNS name:
<service>.<namespace>.svc.cluster.local. kubectl logs,kubectl describe, andkubectl set envfor a Deployment, with the-nflag.kubectl exec <Pod or deploy/name> -- wget -qO- -T 5 <URL>for a request from inside the cluster.
The tasks live in the labs/ folder: each lab brings up its own kind
cluster on your machine, with instructions in its README.md.
Homework
Practice the theory on your own cluster: 2 steps with a check. Set up the cluster with the Kubernetes locally track, the tasks live in the k8s-practice repository.
./run.sh start k8s-namespace # set up the starting state
./run.sh verify k8s-namespace # check the current step
In short
- A namespace isolates resources inside a cluster; names are unique within its boundary.
- Namespaced: Pod, Deployment, Service, ConfigMap, Secret. Cluster-scoped: Node, Namespace, PersistentVolume, ClusterRole, StorageClass.
- Check the group:
kubectl api-resources --namespaced=false. -npicks a namespace for a command,-Ashows all of them at once.- Selection order:
metadata.namespace, then-n, then the context, thendefault. Different values in the manifest and in-ncause an error. - A Service's FQDN:
<service>.<namespace>.svc.cluster.local. - Deleting a namespace wipes out everything inside it and runs
asynchronously through the
Terminatingphase.
Interview-style questions
Interview questions on this topic: 1
Included with practice access, $49 one-time. Get access
Answer out loud or in writing, then reveal the answer and honestly mark whether you knew it.
Done reading?
Mark the lesson as read to move your track progress forward.
Lesson marked as done.
Go through it with an AI agent
The agent explains anything unclear in plain words, gives you 2 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.
Tell the agent: use MCP izi, give me lesson k8s-basics/namespace
Progress saved in this browser
Clear your history or open this on your phone, and the marks will be gone. Leave your email and they'll move to your account. No password needed.
Done. moved to your account. You can see your progress on any device. My progress