Skip to main content

Command Palette

Search for a command to run...

Day 3 - Kubernetes Without The Tears

Labels, Selectors, and Namespaces

Updated
5 min read
Day 3 - Kubernetes Without The Tears
T
TJ Gokken is an AI Systems Architect with a passion for bridging the gap between technology and practical application. Specializing in .NET frameworks and machine learning, TJ helps software teams operationalize AI to drive innovation and efficiency. With over two decades of experience in programming and technology integration, he is a trusted advisor and thought leader in the AI community.

It’s only Day3, and we have already got our first Kubernetes app running. We've seen pods in action. We even watched Kubernetes replace a deleted one like it was no big deal.

Now it’s time to talk about something that keeps things from turning into a complete mess when your cluster grows: labels, selectors, and namespaces. It is all about organizing after all - I think. So far, it served me well.


Under the Hood

As your cluster scales from one deployment to dozens (or hundreds), you're going to need a way to find, group, and manage things. Enter labels and namespaces. As developers, we are accustomed to namespaces. Labels, though, are a new concept - especially if you are coming from the C# world. These labels are not the <label> tags we are used to.

So, let’s take a look at the labels first.

Labels: The Sticky Notes of Kubernetes

Labels are key-value pairs you can stick on just about anything—pods, services, deployments, you name it.

Here’s how they look:

labels:
  app: nginx
  env: dev
  tier: frontend

And yes, you are right. Pair having 3 properties? You see, even though the name says "pair," you can have as many of them as you want on a single resource. Think of each key-value pair as a little colored sticky note: one might say "env=dev", another might say "tier=frontend", and so on.

These aren’t just decorative—they’re how Kubernetes (and you) find stuff. You’ll use them in selectors (just keep reading, it’s coming up) to say, “Hey, give me all the pods with app=nginx.”

You can label everything consistently, however you like. But the convention is usually things like app, env, tier, version, etc.

Selectors: The Find Button

Selectors are how you query resources based on their labels.

Remember the YAML file we created yesterday?

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

Yes that one. We’ve actually already used one in that file:

selector:
  matchLabels:
    app: nginx

That told the deployment, “Only manage pods with the label app=nginx.”

How does that help and why does it matter? Because it gives you control. You can have multiple pods running different apps, and the deployment won’t touch the wrong ones. It’s like saying, “This flight schedule is only for the planes marked 'nginx'—ignore the rest.” It keeps things tidy, scoped, and safe.

You can also use selectors in the CLI:

kubectl get pods -l app=nginx
kubectl get pods -l env=dev

Or even combine them:

kubectl get pods -l 'app=nginx,tier=frontend'

Namespaces: Your Cluster’s Neighborhoods

As developers, we are accustomed to namespaces, but let’s go through them in the context of K8s.

In K8s, everything lives in the default namespace by default (pun intended) but Kubernetes lets you split things into different namespaces so your dev, staging, and prod stuff don’t bump into each other.

You can also use them to separate teams, apps, or projects. Each namespace has its own set of resources—like a sandbox.

Let’s go through some of the most common commands regarding namespaces:

ActionCommand
See all namespaceskubectl get namespaces
Create a new namespacekubectl create namespace mynamespace
Run a file in a namespacekubectl apply -f your-file.yaml -n mynamespace
Target a namespace with CLIkubectl get pods -n mynamespace

When you create a new namespace, you are basically saying “Hey Kubernetes, set up a new mini-world called mynamespace where I can deploy stuff without cluttering the default space.”

I know what you’re thinking: Running the command to get the namespaces can get old very fast, isn’t there a way where I can manage these namespaces easier?

Once you have a bunch of namespaces, you can keep track of what you’re working in by setting a default context or organizing your configs by project. We’ll cover that in a future article, but for now we are working with simple namespaces and kubectl get namespaces is our best friend. But we will get there, I promise.

Lab: Organize Your Resources

Let’s put what we learnt to use and make a new namespace, label something, and practice filtering.

Step 1: Create a new namespace

kubectl create namespace dev-space

Step 2: Re-deploy nginx into it

Copy your previous YAML file and add this to the metadata section:

metadata:
  name: nginx-deployment
  namespace: dev-space

Then apply it:

kubectl apply -f nginx-deployment.yaml

Step 3: Add more labels

Edit your deployment YAML and add this under labels:

  labels:
    app: nginx
    env: dev
    tier: frontend

Your final YAML file should look like below:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: dev-space
  labels:
    app: nginx
    env: dev
    tier: frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        env: dev
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

Then, finally re-apply it:

kubectl apply -f nginx-deployment.yaml

Step 4: Filter like a pro

Try these:

kubectl get pods -n dev-space -l app=nginx
kubectl get pods -n dev-space -l "env=dev,tier=frontend"

Now you’ve got your app running in its own namespace, with labels that make it easy to find and group. These commands above will give you the list of the pods running filtered by your params. Go ahead and change one of the filters by adding a typo to the filter, such as kubectl get pods -n dev-space -l app=nginx1, and you will see that you will get nothing.

Tomorrow we’ll look at how to handle config and secrets the right way.

We’re building the muscle memory now—one YAML file at a time.

Kubernetes Without The Tears

Part 6 of 8

A dev-friendly crash course you can finish before burnout kicks in.

Up next

Day 2 - Kubernetes Without The Tears

Pods, Deployments, and Services