skip to content

In Kubernetes, what are labels, and how do equality-based and set-based label selectors decide which objects match?

level: juniorimportance: must knowfreq 74%

answer

  1. identifying metadata, not description
  2. requirements are ANDed
  3. 63-character name and value
  4. notin also matches missing keys
  5. matchLabels plus matchExpressions

basics

~20 s

Kubernetes labels are key/value pairs on an object's metadata. A label selector lists requirements, all of which must match: equality (=, !=) or set-based (in, notin, exists). Services, ReplicaSets and kubectl use selectors to find objects.

solid answer

~40 s

Labels are identifying key/value pairs in `metadata.labels`. The key is an optional DNS-subdomain prefix plus a name of up to 63 characters, and the value is up to 63 characters. A **selector** is a list of requirements that are always ANDed, and it only matches objects in its own namespace. Equality-based requirements are `key=value` and `key!=value`. Set-based requirements are `key in (a,b)`, `key notin (a)`, `key` and `!key`. Note that `!=` and `notin` also match objects that lack the key. In manifests, Deployments and similar objects use `matchLabels` (equality) plus `matchExpressions` with `In`, `NotIn`, `Exists` or `DoesNotExist`, while a Service's `spec.selector` is a plain equality map. Day to day you use `kubectl get -l`, `--show-labels`, `-L` and `kubectl label` with `--overwrite` or `key-`.

code

bash · 3 lines
bash
kubectl get pods -n ledger -l 'app.kubernetes.io/name=ledger-reconciler,tier in (worker)' -L tier
kubectl get pods -n ledger -l 'tier,tier notin (batch)'
kubectl label pod ledger-worker-7f9c4 -n ledger tier=worker --overwrite

go deeper

for a junior

Know what a label is, the two selector styles, that requirements are ANDed, and how to use kubectl get -l, --show-labels and kubectl label.

for a middle

Explain matchLabels versus matchExpressions and the four operators, the key and value length rules, and why notin and != match objects without the key.

for a senior

Show you can find a selector mismatch quickly by comparing it with --show-labels, and that you keep selector labels small and stable across a shared cluster.

for a principal

Discuss a cluster-wide labelling convention built on the app.kubernetes.io keys, and how you would enforce it so 22 teams' tooling can rely on it.

## What a label is A **label** is a key/value pair stored in an object's `metadata.labels` map. Kubernetes attaches no meaning to most labels. They exist so that **one object can find a set of other objects** without naming each one. A Service finds its pods this way, a ReplicaSet counts its pods this way, and `kubectl get` filters by labels too. The rules for a label are strict: - The **key** has an optional prefix and a name, written `prefix/name`. The name is at most **63 characters**. The prefix, if present, is a DNS subdomain of at most **253 characters**, such as `app.kubernetes.io`. - The `kubernetes.io/` and `k8s.io/` prefixes are **reserved** for Kubernetes' own components. - The **value** is at most **63 characters** and may be empty. - Labels are meant to **identify** an object ("this is the ledger reconciler, the worker part, owned by team payments"). Other metadata that nothing selects on does not belong in labels. A common, tool-friendly set is the **recommended labels**: `app.kubernetes.io/name`, `app.kubernetes.io/instance`, `app.kubernetes.io/version`, `app.kubernetes.io/component`, `app.kubernetes.io/part-of` and `app.kubernetes.io/managed-by`. In a 140-node cluster shared by 22 product teams, agreeing on these keys means every team's dashboards and `kubectl` queries can use the same keys. ## What a selector does A **label selector** is a query over labels. It never looks at names, annotations or `spec` fields. A selector is a list of **requirements**, and an object matches only when it satisfies **every** requirement (logical AND). There is no OR across requirements. The nearest thing to OR is a set of values inside one `In` requirement. A selector only looks inside its own namespace. A Service or a Deployment in namespace `ledger` selects pods in `ledger`, never in another namespace. ## Equality-based vs set-based requirements | Form | Operators | Example | Matches an object with no such key? | |---|---|---|---| | Equality | `=`, `==` | `tier=worker` | No | | Inequality | `!=` | `tier!=worker` | **Yes** | | Set: membership | `in` | `env in (prod,staging)` | No | | Set: exclusion | `notin` | `tier notin (batch)` | **Yes** | | Set: existence | bare key | `team` | No | | Set: absence | `!key` | `!canary` | Yes | The two "Yes" rows in the middle of the table catch people out. `!=` and `notin` both match objects that **do not carry the key at all**. If you want "has a tier label, and it is not batch", write both requirements: `tier,tier notin (batch)`. ## Two places selectors are written 1. **Strings**, on the command line: `kubectl get pods -l 'app.kubernetes.io/name=ledger-reconciler,tier in (worker)'`. The `-l` flag is short for `--selector`. 2. **Structured fields** in manifests. Newer objects (Deployment, ReplicaSet, StatefulSet, DaemonSet, Job, PodDisruptionBudget) use a `LabelSelector` with two parts: - `matchLabels`: a map. Each entry is the same as an equality requirement. - `matchExpressions`: a list of `{key, operator, values}` entries. The operator is `In`, `NotIn`, `Exists` or `DoesNotExist`. `In` and `NotIn` need at least one value, and `Exists` and `DoesNotExist` must have no values. When both parts are set, **all of them are ANDed**. A Service's `spec.selector` is older and simpler: a plain map, so it supports **equality only**. ## Working with labels in kubectl ```bash # add a label; fails if the key already has a value kubectl label pod ledger-worker-7f9c4 team=payments # change an existing value kubectl label pod ledger-worker-7f9c4 team=ledger --overwrite # remove a label (trailing dash) kubectl label pod ledger-worker-7f9c4 team- # filter, show all labels, or show chosen labels as columns kubectl get pods -l 'team=ledger,tier in (worker)' kubectl get pods --show-labels kubectl get pods -L app.kubernetes.io/version,tier ``` ## Practical guidance - Use a **small, stable** set of labels in selectors, such as name and instance. Put things that change often, like version, in labels that nothing selects on. - Selectors match only labels. Kubernetes also has **field selectors** (`--field-selector status.phase=Running`), which are a separate mechanism with a much smaller set of supported fields. - When a selector seems to match nothing, compare it with `kubectl get pods --show-labels` first. A typo in a key or value simply matches nothing. It does not raise an error. - Label keys and values are case-sensitive, so `Tier=Worker` and `tier=worker` are different labels.

  • Can a Kubernetes label selector express OR between two different keys?
    No. A selector's requirements are always ANDed. OR exists only inside one set-based requirement, such as `env in (prod,staging)`, which matches any listed value for that single key. To get "team=a OR tier=b" you run two queries and merge the results, or add a shared label that both sets of objects carry and select on that.
  • Why do the Kubernetes recommended labels use the app.kubernetes.io/ prefix?
    The prefix places the keys in a shared, documented namespace so different tools and teams read them the same way: `name`, `instance`, `version`, `component`, `part-of` and `managed-by`. Unprefixed keys like `app` are treated as private to the user and can collide across teams. Prefixes under `kubernetes.io/` and `k8s.io/` are reserved for Kubernetes components.
  • How is a kubectl field selector different from a Kubernetes label selector?
    `--field-selector` filters on a small, per-resource set of object fields, such as `status.phase` or `spec.nodeName` for pods, and supports only `=`, `==` and `!=`. A label selector works only on `metadata.labels`, supports set-based operators and is what controllers use to find their objects. They are separate mechanisms.

Labels are like tags on library books and a selector is a catalogue search. The search returns every book whose tags satisfy all the conditions, whoever shelved it.

saying these in an interview costs you the question

  • Saying the requirements in a selector are ORed together
  • Believing tier!=batch excludes pods that have no tier label
  • Thinking a Service selector can use matchExpressions
  • Saying a selector can match pods in other namespaces
  • Treating labels as free-form notes for any metadata
  • Expecting a misspelled selector key to raise an error