K8s by Example: Resource Quotas

Resource Quotas limit aggregate resource consumption per namespace. They prevent any single team from consuming all cluster resources. Quotas apply to CPU, memory, storage, and object counts. Use for: multi-tenant clusters, cost control, capacity planning, preventing runaway workloads.

compute-quota.yaml

Compute quotas limit total CPU and memory in a namespace. Both requests (guaranteed resources) and limits (maximum resources) can be constrained. Pods that would exceed the quota are rejected.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: team-a
spec:
  hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi
object-count-quota.yaml

Object count quotas limit the number of resources. Prevent namespace sprawl with too many Pods, Services, or ConfigMaps. Useful for limiting PersistentVolumeClaims to control storage costs.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota
  namespace: team-a
spec:
  hard:
    pods: "50"
    services: "10"
    configmaps: "20"
    secrets: "20"
    persistentvolumeclaims: "10"
    services.loadbalancers: "2"
    services.nodeports: "5"
storage-quota.yaml

Storage quotas limit total storage and number of claims. Can be scoped by StorageClass to allow more SSD storage than HDD, or limit expensive storage tiers.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-quota
  namespace: team-a
spec:
  hard:
    requests.storage: 100Gi
    persistentvolumeclaims: "10"
    fast-ssd.storageclass.storage.k8s.io/requests.storage: 20Gi
    fast-ssd.storageclass.storage.k8s.io/persistentvolumeclaims: "3"
scoped-quota.yaml

Scoped quotas apply only to certain Pods. Use scopes to create different limits for BestEffort vs Guaranteed QoS, or for terminating vs long-running Pods.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: besteffort-quota
  namespace: team-a
spec:
  hard:
    pods: "10"
  scopes:
    - BestEffort
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: not-besteffort-quota
  namespace: team-a
spec:
  hard:
    pods: "40"
    requests.cpu: "10"
    requests.memory: 20Gi
  scopes:
    - NotBestEffort
limit-range.yaml

LimitRange sets defaults and constraints per Pod/Container. Unlike ResourceQuota (namespace aggregate), LimitRange applies to individual resources. Use together: LimitRange for per-pod constraints, ResourceQuota for namespace totals.

apiVersion: v1
kind: LimitRange
metadata:
  name: resource-limits
  namespace: team-a
spec:
  limits:
    - type: Container
      default:
        cpu: "500m"
        memory: 256Mi
      defaultRequest:
        cpu: "100m"
        memory: 128Mi
      max:
        cpu: "2"
        memory: 2Gi
      min:
        cpu: "50m"
        memory: 64Mi
    - type: PersistentVolumeClaim
      max:
        storage: 10Gi
      min:
        storage: 1Gi
priority-quota.yaml

Priority-based quotas limit resources by PriorityClass. Allow more resources for critical workloads, fewer for batch jobs. Scope quotas to specific priority levels.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: high-priority-quota
  namespace: team-a
spec:
  hard:
    pods: "20"
    requests.cpu: "20"
    requests.memory: 40Gi
  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values: ["high-priority", "critical"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: low-priority-quota
  namespace: team-a
spec:
  hard:
    pods: "50"
    requests.cpu: "5"
    requests.memory: 10Gi
  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values: ["low-priority", "batch"]
terminal

Monitor quota usage to track consumption and plan capacity. The Used column shows current consumption; Hard shows the limit. Alerts when approaching limits help prevent workload rejections.

$ kubectl describe resourcequota compute-quota -n team-a
Name:            compute-quota
Namespace:       team-a
Resource         Used    Hard
--------         ----    ----
limits.cpu       8       20
limits.memory    16Gi    40Gi
requests.cpu     4       10
requests.memory  8Gi     20Gi

$ kubectl get resourcequota -n team-a
NAME            AGE   REQUEST                      LIMIT
compute-quota   1d    requests.cpu: 4/10, ...      limits.cpu: 8/20, ...
object-quota    1d    pods: 25/50, services: 3/10

$ kubectl create deployment test --image=nginx -n team-a
error: failed to create deployment: exceeded quota

Index | GitHub | Use arrow keys to navigate |