A label is a key-value pair in metadata.labels used to identify and group objects. Labels are not unique: many pods can share app: web.
metadata:
name: web-7f9c
labels:
app: web
environment: production
tier: frontend
A selector picks objects by label. Services, ReplicaSets and Deployments all use selectors to know which pods are "theirs".
flowchart LR S["Service web<br/>selector: app=web"] --> P1["pod app=web"] S --> P2["pod app=web"] S -.-x P3["pod app=api"]
- Equality-based:
app=web,environment!=dev. - Set-based:
'environment in (dev,staging)','!canary'.
nodeSelector
A pod picks nodes by node labels with nodeSelector. It is a map, not a list:
spec:
nodeSelector:
disk: ssd
Commands
| Command | Meaning |
|---|---|
kubectl get pods -l app=web |
Filter pods labelled app=web |
kubectl get pods -L environment |
Add a column showing label environment |
kubectl label pod web tier=frontend |
Add a label |
kubectl label pod web env=prod --overwrite |
Change an existing label |
kubectl label nodes worker-1 disk=ssd |
Label a node |
Mixing up -l (filter) and -L (add column) is a common mistake. A Service without endpoints is usually a selector/label mismatch (app: web vs app: Web).
Recommended labels
Kubernetes suggests a common set so tools and people can understand any app:
| Label | Example |
|---|---|
app.kubernetes.io/name |
shop |
app.kubernetes.io/instance |
shop-prod |
app.kubernetes.io/version |
1.4.2 |
app.kubernetes.io/component |
api |
app.kubernetes.io/part-of |
online-store |
app.kubernetes.io/managed-by |
Helm |
Label keys may have a DNS prefix (example.com/team) and a name of up to 63 characters; values are also limited to 63 characters of letters, digits, -, _, and ..
Labels versus annotations
Labels are for selecting and grouping, so keep them short and stable. Annotations hold non-identifying data that tools read, such as a Git commit, a build URL, or ingress controller settings, and can be much longer. You cannot select objects by annotation.
Selectors that must not change
A Deployment's spec.selector is immutable after creation, and it must match the labels in its pod template. Changing labels in the template without matching the selector is rejected; changing the selector requires recreating the Deployment. Plan labels before the first release.
Placing pods with affinity
nodeSelector is the simple form. Node affinity adds preferences and operators, and pod anti-affinity spreads replicas:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector: { matchLabels: { app: web } }
topologyKey: kubernetes.io/hostname
This asks the scheduler to avoid putting two web pods on the same node.
Field selectors
Besides labels, some built-in fields can filter results: kubectl get pods --field-selector status.phase=Running or --field-selector spec.nodeName=worker-1. Labels also enable simple release tricks: a Service that selects app: web sends traffic to both track: stable and track: canary pods, while a second Service can target only the canary.