Quota#
A Quota is a reusable allocation profile owned by the cluster
administrator. It defines the resource ceilings a tenant may consume
(resourcequota) and, optionally, per-object defaults and bounds
(limitrange). A Tenant references a Quota by name through its
spec.quota field.
The value is in the indirection: one Quota can back many tenants. The admin
defines small, medium and large once, assigns them, and changes a tier in
a single place for every tenant that uses it. It also keeps duties separate —
admins own the ceilings, tenant owners work freely beneath them.
flowchart LR
Admin["Platform admin"] -->|defines once| Q["Quota 'small'"]
Q --> T1["Tenant alpha<br/>spec.quota: small"]
Q --> T2["Tenant bluesky<br/>spec.quota: small"]
Q --> T3["Tenant gamma<br/>spec.quota: small"]
How a Quota is enforced#
The ceiling is the same everywhere; the underlying object the operator creates differs by distribution.
flowchart TB
Q["Quota CR"]
Q -->|OpenShift| CRQ["ClusterResourceQuota<br/>one object spanning all<br/>of the tenant's namespaces"]
Q -->|other distributions| RQ["ResourceQuota<br/>in every tenant namespace"]
RQ --> Agg["Aggregated across namespaces<br/>at admission time"]
- On OpenShift, MTO relies on a ClusterResourceQuota that spans all of the tenant's namespaces and does the calculation natively.
- On other Kubernetes distributions, MTO creates a standard ResourceQuota in each tenant namespace and aggregates usage at admission time.
Preview on Kubernetes
Quota enforcement on non-OpenShift distributions is a preview feature. Under webhook load it can admit more than the configured ceiling. Reach out to Stakater Support with any questions.
The spec at a glance#
A Quota is served at tenantoperator.stakater.com/v1beta1 (note: the
Tenant that links it is v1beta3). The spec has two fields,
each a standard Kubernetes type, so any key those types support can be set:
| Field | Required | What it controls |
|---|---|---|
resourcequota |
Yes | Aggregate resource ceilings for the tenant — a ResourceQuotaSpec. |
limitrange |
No | Per-object defaults, minimums and maximums — a LimitRangeSpec. |
For a manifest you can adapt, see Assigning a quota to a tenant below; the full generated schema is in the API reference.
Assigning a quota to a tenant#
Bill, a cluster admin, first creates a Quota with the ceilings Anna's tenant
will have. limitrange is optional — skip it if you don't need per-object
bounds.
kubectl create -f - << EOF
apiVersion: tenantoperator.stakater.com/v1beta1
kind: Quota
metadata:
name: small
spec:
resourcequota:
hard:
requests.cpu: '5'
requests.memory: '5Gi'
configmaps: "10"
secrets: "10"
services: "10"
services.loadbalancers: "2"
limitrange:
limits:
- type: "Pod"
max:
cpu: "2"
memory: "1Gi"
min:
cpu: "200m"
memory: "100Mi"
EOF
kubectl get quota small
NAME STATE AGE
small Active 3m
Bill then creates Anna's tenant, linking the small quota through
spec.quota:
kubectl create -f - << EOF
apiVersion: tenantoperator.stakater.com/v1beta3
kind: Tenant
metadata:
name: bluesky
spec:
quota: small
accessControl:
owners:
users:
- anna@aurora.org
- anthony@aurora.org
namespaces:
withTenantPrefix:
- production
sandboxes:
enabled: true
EOF
Anna can now create resources freely up to the quota's ceilings:
kubectl -n bluesky-production create deployment nginx --image nginx:latest --replicas 4
Once the tenant's usage reaches a ceiling, further resources are rejected:
kubectl -n bluesky-production run overflow --image=nginx:latest
Error from server (Cannot exceed Namespace quota: please, reach out to the system administrators)
Limiting total storage#
To cap the storage a tenant may provision, Bill adds requests.storage to
resourcequota.hard. This Quota limits the tenant to 50Gi across all its
namespaces:
kubectl create -f - << EOF
apiVersion: tenantoperator.stakater.com/v1beta1
kind: Quota
metadata:
name: medium
spec:
resourcequota:
hard:
requests.cpu: '5'
requests.memory: '10Gi'
requests.storage: '50Gi'
EOF
Link it to the tenant the same way — set spec.quota: medium on the Tenant.
The combined storage used by all of the tenant's namespaces will then not
exceed 50Gi.
Limiting storage per StorageClass#
To cap how much a tenant may provision from a specific StorageClass, Bill
uses the <storage-class-name>.storageclass.storage.k8s.io/requests.storage
key. This Quota limits provisioning from the stakater StorageClass to 20Gi:
kubectl create -f - << EOF
apiVersion: tenantoperator.stakater.com/v1beta1
kind: Quota
metadata:
name: sc-limited
spec:
resourcequota:
hard:
requests.cpu: '2'
requests.memory: '4Gi'
stakater.storageclass.storage.k8s.io/requests.storage: '20Gi'
EOF
Link it with spec.quota: sc-limited. The combined storage provisioned from
the stakater StorageClass across the tenant's namespaces will then not exceed
20Gi.
Note
This limit applies only to the named StorageClass. A PVC created with a different StorageClass is not restricted by this key.
Tip
For the full set of quota keys, see the Kubernetes Resource Quotas documentation.