Kubernetes labels and selectors explained (the glue between objects)
Labels and selectors in Kubernetes: how Deployments label Pods, how Services find them, kubectl -l and endpoints checks, common mistakes, and optional kprompt examples.
You already know Pods, Deployments, and Services — see Pods vs Deployments and Services if you need a refresher. Namespaces scope where objects live. Labels and selectors are how Kubernetes connects those objects: which Pods belong to a Deployment, and which Pods a Service sends traffic to.
This guide explains labels on Pods and Deployments, selectors on Services, the kubectl commands that make the link visible, and the mistakes that leave Endpoints empty even when everything looks Running.
The one-sentence version
- A label is key/value metadata on an object (for example app: api).
- A selector is a filter: “give me objects with these labels.”
- Deployment Pod template labels must match the Service selector — or traffic never reaches your Pods.
What is a label?
Labels are arbitrary key/value pairs attached to Kubernetes objects. They do not change how a container runs by themselves — they organize and select objects. Controllers, Services, and kubectl -l all rely on them.
Labels on a Pod (metadata.labels)
apiVersion: v1
kind: Pod
metadata:
name: api-manual
labels:
app: api
tier: backend
env: staging
spec:
containers:
- name: api
image: nginx:1.27On a Deployment, labels appear in two places beginners confuse: metadata.labels on the Deployment object itself (optional, for your own organization) and spec.template.metadata.labels on the Pod template (required for Services to target the Pods the Deployment creates).
What is a selector?
A selector is a label query. A Service uses spec.selector to decide which Pods receive traffic. kubectl uses -l the same way. ReplicaSets (owned by Deployments) also use selectors to know which Pods they own.
Service selector must match Pod labels
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api # must match Pod template labels
ports:
- port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 2
selector:
matchLabels:
app: api # ReplicaSet watches Pods with this label
template:
metadata:
labels:
app: api # Pods get this label — Service must match here
spec:
containers:
- name: api
image: nginx:1.27
ports:
- containerPort: 8080How Deployment and Service connect
The mental model from Service vs Deployment still applies: the Deployment keeps Pods alive; the Service gives them a stable address. Labels are the wire between them. Scale the Deployment and new Pods inherit template labels — the Service picks them up automatically.
Mental model
Deployment "api"
└── Pod template labels: app=api
├── Pod api-7f8c9d-xk2lm labels: app=api
└── Pod api-7f8c9d-mn4pq labels: app=api
Service "api" selector: app=api
│
└── Endpoints → both Pod IPskubectl commands that stick
These four commands are the beginner debugging loop for “Service exists but nothing works.” Run them in order before you change YAML.
See labels, selectors, and Endpoints
# 1) What labels do my Pods have?
kubectl get pods -n staging --show-labels
kubectl get pods -l app=api -n staging
# 2) What does the Service select?
kubectl get svc api -n staging -o yaml | grep -A3 selector
# 3) Which Pod IPs are registered?
kubectl get endpoints api -n staging
kubectl get endpointslices -l kubernetes.io/service.name=api -n staging
# 4) Do Pod labels match the Service selector?
kubectl get pods -n staging -l app=api --show-labels
kubectl describe svc api -n stagingReading Endpoints output
Endpoints (or EndpointSlices) list the Pod IPs behind a Service. If ADDRESSES is empty or <none>, the Service selector did not match any Pod — even if kubectl get pods shows Running Pods with a similar name.
Healthy vs broken
# Healthy — Pod IPs listed
NAME ENDPOINTS AGE
api 10.244.1.12:8080,10.244.2.8:8080 5m
# Broken — selector mismatch (very common)
NAME ENDPOINTS AGE
api <none> 5mmatchLabels vs matchExpressions (beginner view)
- matchLabels — equality only (app: api). Enough for most apps.
- matchExpressions — In, NotIn, Exists, DoesNotExist for advanced filtering.
- Beginners: make Deployment template labels and Service selector identical with matchLabels first.
matchExpressions example (optional)
selector:
matchExpressions:
- key: app
operator: In
values:
- api
- api-canaryCommon beginner mistakes
- Labels on the Deployment metadata but not on spec.template.metadata.labels — Service cannot see them on Pods
- Typo: app: api on Pods but app:api or app: Api on the Service selector (labels are case-sensitive)
- Changing the Service name and assuming DNS follows Pod names — clients dial the Service name; labels do the matching
- Running Pods from an old ReplicaSet after a label change — Endpoints update only for Pods that still match
- Using kubectl get pods without -l and missing that the Running Pod has different labels than you think
When labels matter beyond Services
- kubectl logs and exec with -l app=api — target the right Pod among replicas
- NetworkPolicy and some Ingress controllers select workloads by labels
- Prometheus ServiceMonitor and Helm charts often assume standard labels like app.kubernetes.io/name
Same checks in natural language (optional)
kprompt resolves label phrases in read prompts. Mutations still show a plan and ask for approval on a TTY.
Soft kprompt examples
kprompt "list pods with label app=api in staging"
kprompt "describe service api in staging"
kprompt "get endpoints for api in staging"
kprompt "explain why service api has no endpoints in staging"What to learn next
Labels connect Deployments to Services. Next, configure apps with ConfigMaps and Secrets (env vars and mounted files). For deeper kubectl reading, see kubectl get pods explained and the troubleshooting guides when Pods misbehave.
Related posts
Kubernetes Service vs Deployment: roles, not rivals
Service vs Deployment in Kubernetes: Deployments run and update Pods; Services give those Pods a stable network identity. When you need each, how they connect via labels, and kubectl checks that stick.
Read articleWhat is a Kubernetes Service? A beginner guide to stable networking
Why Pod IPs are not enough, what a Service does, ClusterIP vs NodePort vs LoadBalancer, selectors and Endpoints, kubectl commands, and optional natural-language checks with kprompt.
Read articlekubectl get pods explained: STATUS, restarts, and next commands
How to read kubectl get pods output — READY, STATUS, RESTARTS, AGE — what CrashLoopBackOff and Pending mean, and which kubectl command to run next.
Read article