Creating a namespace in Minikube takes one command: kubectl create namespace dev. Minikube runs a normal Kubernetes API server, so namespaces work exactly as they do on a managed cluster, and nothing about the minikube binary itself is involved. The interesting parts are what you do afterward: pinning your context so you stop typing the namespace flag, adding quotas so a runaway pod cannot eat your laptop, and knowing what to do when a namespace refuses to delete.
kubectl create namespace dev, then make it the default for your session with kubectl config set-context --current --namespace=dev. To create one declaratively, apply a manifest with kind: Namespace. Verify with kubectl get namespaces.Everything below was checked against minikube 1.38.1, which ships Kubernetes v1.35.1 as its default. The commands are plain kubectl, so they transfer unchanged to kind, k3s, EKS or GKE. Namespaces are the cheapest isolation boundary Kubernetes gives you, and on a local cluster they are the difference between a tidy workspace and one where kubectl get pods returns forty things you do not recognize.
The imperative way
Start the cluster if it is not already running, then create the namespace.
minikube start
kubectl create namespace dev
# Confirm it exists
kubectl get namespaces
kubectl get ns dev -o yaml
# Add labels after the fact
kubectl label namespace dev team=platform env=localThe name has to be a valid DNS label: lowercase letters, digits and hyphens, at most 63 characters, starting and ending with an alphanumeric character. dev, team-a and staging2 all work. Dev, team_a and a name starting with a digit and a dot will all be rejected by the API server with a clear validation message.
The declarative way with a manifest
Anything you intend to keep should live in a file under version control. A namespace manifest is about as small as Kubernetes YAML gets.
# namespace-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
labels:
team: platform
env: local
pod-security.kubernetes.io/enforce: baselinekubectl apply -f namespace-dev.yaml
# See the YAML that would be sent, without sending it
kubectl create namespace dev --dry-run=client -o yaml--dry-run=client -o yaml pattern is the fastest way to generate a starting manifest for almost any resource. Pipe it to a file, edit, then apply. It saves you from remembering the exact apiVersion for things you create rarely.That pod-security.kubernetes.io/enforce label is worth adding even locally. It switches on the built in Pod Security admission controller for the namespace, so a manifest that requests privileged access gets rejected at apply time instead of failing mysteriously later. The three levels are privileged, baseline and restricted.
Making a namespace the default for your session
Typing -n dev on every command gets old within about five minutes. The namespace is a property of the kubeconfig context, so you set it once.
# Pin the namespace on the active context
kubectl config set-context --current --namespace=dev
# Check what you just did
kubectl config view --minify -o jsonpath='{..namespace}'
# Go back to the default namespace
kubectl config set-context --current --namespace=defaultkubectl delete deployment web, get a confirmation, and wonder why the app is still up in the namespace you were actually looking at. Put the current namespace in your shell prompt, or run kubectl config view --minify before any destructive command.Deploying into the namespace
Every namespaced resource accepts -n or a metadata.namespace field. Prefer the flag on the command line and the field in files you commit.
kubectl create deployment web --image=nginx -n dev
kubectl expose deployment web --type=NodePort --port=80 -n dev
kubectl get all -n dev
# Which resource kinds are namespaced at all?
kubectl api-resources --namespaced=true -o name | head
kubectl api-resources --namespaced=false -o nameThat last pair is worth running once. Nodes, PersistentVolumes, StorageClasses and ClusterRoles are cluster scoped, so putting them in a namespace manifest does nothing. Everything you normally deploy, Deployments, Services, ConfigMaps, Secrets and PersistentVolumeClaims, is namespaced.
Resource quotas and limit ranges
This is the main reason to bother with namespaces on a laptop. A ResourceQuota caps the total a namespace can request. A LimitRange sets defaults for any container that forgets to declare its own, which is most of them.
# quota-dev.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 4Gi
pods: "20"
persistentvolumeclaims: "4"
---
apiVersion: v1
kind: LimitRange
metadata:
name: dev-defaults
namespace: dev
spec:
limits:
- type: Container
default:
cpu: 200m
memory: 256Mi
defaultRequest:
cpu: 100m
memory: 128Mikubectl apply -f quota-dev.yaml
kubectl describe quota dev-quota -n dev
kubectl describe limitrange dev-defaults -n devOnce a ResourceQuota that constrains CPU or memory exists in a namespace, the API server requires every new container to declare requests and limits for those resources. Without a LimitRange supplying defaults, plain kubectl create deployment starts failing with a forbidden error. Apply both together or neither.
| Task | Command | Notes |
|---|---|---|
| Create | kubectl create namespace dev | Fails if the name already exists |
| Create or update | kubectl apply -f namespace-dev.yaml | Idempotent, safe to rerun |
| List | kubectl get ns | Shows STATUS Active or Terminating |
| Set as default | kubectl config set-context --current --namespace=dev | Persists in your kubeconfig |
| Inspect usage | kubectl describe quota -n dev | Used versus hard for each resource |
| Delete | kubectl delete ns dev | Deletes everything inside it too |
Deleting a namespace, including a stuck one
Deleting a namespace deletes every namespaced resource inside it. There is no confirmation prompt and no undo, so read the name twice.
kubectl delete namespace dev
# Do not block the shell while it drains
kubectl delete namespace dev --wait=falseSometimes the namespace sits in Terminating and never leaves. That means a resource inside it carries a finalizer that nothing is clearing, usually because the controller or the API service that owned it is gone. Diagnose before you reach for the blunt instrument.
# The status conditions explain what is blocking
kubectl get namespace dev -o jsonpath='{.status.conditions}' | tr ',' '\n'
# Any aggregated API that is unavailable will block deletion forever
kubectl get apiservice | grep -i false
# Hunt for whatever is left inside
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n 1 kubectl get --show-kind --ignore-not-found -n devIf the blocker is a broken APIService, delete that APIService and the namespace usually finishes on its own within a few seconds. If you have already confirmed nothing real is left, you can strip the finalizers directly.
kubectl get namespace dev -o json \
| jq '.spec.finalizers = []' \
| kubectl replace --raw "/api/v1/namespaces/dev/finalize" -f -minikube delete. On a shared or production cluster it can leave real cloud resources billing you, so investigate first.Viewing what lives in a namespace
Once you have a few namespaces, the everyday problem becomes seeing across them without losing track of where things are.
# Everything in one namespace
kubectl get all -n dev
# Pods everywhere, with the namespace column
kubectl get pods --all-namespaces
# Same thing, short form
kubectl get pods -A -o wide
# Sort by which namespace is holding the most events
kubectl get events -A --sort-by=.lastTimestamp | tail -20Note that kubectl get all is misleading: it covers a common set of workload and service kinds, not literally every resource. ConfigMaps, Secrets, Ingresses and custom resources are not in that set. When you need a real inventory before deleting something, use the api-resources loop from the previous section instead.
Troubleshooting
Error: namespaces “dev” already exists. Use kubectl apply instead of kubectl create, or add --dry-run=client -o yaml | kubectl apply -f - to make the operation idempotent in a script.
Pods are forbidden with a message about minimum CPU request. You applied a ResourceQuota without a matching LimitRange. Either add the LimitRange shown above, or set explicit resources.requests and resources.limits on every container in the deployment.
Resources land in the wrong namespace. Your context namespace is set to something you forgot about. Run kubectl config view --minify -o jsonpath='{..namespace}'. An empty result means the default namespace.
The namespace is Terminating after a Helm uninstall failed. Custom resources from the chart still carry finalizers pointing at a controller you already removed. Reinstall the controller so it can clean up, or patch the finalizer off the individual custom resources. Our notes on installing Helm in Minikube cover the release lifecycle that produces this.
You cannot see the namespace at all. On Minikube you are cluster admin by default, so this is almost always a context problem rather than an RBAC one. Confirm with kubectl config current-context and check that the profile you expect is running via minikube profile list.
Frequently asked questions
Does Minikube need anything special to support namespaces?
No. Namespaces are a core Kubernetes API object, and Minikube runs an unmodified API server. Every command in this guide is plain kubectl. A fresh cluster already has four namespaces: default, kube-system, kube-public and kube-node-lease.
How do I create several namespaces at once?
Put multiple documents in one YAML file separated by three hyphens and apply it, or loop in the shell with for n in dev test stage; do kubectl create namespace "$n"; done. The manifest approach is better because you can rerun it safely and keep it in version control.
Can two namespaces run services with the same name?
Yes, and that is the point. Names only need to be unique within a namespace. Cross namespace DNS resolution uses the fully qualified form service.namespace.svc.cluster.local, so a pod in dev reaches the staging database as db.staging.svc.cluster.local.
Do namespaces isolate network traffic by default?
No. Without a NetworkPolicy, any pod can reach any other pod across namespaces. Namespaces isolate names, quotas and RBAC, not packets. On Minikube you need a CNI that enforces policy, so start the cluster with minikube start --cni=calico if you want to test NetworkPolicy behavior.
What happens to PersistentVolumeClaims when I delete the namespace?
The claims are deleted with everything else. Whether the underlying PersistentVolume is removed depends on its reclaim policy. Minikube’s default storage class uses Delete, so the backing data goes away. Snapshot anything you care about first.
The bottom line
One command creates a namespace, and a manifest plus a ResourceQuota and a LimitRange turns it into a sandbox that will not take your machine down. Set the context namespace so you stop typing the flag, but leave yourself a visible reminder of which one is active.
The failure mode worth rehearsing before you need it is a namespace stuck in Terminating. Check the status conditions and the APIService list first, and only clear finalizers once you know what they were waiting on. When you are ready to tear individual workloads down rather than the whole namespace, see our guide on deleting a deployment in Minikube, and the official Kubernetes namespaces documentation is the definitive reference for the object itself. If you are still standing the cluster up, start with installing Minikube on Ubuntu.
About this article: GeekBlog covers U.S. technology news, AI, phones, smartwatches and gaming. Every story is written and checked under our Editorial Policy. Spotted a mistake or have a story tip? Contact our editors.

