Kubernetes Core Concepts

Namespaces: Organizing Workloads

Namespaces help organize Kubernetes resources inside a cluster. They are useful for separating teams, applications, environments, and lab work — but they are not the same thing as strong security isolation by themselves.

What this lesson covers

So far, most of our labs used the default namespace. That is fine for early learning, but real clusters need better organization. Namespaces provide a way to group related resources inside the same Kubernetes cluster.

By the end of this lesson, you should understand:

  • What a Namespace is
  • What Namespaces are good for
  • What Namespaces do not solve by themselves
  • How to list existing Namespaces
  • How to create a Namespace
  • How to deploy resources into a specific Namespace
  • How to query resources across all Namespaces
  • How to set a default Namespace for your current context
  • How Services resolve across Namespaces
  • How to clean up a Namespace and everything inside it
Field note: Namespaces organize resources. They can support security boundaries when combined with RBAC, NetworkPolicies, ResourceQuotas, and admission controls, but a Namespace alone is not a complete security boundary.

The short version

A Namespace is a logical grouping of Kubernetes resources inside a cluster.

Instead of putting every Pod, Deployment, Service, ConfigMap, and Secret into the same space, you can separate them:

default
kube-system
training
dev
test
prod
team-a
team-b

Each Namespace can contain resources with the same names as resources in another Namespace.

For example, this is allowed:

dev/nginx
test/nginx
prod/nginx

The name nginx can exist in multiple Namespaces because the full identity includes the Namespace.

Why Namespaces matter

Namespaces help reduce confusion as clusters grow.

They are commonly used to separate:

  • Applications
  • Teams
  • Environments
  • Lab work
  • System components
  • Temporary test workloads

Without Namespaces, everything ends up in the same default bucket. That becomes hard to read, hard to manage, and easy to accidentally change.

What Namespaces are not

Namespaces are not the same as separate clusters.

They do not automatically provide:

  • Strong network isolation
  • Separate node pools
  • Separate administrators
  • Separate etcd databases
  • Automatic security boundaries
  • Automatic resource limits

Those controls require additional configuration.

Field note: Treat Namespaces as an organization and policy scope. Do not assume they isolate workloads unless you have configured the controls that make isolation real.

Namespace-scoped vs cluster-scoped resources

Many Kubernetes resources live inside a Namespace.

Namespace-scoped resources include:

  • Pods
  • Deployments
  • ReplicaSets
  • Services
  • ConfigMaps
  • Secrets
  • Ingress resources

Some resources are cluster-scoped and do not belong to a single Namespace.

Cluster-scoped resources include:

  • Nodes
  • Namespaces
  • PersistentVolumes
  • ClusterRoles
  • ClusterRoleBindings
  • StorageClasses

This matters because some commands need a Namespace and others do not.

Before you start the lab

This lab assumes:

  • Docker Desktop is running
  • Your kind cluster exists
  • kubectl is installed
  • Your current context is kind-stealth-k8s-lab

Check your context:

kubectl config current-context

You should see:

kind-stealth-k8s-lab

Check your node:

kubectl get nodes

If your cluster no longer exists, recreate it:

kind create cluster --name stealth-k8s-lab

Step 1: List existing Namespaces

Run:

kubectl get namespaces

You will usually see Namespaces like:

default
kube-node-lease
kube-public
kube-system
local-path-storage

What these are

  • default: The default place for resources if you do not specify a Namespace.
  • kube-system: System components often run here.
  • kube-public: A Namespace intended for publicly readable cluster information.
  • kube-node-lease: Used for node heartbeat lease objects.
  • local-path-storage: Often present in kind for local storage support.

Step 2: See resources across all Namespaces

Run:

kubectl get pods -A

The -A flag means all Namespaces.

You can also run:

kubectl get services -A
kubectl get deployments -A

This is useful when you are not sure where something exists.

Field note: If you cannot find a resource, check whether you are looking in the wrong Namespace before assuming it does not exist.

Step 3: Create a Namespace

Create a Namespace for this lab:

kubectl create namespace training-lab

Confirm it exists:

kubectl get namespaces

You should see training-lab in the list.

Step 4: Create a Deployment in the Namespace

Create a Deployment inside the training-lab Namespace:

kubectl create deployment namespace-web-lab --image=nginx:latest -n training-lab

The -n flag means Namespace.

Check Deployments in the default Namespace:

kubectl get deployments

You should not see namespace-web-lab there.

Now check the training-lab Namespace:

kubectl get deployments -n training-lab

You should see the Deployment.

Step 5: Check Pods in the Namespace

Run:

kubectl get pods -n training-lab

You should see the Pod created by the Deployment.

You can also check across all Namespaces:

kubectl get pods -A

Now you should see the Pod listed under the training-lab Namespace.

Step 6: Create a Service in the Namespace

Expose the Deployment with a Service inside the same Namespace:

kubectl expose deployment namespace-web-lab --port=80 --target-port=80 --type=ClusterIP -n training-lab

Check Services in the Namespace:

kubectl get services -n training-lab

Check endpoints:

kubectl get endpoints -n training-lab

You should see endpoints for the Service.

Step 7: Port-forward to the Service in the Namespace

Run:

kubectl port-forward -n training-lab service/namespace-web-lab 8080:80

Keep that PowerShell window open. Then open a browser and go to:

http://localhost:8080

You should see the nginx welcome page.

Press Ctrl+C in PowerShell to stop port-forwarding.

Step 8: Create the same resource name in another Namespace

Create another Namespace:

kubectl create namespace training-lab-2

Now create another Deployment with the same name, but in the second Namespace:

kubectl create deployment namespace-web-lab --image=httpd:latest -n training-lab-2

This works because resource names only need to be unique within the same Namespace.

Check both:

kubectl get deployments -n training-lab
kubectl get deployments -n training-lab-2

Both Namespaces can have a Deployment named namespace-web-lab.

Field note: A resource name plus Namespace identifies most workload resources. That is why the same application name can exist in dev, test, and prod Namespaces.

Step 9: Use a Namespace in YAML

You can specify a Namespace in a resource manifest.

Create a file named:

namespace-configmap-lab.yaml

Paste this into the file:

apiVersion: v1
kind: ConfigMap
metadata:
  name: namespace-config-lab
  namespace: training-lab
data:
  APP_MODE: namespace-training
  LOG_LEVEL: info

Apply it:

kubectl apply -f namespace-configmap-lab.yaml

Check ConfigMaps in the default Namespace:

kubectl get configmaps

You should not see it there.

Check ConfigMaps in training-lab:

kubectl get configmaps -n training-lab

You should see namespace-config-lab.

Step 10: Set the default Namespace for your current context

Typing -n training-lab repeatedly can get annoying. You can set the default Namespace for your current kubectl context:

kubectl config set-context --current --namespace=training-lab

Now run:

kubectl get pods
kubectl get services
kubectl get configmaps

kubectl will use training-lab by default for namespace-scoped resources.

Confirm the current Namespace

Run:

kubectl config view --minify --output 'jsonpath={..namespace}'

You should see:

training-lab

Step 11: Reset the default Namespace back to default

Before we finish, set your current context back to the default Namespace:

kubectl config set-context --current --namespace=default

Confirm:

kubectl config view --minify --output 'jsonpath={..namespace}'

You should see:

default
Field note: Setting a default Namespace is convenient, but it can also confuse you if you forget it is set. When troubleshooting, always verify context and Namespace.

Step 12: Understand service DNS across Namespaces

Kubernetes provides DNS names for Services.

Inside the same Namespace, a workload can usually reach a Service by short name:

namespace-web-lab

From another Namespace, it is safer to use a more complete name:

namespace-web-lab.training-lab.svc.cluster.local

The pattern is:

<service-name>.<namespace>.svc.cluster.local

You do not need to memorize every DNS detail right now. The key idea is that Namespace affects service discovery.

Step 13: Describe a Namespace

Run:

kubectl describe namespace training-lab

You may see labels, annotations, and status information. Later, when we cover quotas and policies, this view becomes more useful.

Step 14: Delete a Namespace and everything inside it

Deleting a Namespace deletes the namespace-scoped resources inside it.

Delete the first lab Namespace:

kubectl delete namespace training-lab

Delete the second lab Namespace:

kubectl delete namespace training-lab-2

Check Namespaces:

kubectl get namespaces

It may take a little time for the Namespaces to fully terminate.

Why this is useful

Namespaces are convenient for labs because you can place all related resources into a Namespace and then delete the Namespace to clean up most of the lab.

Field note: Namespace deletion is powerful. In a real environment, deleting the wrong Namespace can remove many resources at once.

Common Namespace troubleshooting commands

Use this flow when you cannot find a resource or suspect you are looking in the wrong place:

kubectl config current-context
kubectl config view --minify --output 'jsonpath={..namespace}'
kubectl get namespaces
kubectl get pods
kubectl get pods -A
kubectl get deployments -A
kubectl get services -A
kubectl get configmaps -A
kubectl describe namespace <namespace-name>

This usually tells you:

  • Which cluster kubectl is pointed at
  • Which Namespace kubectl uses by default
  • Whether the Namespace exists
  • Whether the resource exists in another Namespace
  • Whether you accidentally created something in default

Common Namespace mistakes

Looking only in default

If you run kubectl get pods without a Namespace, you may only see resources in your current default Namespace.

Forgetting the current default Namespace was changed

If you set a default Namespace for your context, kubectl will keep using it until you change it again.

Assuming Namespaces provide full isolation

Namespaces organize resources, but security isolation requires additional controls.

Deleting the wrong Namespace

Deleting a Namespace can delete many resources at once. Be careful in shared or production clusters.

Where Namespaces fit in real environments

In real clusters, Namespaces are often paired with:

  • RBAC: Controls who can do what inside a Namespace.
  • ResourceQuotas: Limit how much CPU, memory, or object count a Namespace can consume.
  • LimitRanges: Apply default or maximum resource limits.
  • NetworkPolicies: Control allowed network traffic.
  • Pod Security Standards: Restrict risky Pod behavior.
  • Admission policies: Enforce cluster rules when resources are created or updated.

We will cover these later. For now, focus on how Namespaces organize resources and affect kubectl commands.

What you just learned

In this lesson, you:

  • Listed existing Namespaces
  • Viewed resources across all Namespaces
  • Created Namespaces
  • Created Deployments and Services inside specific Namespaces
  • Created duplicate resource names in different Namespaces
  • Used Namespace metadata in YAML
  • Changed the default Namespace for your current context
  • Reset the default Namespace back to default
  • Learned how Namespace affects Service DNS
  • Deleted Namespaces to clean up lab resources
Bottom line: Namespaces help organize Kubernetes resources. They make clusters easier to manage, but they are not complete security boundaries unless combined with policy, RBAC, network controls, and resource governance.

Check your understanding

Use these questions to test whether the Namespace concepts made sense.

  1. What does a Namespace do in Kubernetes?
  2. Can two different Namespaces contain resources with the same name?
  3. What flag tells kubectl which Namespace to use?
  4. What does -A mean in kubectl get pods -A?
  5. Name two resources that are usually namespace-scoped.
  6. Name two resources that are cluster-scoped.
  7. Why can deleting a Namespace be dangerous?
  8. What command sets the default Namespace for the current context?
  9. Why should you reset your default Namespace after a lab?
  10. What is the full DNS pattern for a Service across Namespaces?
  11. Are Namespaces complete security boundaries by themselves?
  12. What are three controls commonly paired with Namespaces in real environments?
Answer key
  1. A Namespace logically groups Kubernetes resources inside a cluster.
  2. Yes, as long as the resources are in different Namespaces.
  3. -n or --namespace.
  4. All Namespaces.
  5. Examples: Pods, Deployments, Services, ConfigMaps, Secrets, Ingress resources.
  6. Examples: Nodes, Namespaces, PersistentVolumes, ClusterRoles, ClusterRoleBindings, StorageClasses.
  7. Because deleting a Namespace deletes the namespace-scoped resources inside it.
  8. kubectl config set-context --current --namespace=<namespace-name>.
  9. To avoid accidentally running future commands in the wrong Namespace.
  10. <service-name>.<namespace>.svc.cluster.local.
  11. No. They need additional controls to act as meaningful security boundaries.
  12. Examples: RBAC, ResourceQuotas, LimitRanges, NetworkPolicies, Pod Security Standards, and admission policies.
← Previous: Ingress Series index Next: Resource Requests and Limits →