Kubernetes
OR selector
labels
container orchestration
DevOps

How can the OR selector be used with labels in Kubernetes?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Kubernetes label selectors support OR logic within a single label key using set-based selectors with the In operator. For example, app in (frontend, backend) matches resources where the app label is either frontend or backend. However, there is no native OR across different label keys — multiple selector conditions are always AND-ed together. To achieve cross-key OR logic, you must use multiple queries and merge the results, or use a workaround like adding a grouping label. This article covers how to use set-based selectors for OR behavior and the workarounds for cases the native syntax cannot handle.

Label Selector Types

Kubernetes has two types of selectors:

Equality-Based Selectors

bash
1# Exact match (AND only)
2kubectl get pods -l app=frontend
3kubectl get pods -l app=frontend,env=production   # AND: both must match
4kubectl get pods -l 'app!=backend'                 # Not equal

Set-Based Selectors

bash
1# OR within a single key — matches frontend OR backend
2kubectl get pods -l 'app in (frontend, backend)'
3
4# NOT in a set
5kubectl get pods -l 'app notin (test, staging)'
6
7# Key exists
8kubectl get pods -l 'app'
9
10# Key does not exist
11kubectl get pods -l '!app'

The In operator is how you achieve OR logic for a single label key.

OR Within a Single Key

kubectl Examples

bash
1# Pods where env is staging OR production
2kubectl get pods -l 'env in (staging, production)'
3
4# Services where tier is frontend OR api
5kubectl get svc -l 'tier in (frontend, api)'
6
7# Deployments where version is v1, v2, or v3
8kubectl get deployments -l 'version in (v1, v2, v3)'

In YAML Manifests (set-based)

yaml
1# Service that targets pods with app=frontend OR app=backend
2apiVersion: v1
3kind: Service
4metadata:
5  name: combined-service
6spec:
7  selector:
8    # Note: Service spec.selector only supports equality-based
9    # Use matchLabels for equality
10    app: frontend
11  ports:
12    - port: 80
13---
14# Deployment with set-based selector
15apiVersion: apps/v1
16kind: Deployment
17metadata:
18  name: my-deployment
19spec:
20  selector:
21    matchExpressions:
22      - key: app
23        operator: In
24        values:
25          - frontend
26          - backend
27  template:
28    metadata:
29      labels:
30        app: frontend
31    spec:
32      containers:
33        - name: app
34          image: nginx

NetworkPolicy Example

yaml
1apiVersion: networking.k8s.io/v1
2kind: NetworkPolicy
3metadata:
4  name: allow-web-traffic
5spec:
6  podSelector:
7    matchExpressions:
8      - key: role
9        operator: In
10        values:
11          - web
12          - api
13  ingress:
14    - from:
15        - podSelector:
16            matchExpressions:
17              - key: tier
18                operator: In
19                values:
20                  - frontend
21                  - loadbalancer
22      ports:
23        - port: 80

Combining AND and OR

Multiple selector expressions are AND-ed together. Each expression can have OR logic within it using In:

bash
# (env is staging OR production) AND (tier is frontend OR api)
kubectl get pods -l 'env in (staging, production), tier in (frontend, api)'
yaml
1spec:
2  selector:
3    matchExpressions:
4      # These are AND-ed together
5      - key: env
6        operator: In
7        values: [staging, production]     # OR within env
8      - key: tier
9        operator: In
10        values: [frontend, api]           # OR within tier
11      - key: version
12        operator: NotIn
13        values: [deprecated]              # AND exclude deprecated

This selects pods where env is (staging OR production) AND tier is (frontend OR api) AND version is NOT deprecated.

Cross-Key OR (Workarounds)

Kubernetes does not support OR across different keys natively. For example, you cannot directly say "app=frontend OR tier=web" in a single selector.

Workaround 1: Multiple Queries

bash
1# Get pods matching app=frontend
2kubectl get pods -l 'app=frontend' -o name > /tmp/set1.txt
3
4# Get pods matching tier=web
5kubectl get pods -l 'tier=web' -o name >> /tmp/set1.txt
6
7# Combine and deduplicate
8sort -u /tmp/set1.txt

Or using a single command:

bash
1# Union of two selectors
2kubectl get pods -l 'app=frontend' -o name | sort > /tmp/a
3kubectl get pods -l 'tier=web' -o name | sort > /tmp/b
4sort -u /tmp/a /tmp/b

Workaround 2: Add a Grouping Label

Add a common label to all resources that should match your OR condition:

yaml
1# Pod 1: frontend app
2metadata:
3  labels:
4    app: frontend
5    group: web-tier    # Grouping label
6
7# Pod 2: web tier (different app)
8metadata:
9  labels:
10    tier: web
11    group: web-tier    # Same grouping label
12
13# Now select both with a single query
14# kubectl get pods -l group=web-tier

Workaround 3: Use the Kubernetes API Directly

bash
1# Use the API with multiple label selectors (still AND within each call)
2# Get union programmatically
3kubectl get pods -l 'app=frontend' -o json > /tmp/frontend.json
4kubectl get pods -l 'tier=web' -o json > /tmp/web.json
5
6# Merge with jq
7jq -s '.[0].items + .[1].items | unique_by(.metadata.name)' \
8    /tmp/frontend.json /tmp/web.json

Operator Reference

OperatorMeaningExample
InValue is in set (OR)app in (a, b, c)
NotInValue is not in setenv notin (test)
ExistsKey exists (any value)key: app, operator: Exists
DoesNotExistKey does not existkey: legacy, operator: DoesNotExist

Common Pitfalls

  • Expecting OR across different label keys: Multiple selector conditions are always AND-ed. kubectl get pods -l 'app=frontend,tier=web' means app=frontend AND tier=web, not OR. Use In within a single key for OR logic, or run separate queries.
  • Using set-based selectors in Service spec.selector: The Service spec.selector field only supports equality-based matching (matchLabels). Set-based selectors (matchExpressions with In) are supported in Deployments, ReplicaSets, Jobs, DaemonSets, and NetworkPolicies, but not in Services.
  • Forgetting quotes around set-based selectors in kubectl: kubectl get pods -l app in (frontend, backend) fails because the shell interprets parentheses. Always quote the selector: kubectl get pods -l 'app in (frontend, backend)'.
  • Mismatching selector and template labels: In a Deployment, spec.selector.matchExpressions must match the labels in spec.template.metadata.labels. If the template labels do not satisfy the selector, the Deployment fails to create pods.
  • Assuming label changes propagate to selectors: Changing a pod's labels after creation causes it to fall out of any Deployment or Service selector that no longer matches. The controller may create a new pod to replace it, leaving the relabeled pod orphaned.

Summary

  • Use In operator for OR logic within a single label key: app in (frontend, backend)
  • Multiple selector conditions are always AND-ed — there is no native cross-key OR
  • Set-based selectors (matchExpressions) support In, NotIn, Exists, and DoesNotExist
  • For cross-key OR logic, use multiple queries and merge results, or add a common grouping label
  • Quote set-based selectors in kubectl commands to prevent shell interpretation of parentheses

Course illustration
Course illustration

All Rights Reserved.