Skip to main content
Course/Config & Health/Labels & Selectors
2/945 min
Config & Health

Labels & Selectors

Tag resources with key-value metadata and use selectors to wire Services, Deployments, and queries together.

beginner45 minRead β†’ Lab β†’ Quiz β†’ Practice
🧠 Brain Warm-Up
🧠 Brain Warm-Up: How does a Kubernetes Service dynamically find which Pods to route traffic to, and what low-level mechanism is updated on the worker nodes when a Pod's labels change?

What Are Labels?

Labels are key-value pairs attached to metadata fields in Kubernetes API objects. They are key to the design of Kubernetes, enabling loose coupling between resources. Instead of hardcoding relationships (e.g., pointing a Service to a specific Pod name), objects query other objects dynamically using labels.

metadata:
  labels:
    app: web
    tier: frontend
    env: production
    version: v2

Label keys have two optional parts: a prefix (up to 253 characters, domain-style) and a name (up to 63 characters). The Kubernetes community uses recommended keys prefixed with app.kubernetes.io/ (e.g., app.kubernetes.io/name, app.kubernetes.io/part-of).

Visualizing Service Selectors

  +---------------------+
  |   Service Object    |
  | selector: app=web   |
  +---------------------+
             |
             v (EndpointSlice Controller watches label changes via Informer)
  +---------------------+
  | EndpointSlice (EP)  | <--- Contains IPs: [10.244.1.5, 10.244.2.12]
  +---------------------+
             |
   +---------+---------+ (kube-proxy syncs to nodes)
   |                   |
   v                   v
+------------------+ +------------------+
|      Node 1      | |      Node 2      |
| iptables / IPVS  | | iptables / IPVS  |
| rules updated    | | rules updated    |
+------------------+ +------------------+
   | (routes traffic)  | (routes traffic)
   v                   v
+------------------+ +------------------+
| Pod: app=web     | | Pod: app=web     |
| IP: 10.244.1.5   | | IP: 10.244.2.12  |
+------------------+ +------------------+

The Reconcile Loop & Selectors

Under the hood, labels and selectors power the Reconcile Loop β€” the core control mechanism of Kubernetes.

  1. Informer Caches: Controllers (like the ReplicaSet controller or the EndpointSlice controller) run in the kube-controller-manager. They register a Watch on the kube-apiserver for specific resource types.
  2. Label Matching: When a new Pod is created or labeled, the EndpointSlice controller filters Pods using the label selector defined in a Service.
  3. Endpoint Propagation: The controller generates or updates an EndpointSlice object listing the IPs of all matching Pods.
  4. Data Plane Updates: kube-proxy running on every node watches the API server for changes to Services and EndpointSlices. Upon notification, it updates the node's packet-routing configuration:

- iptables mode: Updates chaining rules to randomly distribute connections across target Pod IPs using the statistic module.

- IPVS mode: Inserts entries into an in-kernel IPVS hash table, supporting faster routing and advanced load-balancing algorithms (e.g., least connections).

Labels vs Annotations

While both store key-value metadata, they have distinct roles:

FeatureLabelsAnnotations
Queryable/Selector-friendlyYes (via label selectors in API queries and manifests)No (cannot be used to filter resources in API requests)
Character LimitsMax 63 characters for keys/values, strict alphanumeric formatNo strict length limits (can store large strings like JSON)
Primary Use CasesDynamic grouping, Service targeting, scheduling constraints (NodeSelector)CI/CD metadata (git hash, build ID), tool config (Ingress controllers, annotations for cert-manager)

Orphaned Pods

If you modify a Pod's labels such that they no longer match a Deployment's replica selector, the Deployment's controller immediately detects that the actual state (N - 1 matching pods) does not match the desired state (N). It spins up a new Pod to restore the replica count. The original Pod remains running as an orphan, disconnected from both the Deployment's control loop and the Service's traffic routing.

Querying With kubectl

# Equality-based
kubectl get pods -l app=web
kubectl get pods -l app=web,tier=frontend

# Set-based (comma = AND)
kubectl get pods -l 'tier in (frontend,backend)'
kubectl get pods -l 'env notin (staging)'