๐ง Kubernetes ResourceQuota Deep Dive: scopeSelector and Beyond¶
๐ Introduction¶
ResourceQuota is a Kubernetes object that lets you limit resource consumption and object count within a namespace. It helps ensure fair usage and prevent abuse of cluster resources by controlling:
- Compute resources (CPU, memory)
- Storage (PVCs, ephemeral storage)
- Object count (pods, services, secrets, etc.)
This guide explains how quotas work, what scopeSelector does, and how to apply quotas on compute, storage, and object counts.
๐ก What Are requests and limits?¶
| Field | Meaning | Think of it as... |
|---|---|---|
request | Minimum guaranteed resource | Your reservation |
limit | Maximum allowed resource | Your ceiling / throttle cap |
๐ง What Happens:¶
- Kubernetes uses
requestsduring scheduling (i.e., finding a node). - Kubernetes uses
limitsduring runtime (i.e., restricting usage).
โ โRequest is the guaranteed minimum amount of resource Kubernetes will reserve for the container at scheduling time.โ
โ โLimit is the absolute maximum amount of resource the container is allowed to use at runtime. It cannot exceed this.โ
๐จ Real-World Analogy: Hotel Room¶
Imagine you're booking a hotel room with flexible budget.
- Request: You tell the hotel, โI need at least 1 room with 1 bed โ guaranteed.โ
- Limit: You say, โBut I wonโt pay for more than 2 beds โ cap it there.โ
Kubernetes does the same:
- It guarantees the container at least the resources specified in
request.- But if the container tries to use more than
limit, it's throttled or OOMKilled.
โ๏ธ In Terms of a Single Pod:¶
Letโs say your pod defines:
resources:
requests:
cpu: "500m"
limits:
cpu: "1000m"
- Scheduler finds a node with at least 500m free CPU.
- Pod is scheduled.
-
At runtime, the container can use up to 1000m, but no more.
-
If it tries more, it will be throttled (for CPU).
- If memory exceeds
limit, it can be OOMKilled.
โ Summary¶
| Concept | Request | Limit |
|---|---|---|
| Scheduler uses it? | โ Yes | โ No |
| Runtime enforces it? | โ No | โ Yes |
| Guarantees availability? | โ Yes | โ No |
| Defines max usage? | โ No | โ Yes |
| Term | Kubernetes Reserves | Container Can Use | Type |
|---|---|---|---|
| Request | โ Yes | โ At least this | Minimum (Guaranteed) |
| Limit | โ No | โ At most this | Maximum (Cap) |
๐งฎ Types of Resources You Can Limit¶
๐น 1. Compute Resources¶
hard:
requests.cpu: "4" # All pods in this namespace together can request up to 4 CPUs
limits.cpu: "8" # All pods can use up to 8 CPUs, but no more
requests.memory: 8Gi # All pods can request up to 8Gi memory
limits.memory: 16Gi # All pods cannot go over 16Gi usage
Meaning:¶
| Behavior | Effect |
|---|---|
| Scheduler behavior | Will only schedule pods if total requests of all pods โค 4 CPUs |
| Runtime behavior | All running pods cannot use more than 8 CPUs at once |
| Same logic applies for memory | Total requests.memory โค 8Gi and limits.memory โค 16Gi |
๐น 2. Storage Resources¶
hard:
requests.storage: 100Gi # Sum of PVC storage requests
persistentvolumeclaims: "10" # Max PVCs allowed
๐น 3. Object Count (Case Study: Limiting Number of Objects)¶
You can also limit how many objects can exist in a namespace.
hard:
pods: "20" # Max number of pods in the namespace
services: "5" # Max services
configmaps: "10" # Max configmaps
secrets: "15" # Max secrets
replicationcontrollers: "4"
services.nodeports: "2"
count/deployments.apps: "10"
๐ This example limits: - Total number of pods, secrets, configmaps, and PVCs. - Maximum number of NodePort services.
You can even combine them all in one quota.
โ
Guide: spec.hard in ResourceQuota¶
๐น Format 1: Basic Resource Consumption Limits (No requests. or limits. prefixes)¶
spec:
hard:
cpu: "2" # โ INVALID (Deprecated and usually ignored)
memory: 5Gi # โ INVALID (Deprecated and usually ignored)
pods: "10" # โ
Valid
services: "5" # โ
Valid
persistentvolumeclaims: "2" # โ
Valid
- โ
cpuandmemorywithout prefix (requests.orlimits.) are not valid anymore forResourceQuota. - โ
Object count quotas like
pods,services,configmaps, etc., are fully valid.
๐ Why not valid?
Since Kubernetes v1.2+, you must specify CPU and Memory with
requests.orlimits.prefixes insideResourceQuota. Barecpu/memoryfields are ignored or trigger validation errors.
๐น Format 2A: โ โ Flat Key Style (Canonical and Correct)¶
spec:
hard:
requests.cpu: "4"
limits.cpu: "8"
requests.memory: 8Gi
limits.memory: 16Gi
โ This is the only valid way to enforce compute resource quotas in Kubernetes.
- Uses flat key format like
requests.cpu,limits.memory - This is how Kubernetes parses and enforces CPU and memory quotas
๐น Format 2B: โ INVALID โ Nested Style¶
spec:
hard:
requests:
cpu: "4"
memory: 8Gi
limits:
cpu: "8"
memory: 16Gi
โ This is invalid YAML for ResourceQuota, even though it looks readable.
- Not supported by Kubernetes API.
- Will cause this error:
quantities must match the regular expression '^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$'
๐ Why not valid?
Kubernetes expects all keys inside
.spec.hardto be flat strings likerequests.cpu, not nested maps likerequests: { cpu: "4" }.
โ Valid Object Count Quotas¶
These are always allowed inside .spec.hard:
apiVersion: v1
kind: ResourceQuota
metadata:
name: abc
namespace: default
spec:
hard:
configmaps: "20"
count/deployments.apps: "10"
count/jobs.batch: "10"
count/replicasets.apps: "10"
count/statefulsets.apps: "10"
limits.cpu: "8"
limits.memory: 16Gi
persistentvolumeclaims: "10"
pods: "20"
replicationcontrollers: "4"
requests.cpu: "4"
requests.memory: 8Gi
requests.storage: 100Gi
secrets: "20"
services: "20"
services.nodeports: "2"
โ Summary Table (Corrected)¶
| Format Type | Example | Valid? | Why |
|---|---|---|---|
| Flat Resources | requests.cpu: "4", limits.memory: 16Gi | โ | Required format for compute resources |
| Nested Resources | requests: { cpu: "4" } | โ | Not valid YAML โ not parsed by API |
| Object Quotas | pods: "10", services: "5" | โ | Fully valid for object-count limits |
| Deprecated Bare CPU | cpu: "2", memory: "5Gi" | โ | Not valid โ must use requests/limits |
๐ก Recommendation¶
Always use flat key syntax for resource-based quotas:
requests.cpu: "4"
limits.memory: 16Gi
And avoid nesting under requests: or limits: in ResourceQuota YAMLs.
๐ Using scopes in ResourceQuota¶
The scopes field restricts the quota to apply only to a subset of objects:
| Scope | Description |
|---|---|
BestEffort | Applies only to pods without requests/limits |
NotBestEffort | Applies to pods with at least one request or limit |
Terminating | Applies to pods with active deadlines |
NotTerminating | Applies to pods without deadlines |
PriorityClass | Use only with scopeSelector (explained below) |
Example: Limit BestEffort Pods Only¶
spec:
hard:
pods: "5"
scopes:
- BestEffort
โ๏ธ Advanced Filtering with scopeSelector¶
scopeSelector allows more advanced filtering logic, similar to label selectors. Useful when applying quotas based on PriorityClass, etc.
Example: Apply only to pods in middle PriorityClass¶
Allows advanced filtering with matchExpressions:
spec:
hard:
pods: "10"
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values:
- middle
๐ง This is helpful when you want to limit resource consumption only for pods that belong to a specific priority class.
Not cleared about
scopeSelector? Click here for more info!
๐ ๏ธ CLI Equivalents: kubectl create quota¶
๐น --hard Flag¶
- Defines the resource limits
- Maps directly to
spec.hard
kubectl create quota compute-quota \
--hard=pods=10,requests.cpu=4,limits.cpu=8,requests.memory=8Gi,limits.memory=16Gi \
--namespace=dev
๐น --scopes Flag¶
- Applies quota only to objects matching all listed scopes
- Maps to
spec.scopes
kubectl create quota scope-limited \
--hard=pods=5 \
--scopes=BestEffort \
--namespace=dev
๐ You can later modify them in YAML for complex cases (e.g., scopeSelector).
๐งช Case Study-1: Mixed Quota with Scopes (CLI Command)¶
kubectl create quota mixed-quota \
--hard=services=5,pods=10 \
--scopes=NotTerminating,BestEffort \
--namespace=prod
๐ YAML:
apiVersion: v1
kind: ResourceQuota
metadata:
name: mixed-quota
namespace: prod
spec:
hard:
services: "5"
pods: "10"
scopes:
- NotTerminating
- BestEffort
๐งช Case Study-2: Mixed ResourceQuota (YAML)¶
# PriorityClass (must exist):
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: middle
value: 100000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "Middle tier priority"
---
# ResourceQuota with scopes:
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-dev-limit
namespace: dev
spec:
hard:
requests.cpu: "6"
requests.memory: 12Gi
limits.cpu: "12"
limits.memory: 24Gi
pods: "30"
persistentvolumeclaims: "5"
requests.storage: 200Gi
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values:
- middle
๐ What This Does:¶
- Applies only to pods with priorityClassName: middle
- Sets total compute usage caps
- Limits pod & PVC count
- Restricts total requested storage
โณ๏ธ Case Study-3; Full Example: Compute, Storage, Object Count, and ScopeSelector¶
apiVersion: v1
kind: ResourceQuota
metadata:
name: complete-quota
namespace: dev
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "4"
limits.memory: 8Gi
persistentvolumeclaims: "3"
pods: "20"
services: "10"
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values:
- high
โ๏ธ This YAML restricts compute, object count, and applies only to PriorityClass=high
๐ Bonus Tip: How Kubernetes Calculates Resources¶
Official docs: Resource Management for Pods and Containers
- In Kubernetes, containers can specify:
resources.requests: Minimum required resources.resources.limits: Max usable resources.
resources:
requests:
cpu: "250m"
memory: "64Mi"
limits:
cpu: "500m"
memory: "128Mi"
ResourceQuota tracks either or both via the .spec.hard section.
Note: When a ResourceQuota is defined in a namespace, every Pod must request/limit the listed resources.
๐งฎ Units in CPU and Memory¶
Understanding resource units is essential when defining requests, limits, or ResourceQuota.
๐ธ CPU Units¶
| Format | Meaning | Example |
|---|---|---|
m | millicores (1/1000 of 1 CPU) | 500m = 0.5 CPU |
| no unit | cores | 1 = 1 core |
๐ 1000m = 1 CPU core
โ๏ธ Valid examples:
cpu: "250m" # quarter of a CPU
cpu: "1" # 1 full CPU core
cpu: "2.5" # 2 and a half CPU cores
๐ธ Memory Units¶
Kubernetes accepts both binary (power-of-2) and decimal (power-of-10) formats.
| Suffix | Type | Meaning | Example |
|---|---|---|---|
Ki | Binary | Kibibyte (1024 bytes) | 64Ki = 65,536 bytes |
Mi | Binary | Mebibyte (1024 Ki) | 128Mi = 134MB |
Gi | Binary | Gibibyte (1024 Mi) | 2Gi = 2.14GB |
M | Decimal | Megabyte (1,000,000 bytes) | 128M = 128MB |
G | Decimal | Gigabyte (1,000,000,000 bytes) | 2G = 2GB |
โ๏ธ Valid examples:
memory: "128Mi"
memory: "1Gi"
memory: "512M"
โ Avoid mixing formats unless you're confident โ binary units (Mi, Gi) are more common in K8s.
Key Takeaways¶
- Use
mfor CPU if using less than 1 core (e.g.250m) - Use
Mi,Gifor memory (e.g.512Mi,2Gi) - Always use quotes around values to avoid parsing errors
If the exam question just says "total allowed CPU: 500m", and doesn't say limits, the best assumption is:
๐ก It refers to
requests.cpu, notlimits.cpu.
If it were meant to be a cap, the exam would say:
โmaximum CPU limit per namespaceโ โ in which case youโd use
limits.cpu.
โ Best Practices¶
- Use
requests.*andlimits.*to control fine-grained consumption - Use
scopesto target pod behavior (BestEffort, Terminating, etc.) - Use
scopeSelectorfor advanced use cases (e.g. PriorityClass)
| Practice | Why It Matters |
|---|---|
Always define PriorityClass clearly | Required for scopeSelector to work |
| Use multiple quotas per tier/team | Fine-grained control |
Donโt mix scopes with scopeSelector | Kubernetes doesnโt allow both |
| Name ResourceQuotas descriptively | Easier audit/debugging |
Use kubectl describe quota | For real-time usage stats |
๐ Summary Table¶
| Concept | Field / Flag | Description |
|---|---|---|
| Set hard resource caps | spec.hard / --hard | Limit memory, CPU, and object counts |
| Target certain pods | spec.scopes / --scopes | Restrict quotas to certain pod types |
| Fine-grained logic | spec.scopeSelector | Use complex rules (e.g., match PriorityClass) |
| CLI usage | kubectl create quota | Create ResourceQuota without writing YAML |
| Purpose | Field | Example |
|---|---|---|
| Set resource limits | spec.hard | cpu, memory, pods |
| Scope filtering (basic) | spec.scopes | BestEffort, NotBestEffort |
| Scope filtering (advanced) | spec.scopeSelector | matchExpressions |
| Object tracking (limits) | spec.hard.pods | Max pod count |
| Storage quota | requests.storage | Total PVC request limit |