Skip to content

Resource Quota and Limit Range (ResourceQuota / LimitRange)

ResourceQuota and LimitRange are two namespace-level resource governance mechanisms built into Kubernetes. Kuboard provides management pages for both under the Namespace navigation group, and offers a quick view / edit entry on the namespace detail page.

ResourceWhat it governsOne-line positioning
ResourceQuotaThe entire namespaceTotal cap: limits the cumulative CPU / memory / storage consumed by all objects in the namespace, as well as the number of objects of each type (Pod, Service, PVC, …)
LimitRangeA single container / PodPer-instance constraint: supplies a default request / limit to containers that do not explicitly declare resources, and forces every container / Pod's resource declaration to fall within the min ~ max range

Disambiguation: the quota governs the total, LimitRange governs a single Pod

A quota governs "how much a namespace may use at most and how many objects it may create"; a LimitRange governs "how much a single container / Pod needs at least, may ask for at most, and what it gets by default when nothing is written". Both take effect only when objects are created / updated, and neither reclaims running Pods. They are usually used together: the LimitRange first ensures every container declares explicit resources, and the quota then ensures all containers together do not exceed the namespace's budget.

Where to Find the Entry

Under the Cluster Management → Namespaces group in the left navigation, you can find the Resource Quota and Limit Range menus. Both are namespace-level resources; after entering the list, first select a cluster and a namespace.

The other entry is the namespace detail page → Resource Limit tab: it combines the LimitRange summary and the ResourceQuota usage in one view, and lets you edit quota values directly — the fastest entry for daily operations (see below).

Resource Quota (ResourceQuota)

What a Quota Can Limit

A quota is written dimension by dimension in spec.hard, one key-value pair per dimension. Common dimensions:

hard keyMeaningProvided by the create form
requests.cpuTotal cap on the CPU requests of all PodsNo (YAML)
limits.cpuTotal cap on the CPU limits of all PodsNo (YAML)
cpuCounts CPU requests and limits togetherYes
requests.memoryTotal cap on memory requestsNo (YAML)
limits.memoryTotal cap on memory limitsNo (YAML)
memoryCounts memory requests and limits togetherYes
requests.storageTotal cap on the storage capacity declared by PVCsYes
count/podsPod count limitNo (YAML)
count/deployments.apps, etc.Limits on the number of workloads / objects of each kindNo (YAML)
count/servicesService count limitYes (labeled "Services" in the form)
count/secrets / count/configmapsLimits on the number of Secrets / ConfigMapsNo (YAML)
requests.nvidia.com/gpu, etc.Vendor GPU count limitNo (YAML)

The create form presets five dimensions — CPU, memory, storage requests, objects count and services — which are written to the corresponding keys of spec.hard when filled in; the finer-grained requests.*, limits.* and count/* dimensions are better maintained in the YAML editor.

Quickly Setting a Quota on the Namespace Detail Page

For most scenarios, you do not need to create a quota object first and then wait for it to take effect. Open the namespace detail page → Resource Limit tab:

  1. The upper part of the page is Default Request/Limit per Container (from the LimitRange, see below); the lower part is the Resource Quota usage list, one row per dimension (CPU limit, CPU request, memory limit, memory request, storage request, Pod count, Deployment count, Service count, Secret count, etc.);
  2. A dimension without a quota shows No Limit, and the whole row is displayed in a semi-transparent style;
  3. Click Edit on a row, enter the quota value (CPU: 2 or 100m, memory: 240Mi or 2Gi, count types: a positive integer), and it takes effect immediately after saving;
  4. Click Clear to remove the limit for that dimension.

When a ResourceQuota with the same name already exists in the namespace, Kuboard modifies it directly; otherwise it automatically creates a quota object named after the namespace. The usage rate of each row is shown as a progress bar: ≤20% green, ≤60% default color, ≤80% yellow, >80% red.

Quotas with a scopeSelector

Quotas scoped by spec.scopeSelector (e.g. counting only Pods of a specific priority class) do not appear in the summary list of the namespace detail page; view them on the Resource Quota list / detail page instead.

Creating / Editing a ResourceQuota

Enter Namespace → Resource Quota → Create:

FieldCorresponding keyDescription
Namemetadata.nameUnique within the namespace
CPUhard.cpue.g. 10
Memoryhard.memorye.g. 20Gi
Requests Storagehard["requests.storage"]e.g. 100Gi
Objects Counthard["objects.count"]e.g. 100
Serviceshard.servicese.g. 20

It takes effect on the namespace immediately after creation. The Edit page fields are identical to the create page; the quota name cannot be modified. Advanced fields other than spec.hard (such as scopeSelector) can only be maintained through the YAML entry on the list page.

A complete example of a quota object:

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: default
spec:
  hard:
    limits.cpu: "20"
    limits.memory: 40Gi
    requests.cpu: "10"
    requests.memory: 20Gi
    requests.storage: 100Gi
    count/pods: "50"
    count/deployments.apps: "10"

Viewing Quota Usage

The quota detail page shows spec.hard (hard limits) and status.used (used) side by side in a table:

ColumnSourceDescription
Namekey of spec.hardMetric name (CPU, memory, storage requests, …)
Hard Limitsspec.hardQuota cap
Usedstatus.usedCurrent actual usage of the namespace
Remaininghard limits − usedAmount still available

status.used is continuously maintained by the Kubernetes controllers; no manual maintenance is needed. Dimensions that are not set show -.

Quota Exceeded: Errors and Troubleshooting

When a submitted object would push the namespace past a quota cap, the API server rejects the request directly; creating / importing YAML shows an error like:

sh
Error from server (Forbidden): pods "web-6d9d7f5f5c-abcde" is forbidden:
exceeded quota: compute-quota, requested: limits.memory=2Gi,
used: limits.memory=40Gi, limited: limits.memory=40Gi

requested is the amount this request asks for, used is the current usage and limited is the quota cap — comparing the three pinpoints which dimension is exceeded. Troubleshooting steps:

  1. Open the Resource Quota list of that namespace and compare the Used / Hard Limits of each dimension;
  2. Or simply look at the per-dimension progress bars on the namespace detail page → Resource Limit tab (red means close to / over the cap);
  3. Once the exceeded dimension is clear, choose one of two options: edit the quota to enlarge that dimension, or delete / scale down some workloads to free up usage;
  4. When count/pods is exceeded, rolling releases of workloads are also rejected (new Pods cannot be created); the symptom is "the deployment is stuck updating" — check the Pod count quota first in this case.

An exceeded quota does not affect running objects

A quota is only checked at creation / update time. Running objects are not terminated even if their usage pushes past the cap; however, any new creation afterwards (including scaling up replicas and new Pods produced by rolling updates) is rejected until usage returns within the limit.

Limit Range (LimitRange)

What Problem LimitRange Solves

  • A safety net for containers that "forgot to declare resources": containers without resources.requests / limits are unlimited by default and can easily crowd out other Pods on a node; LimitRange's Default / DefaultRequest fills them in automatically;
  • Hard boundaries for resource declarations: Min / Max guarantees that no container and no Pod can declare resources below the minimum or above the maximum, preventing a single application from eating up the quota instantly;
  • Constrains storage declaration capacity: restricts the Min / Max for PersistentVolumeClaim to prevent a PVC from declaring an excessively large capacity.

Creating a LimitRange

Enter Namespace → Limit Range → Create; the form consists of a Name and a "Limit" editing table. Each table row is one Limit Type; use + Add Limit Type to add multiple rows. Each row contains four pairs of CPU / memory inputs:

ColumnCorresponding spec fieldMeaning
Limit Typelimits[].typeType of the governed object: Container / Pod / PersistentVolumeClaim / PersistentVolume
Defaultlimits[].defaultDefault limit automatically applied when no limit is explicitly declared
Requestlimits[].defaultRequestDefault request automatically applied when no request is explicitly declared
Limitlimits[].maxMaximum allowed value
Minlimits[].minMinimum allowed value

Input examples: CPU 100m or 2, memory 512Mi or 4Gi.

Scenarios for the four Limit Types

  • Container: constrains the CPU / memory of a single container, the most commonly used;
  • Pod: constrains the sum of resources of all containers of the whole Pod (e.g. limiting the total memory cap of a Pod);
  • PersistentVolumeClaim: constrains the storage capacity declared by a PVC; for Min / Max, only the memory column is filled in (semantically the storage capacity);
  • PersistentVolume: similar to PVC, but applies to PV objects.

A complete LimitRange object example:

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: container-limits
  namespace: default
spec:
  limits:
    - type: Container
      default:            # applied automatically when no limit is declared
        cpu: 500m
        memory: 512Mi
      defaultRequest:     # applied automatically when no request is declared
        cpu: 100m
        memory: 128Mi
      max:                # upper bound
        cpu: "2"
        memory: 4Gi
      min:                # lower bound
        cpu: 50m
        memory: 64Mi

How Validation and Defaults Take Effect

Using the Container type as an example, when a Pod is created / updated:

  1. A container with no request declared → defaultRequest is filled in automatically; with no limit declared → default is filled in automatically;
  2. A container with request / limit declared → each is compared against Min / Max; values outside the range are rejected outright;
  3. The filled-in default values must also fall within the Min / Max range (otherwise Kubernetes rejects creating the LimitRange itself).

On a validation failure, you will see an error like:

sh
Error: maximum cpu usage per Container is 2, but limit is 3
Error: minimum memory usage per Container is 64Mi, but request is 32Mi

At the same time, if the namespace already has a quota, the default request / limit filled in by the LimitRange is counted in the ResourceQuota statistics — this is exactly the "first set a safety net, then cap" working combination: the quota statistics are accurate only when every container has an explicit resource declaration.

The effective scope of modifying a LimitRange

A modified LimitRange only affects Pods / PVCs created afterwards. Running containers are neither back-filled with defaults nor evicted by the new Min / Max.

  • Namespace: the Resource Limit tab of the namespace detail page provides quick view / edit of quotas and LimitRanges
  • Pod: LimitRange defaults and Min / Max act directly on Pod resource declarations
  • PersistentVolumeClaim (PVC): the object governed by requests.storage and PVC-type LimitRanges