Tenant Namespaces Should Have A ResourceQuota
More Info:
Advisory: create a ResourceQuota per tenant namespace to bound aggregate CPU, memory and object counts, preventing one tenant from starving others.
Risk Level
Low
Address
Security
Compliance Standards
- Cloudanix Best Practice
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify tenant namespaces (decision step)
On any machine with kubectl access, list namespaces and decide which are “tenant” namespaces (per your org’s multi-tenancy model; usually app or team namespaces, notkube-*,default, or system namespaces):kubectl get ns --show-labelsOptionally, if you label tenant namespaces (recommended), e.g.
tenant=true, list them:kubectl get ns -l tenant=true -
Check which tenant namespaces lack a ResourceQuota
For each tenant namespace you identified, check for existing ResourceQuota objects:kubectl get resourcequota -n <TENANT_NAMESPACE>Note which tenant namespaces return
No resources foundor have quotas that clearly do not bound CPU, memory, and object counts. -
Review existing ResourceQuota coverage and sufficiency (decision step)
For tenant namespaces that do have a ResourceQuota, inspect them to ensure they bound at least aggregate CPU, memory, and key object counts (e.g. pods, services, PVCs, configmaps, secrets):kubectl describe resourcequota -n <TENANT_NAMESPACE>Decide whether limits are appropriate for the tenant (not too low to break workloads, not so high that tenants can starve others).
-
Design quota policies per tenant type (decision step)
Outside the cluster (on any admin workstation), define standard quota “profiles” for different tenant types (e.g. small/medium/large) that include:requests.cpu,requests.memory,limits.cpu,limits.memorypods,services,persistentvolumeclaims,configmaps,secrets, etc.
Document which profile each tenant namespace should receive based on current and projected usage.
-
Create or update ResourceQuota manifests for tenant namespaces
On any machine with kubectl access, create or adjust ResourceQuota objects according to your profiles. Example manifest (adjust values per your decisions):cat << 'EOF' > tenant-resourcequota.yamlapiVersion: v1kind: ResourceQuotametadata:name: tenant-quotanamespace: <TENANT_NAMESPACE>spec:hard:requests.cpu: "4"requests.memory: "8Gi"limits.cpu: "8"limits.memory: "16Gi"pods: "50"services: "10"persistentvolumeclaims: "20"configmaps: "50"secrets: "50"EOFApply for each tenant namespace (edit the manifest namespace or generate one per namespace):
kubectl apply -f tenant-resourcequota.yaml -
Verify quotas are in place and effective
On any machine with kubectl access, confirm that every tenant namespace now has an appropriate ResourceQuota and that usage is tracked:# List quotas per tenant namespacekubectl get resourcequota -n <TENANT_NAMESPACE># Confirm hard limits and current usagekubectl describe resourcequota -n <TENANT_NAMESPACE>Re-run this check for all tenant namespaces; any tenant namespace without a ResourceQuota, or with quotas that don’t bound CPU, memory, and object counts, should be revisited using steps 3–5.
Using kubectl
# 1) List all namespaces to identify tenant namespaces
# Run on: any machine with kubectl access
kubectl get namespaces -o custom-columns=NAME:.metadata.name \
--no-headers | sort
Review this list and decide which are tenant namespaces (for example, team or project namespaces) versus system/internal namespaces (e.g. kube-system, kube-public, kube-node-lease, istio-system, ingress-nginx, etc.).
# 2) For a given tenant namespace, check for ResourceQuota objects
# Replace TENANT_NS with an actual tenant namespace name
kubectl get resourcequota -n TENANT_NS
Problem indication:
- If this command returns
No resources found in TENANT_NS namespace, the tenant namespace has noResourceQuotaand is in violation of this control. - If it returns one or more
ResourceQuotaobjects, you must still review them (next step) to decide whether the quotas are adequate.
# 3) Inspect details of each ResourceQuota in the tenant namespace
# First, list the names:
kubectl get resourcequota -n TENANT_NS -o name
# Then, for each quota (example name: rq-team-a), describe it:
kubectl describe resourcequota rq-team-a -n TENANT_NS
Problem indication (requires human judgment):
Hardlimits missing for CPU or memory (e.g. no entries forlimits.cpu,limits.memory,requests.cpu,requests.memory) mean aggregate resource usage is not bounded.- Missing object count limits (e.g.
pods,configmaps,secrets,services,persistentvolumeclaims) mean the namespace could still starve others via object count exhaustion. - Very high or effectively unlimited values (e.g.
0where that means “no limit”, or values that exceed node/cluster capacity) indicate quotas are not meaningfully constraining the tenant.
# 4) Optional: summarize quotas for all namespaces to spot gaps at a glance
kubectl get resourcequota --all-namespaces
Problem indication:
- Any tenant namespace that does not appear in this list lacks a
ResourceQuotaand should be reviewed and corrected. - Namespaces that appear with quotas but you know are not tenants (e.g. system namespaces) are not relevant to this control and can be ignored.
Automation
#!/usr/bin/env bash
#
# Report tenant namespaces that do NOT have a ResourceQuota
# and summarize quotas for those that do.
#
# Run from: any machine with kubectl access and the correct context.
# Requires: kubectl, jq
set -euo pipefail
# 1) Define how to identify "tenant" namespaces.
# Adjust this selector to match YOUR environment.
# Examples:
# - All non-system namespaces:
# NS_SELECTOR='!name in (kube-system,kube-public,kube-node-lease,default)'
# - Label-based (preferred):
# NS_SELECTOR='tenant=true'
#
# Below uses label-based selection. Update to match your labels.
NS_SELECTOR='tenant=true'
echo "==> Discovering tenant namespaces (selector: ${NS_SELECTOR})"
TENANT_NAMESPACES=$(kubectl get ns -l "${NS_SELECTOR}" -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
if [[ -z "${TENANT_NAMESPACES}" ]]; then
echo "No tenant namespaces found with selector '${NS_SELECTOR}'."
exit 0
fi
echo ""
echo "==> Per-namespace ResourceQuota summary"
echo "Namespace,HasResourceQuota,QuotaName,Hard.cpu,Hard.memory,Hard.pods,Hard.configmaps,Hard.secrets,Hard.services,Hard.persistentvolumeclaims"
MISSING_COUNT=0
for ns in ${TENANT_NAMESPACES}; do
RQ_JSON=$(kubectl get resourcequota -n "${ns}" -o json 2>/dev/null || echo '{}')
RQ_COUNT=$(echo "${RQ_JSON}" | jq '.items | length')
if [[ "${RQ_COUNT}" -eq 0 ]]; then
# No ResourceQuota in this tenant namespace
echo "${ns},NO,,,,,,,"
((MISSING_COUNT++))
continue
fi
# Print one line per ResourceQuota in the namespace
echo "${RQ_JSON}" | jq -r --arg ns "${ns}" '
.items[] as $rq |
[
$ns,
"YES",
$rq.metadata.name,
($rq.spec.hard.cpu // ""),
($rq.spec.hard.memory // ""),
($rq.spec.hard.pods // ""),
($rq.spec.hard.configmaps // ""),
($rq.spec.hard.secrets // ""),
($rq.spec.hard.services // ""),
($rq.spec.hard.persistentvolumeclaims // "")
] | @csv
'
done
echo ""
echo "==> Summary"
TOTAL_NS=$(echo "${TENANT_NAMESPACES}" | wc -l | tr -d ' ')
echo "Total tenant namespaces: ${TOTAL_NS}"
echo "Namespaces without any ResourceQuota: ${MISSING_COUNT}"
if [[ "${MISSING_COUNT}" -gt 0 ]]; then
echo ""
echo "Problem indication:"
echo "- Any line with 'HasResourceQuota' == 'NO' in the CSV output"
echo " (e.g. 'tenant-a,NO,....') marks a tenant namespace that lacks a ResourceQuota."
echo "- These namespaces should be reviewed and given an appropriate ResourceQuota"
echo " to bound aggregate CPU, memory, and object counts."
fi
What output indicates a problem
- In the CSV section, any row where the second column (
HasResourceQuota) isNOindicates a tenant namespace that does not have anyResourceQuotaobjects defined. - The final summary line
Namespaces without any ResourceQuota: N:- If
N > 0, those namespaces are not constrained and should be reviewed and given an appropriateResourceQuotaper the benchmark guidance.
- If