KubernetesCVIII · ResourceQuotaResourceQuota
Quota scoping — PriorityClass and StorageClass-based quotas
What you'll learn
- Use PriorityClass-scoped quotas
- Use StorageClass-scoped quotas
- Reason about the use cases for scoping
- Apply the operational discipline of scoping quotas appropriately
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Quota scoping limits a quota to specific scopes. This lesson walks PriorityClass-scoped quotas, StorageClass-scoped quotas, the use cases, and the operational discipline.
PriorityClass-scoped quotas
apiVersion: v1
kind: ResourceQuota
metadata:
name: high-priority-quota
namespace: tenant-a-prod
spec:
hard:
requests.cpu: "16"
requests.memory: 32Gi
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["high-priority"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: low-priority-quota
namespace: tenant-a-prod
spec:
hard:
requests.cpu: "16"
requests.memory: 32Gi
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["low-priority"]
The PriorityClass-scoped quota only counts Pods with the specified PriorityClass. High-priority workloads get a separate budget from low-priority workloads.
The use case
flowchart LR
A["Namespace: tenant-a-prod"] --> B["High-priority workload: 16 cores"]
A --> C["Low-priority workload: 16 cores"]
B --> D["PriorityClass: high-priority"]
C --> E["PriorityClass: low-priority"]
D --> F["Quota: high-priority-quota"]
E --> G["Quota: low-priority-quota"]
The use case: a tenant has critical workloads (e.g., the checkout API) and batch workloads (e.g., analytics). The two should not compete for the same quota. PriorityClass-scoped quotas give each a separate budget.
StorageClass-scoped quotas
apiVersion: v1
kind: ResourceQuota
metadata:
name: premium-storage-quota
namespace: tenant-a-prod
spec:
hard:
requests.storage: 500Gi
persistentvolumeclaims: "20"
scopeSelector:
matchExpressions:
- scopeName: StorageClass
operator: In
values: ["premium-ssd"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: standard-storage-quota
namespace: tenant-a-prod
spec:
hard:
requests.storage: 1Ti
persistentvolumeclaims: "30"
scopeSelector:
matchExpressions:
- scopeName: StorageClass
operator: In
values: ["standard-hdd"]
The StorageClass-scoped quota only counts PVCs with the specified StorageClass. Premium SSD storage gets a separate budget from standard HDD storage.
The use case
flowchart LR
A["Namespace: tenant-a-prod"] --> B["Premium SSD: 500Gi"]
A --> C["Standard HDD: 1Ti"]
B --> D["StorageClass: premium-ssd"]
C --> E["StorageClass: standard-hdd"]
D --> F["Quota: premium-storage-quota"]
E --> G["Quota: standard-storage-quota"]
The use case: a tenant uses premium SSD for production databases and standard HDD for non-critical workloads. Premium SSD is more expensive; a separate quota prevents overconsumption.
The scoping syntax
spec:
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["high-priority"]
- scopeName: StorageClass
operator: In
values: ["premium-ssd"]
Multiple scopes can be combined: a quota that counts only Pods with the specified PriorityClass AND only PVCs with the specified StorageClass.
Unscoped vs scoped quotas
flowchart LR
A[Unscoped quota] --> B["Counts all Pods/PVCs in namespace"]
C[Scoped quota] --> D["Counts only matching Pods/PVCs"]
The choice:
- Unscoped. Counts every Pod/PVC in the namespace. Simpler; appropriate when all workloads have the same priority and storage tier.
- Scoped. Counts only matching Pods/PVCs. More granular; appropriate when different workloads need separate budgets.
Quiz
Knowledge check · 4 questions
Q1. What does a `PriorityClass`-scoped ResourceQuota let you express?
Q2. A namespace may have several ResourceQuota objects with different scopes.
Q3. Two scoped quotas cover a namespace, yet its total consumption is far above what either allows; find the gap.
`ml-prod` has two ResourceQuotas: `high-quota` scoped to PriorityClass `high-priority` and `low-quota` scoped to PriorityClass `low-priority`, each with `requests.cpu: 16`. `kubectl describe resourcequota -n ml-prod` shows 11 of 16 and 9 of 16. Summing the actual Pod requests in the namespace gives 58 cores, and this namespace is exhausting node allocatable.
Q4. Name three `scopeName` values a ResourceQuota `scopeSelector` accepts besides `PriorityClass`, and say what a quota scoped to `BestEffort` counts.
Passing score: 75%. Answers are checked in this browser.
The operational discipline
Quota scoping in production rests on five non-negotiable elements:
- Define PriorityClasses. Before scoping quotas, define the PriorityClasses in the cluster.
- Define StorageClasses. Before scoping storage quotas, define the StorageClasses.
- Use scoping when justified. Different budgets for different workloads.
- Monitor scoped and unscoped separately. Each quota has its own utilisation.
- Document the scoping. The runbook lists which quotas are scoped and why.
Quota scoping is a precision tool. Use it when different workloads need separate budgets; do not over-scope when a single unscoped quota suffices.