Introduction
kubectl label selectors do not provide a general-purpose OR operator. The important distinction is that Kubernetes supports OR-like matching for multiple values of the same key through set-based selectors, but it does not let you express arbitrary OR conditions across different keys in one plain selector string.
Comma-Separated Selectors Are Always AND
This is the first rule to remember:
kubectl get pods -l app=web,env=production
That means:
app=web AND env=production
Many people expect commas to act like a loose list of alternatives. In label selectors they do not. They add more requirements.
Use in (...) For OR On One Key
If the OR logic is "this key can have one of these values," use a set-based selector with in.
kubectl get pods -l 'env in (staging, production)'
kubectl get pods -l 'app in (web, api, worker)'
This is the Kubernetes-supported way to express:
env=staging OR env=production
You can still combine that with AND logic:
kubectl get pods -l 'app in (web, api),tier=frontend'
That means:
(app=web OR app=api) AND tier=frontend
There Is No Single Selector For OR Across Different Keys
The tricky case is something like:
There is no single -l selector expression for that across different keys. The common workarounds are:
run separate kubectl queries and merge the results
fetch a wider result set and filter with jq
design labels so the OR condition becomes one key with multiple acceptable values
For example, separate queries:
{ kubectl get pods -l app=web -o name; kubectl get pods -l env=staging -o name; } | sort -u
Or JSON filtering:
kubectl get pods -o json | jq -r '.items[]
| select(.metadata.labels.app == "web" or .metadata.labels.env == "staging") | .metadata.name' ``` Those are not as elegant as a native selector, but they are the honest answer when the condition spans different label keys. ## YAML Selectors Follow The Same Idea In workload manifests, set-based matching is expressed with `matchExpressions`. ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: web-deployment spec: selector: matchExpressions: - key: env operator: In values: - staging - production template: metadata: labels: env: production ``` This supports OR across values of the same key. It does not magically introduce arbitrary boolean expressions across unrelated keys either. Another subtle point: not every Kubernetes object supports the same selector syntax. For example, a Service `spec.selector` is much simpler and does not use the same `matchExpressions` structure. ## Quote The Selector In The Shell Set-based selectors contain parentheses, commas, and spaces. Quote them so the shell does not try to interpret those characters first. ```bash kubectl get pods -l 'app in (web, api)' ``` This is a small detail, but it is a very common reason people think the selector syntax itself is broken. ## Common Pitfalls - Expecting commas in `-l` to mean OR instead of AND. - Forgetting that `in (...)` only gives OR behavior for multiple values of the same key. - Trying to express OR across different keys in one plain label selector. - Forgetting shell quotes around set-based selectors. - Assuming every Kubernetes selector field in YAML supports the same syntax and operators. ## Summary - Use `key in (value1, value2)` when the OR condition is multiple values of one label key. - Comma-separated label requirements are always AND. - For OR across different keys, combine multiple queries or post-filter a broader result set. - In manifests, use `matchExpressions` where the resource type supports set-based selectors.