Intro
Kubernetes Resource Quotas are essential for preventing any single tenant or workload from consuming more than its fair share of cluster resources. While quotas are often discussed in the context of capacity planning, their security implications are equally important. A misconfigured quota can lead to denial-of-service conditions, privilege escalation through resource exhaustion, or bypassing of isolation boundaries. This article provides a practical guide to hardening Resource Quotas, focusing on access control, secrets and sensitive data, permissions, and safe configuration checks. We will walk through a realistic deployment scenario, demonstrate concrete commands and expected outputs, and provide an operational checklist to keep your quotas secure over time.
Version and Environment Inventory
Before implementing any hardening measures, you must establish a clear inventory of your Kubernetes environment. This includes the Kubernetes version, the ResourceQuota admission plugin status, the namespaces in scope, and the roles and users who interact with quotas.
Versions and Components
- Kubernetes version: We assume Kubernetes 1.28 or later for this guide. ResourceQuota has been stable since early versions, but API fields may vary.
- API version:
v1for ResourceQuota and LimitRange. - Admission plugin:
ResourceQuotamust be enabled in the kube-apiserver. Check with:
kubectl get --raw /healthz?verbose | grep resourcequota
Expected output if enabled:
[+]resourcequota ok
If not present, add ResourceQuota to the --enable-admission-plugins flag on the API server and restart.
Cluster Topology
Our example cluster has three namespaces:
team-ateam-bshared-services
We will focus on team-a and team-b for quota enforcement, while shared-services may have different policies.
Prerequisites
kubectlconfigured with cluster admin privileges for initial setup.- A test namespace for validating changes before production rollout.
- Understanding of RBAC (Role-Based Access Control) in Kubernetes.
Safe Configuration Path
Hardening Resource Quotas is not just about setting resource limits; it's about ensuring that only authorized entities can create or modify quotas, and that quotas themselves do not inadvertently expose sensitive information. We will proceed in incremental steps, each with a concrete example.
Step 1: Create a Baseline ResourceQuota
Start with a simple quota that limits the number of objects and compute resources in a namespace. For team-a, create a file quota-team-a.yaml:
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "20"
services: "10"
secrets: "30"
configmaps: "30"
persistentvolumeclaims: "10"
Apply it:
kubectl apply -f quota-team-a.yaml
Output:
resourcequota/team-a-quota created
This quota enforces compute and object count limits. Notice that secrets are limited, which is important for security: it prevents a compromised pod from creating a large number of secrets for exfiltration.
Step 2: Secure Access to ResourceQuota Objects
By default, only cluster admins can create ResourceQuotas, but in many organizations, namespace admins are given permission. To enforce least privilege, define a Role that allows viewing but not modifying quotas for developers.
Create a Role for developers in team-a:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: team-a
name: developer
rules:
- apiGroups: [""]
resources: ["resourcequotas"]
verbs: ["get", "list", "watch"]
Apply and bind to a group:
kubectl apply -f developer-role.yaml
kubectl create rolebinding developer-quota-view --role=developer --group=dev-team-a -n team-a
Now a developer cannot edit the quota. To test, impersonate a user in the group:
kubectl auth can-i update resourcequotas -n team-a --as=developer1
Expected output:
no
Step 3: Protect Secrets with Quotas and RBAC
Secrets often contain credentials, tokens, or other sensitive data. A ResourceQuota limiting secrets helps, but you must also control who can create secrets. Combine quota with RBAC to restrict secret creation.
Create a separate role for secret management that only allows creating secrets up to the quota limit. In team-a, only a designated service account should create secrets for CI/CD.
Define a Role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: team-a
name: secret-creator
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "get", "list", "watch", "delete"]
Bind to a service account:
kubectl create rolebinding secret-creator-binding --role=secret-creator --serviceaccount=team-a: ci-bot -n team-a
Now only ci-bot can create secrets, and the quota prevents excessive creation.
Step 4: Use LimitRange to Enforce Defaults and Prevent Quota Evasion
A common bypass is to omit resource requests and limits in pod specs, causing them to consume default values or slip through. LimitRange can set defaults and enforce min/max. Create a LimitRange for team-a:
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
- default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: 2
memory: 4Gi
min:
cpu: 50m
memory: 64Mi
type: Container
Apply:
kubectl apply -f limitrange-team-a.yaml
Now any pod created without explicit requests gets the defaults, which count against the ResourceQuota. This prevents a pod from bypassing quota by omitting requests.
Step 5: Restrict Network Exposure via Quota on Services and Ingresses
ResourceQuota can limit the number of Services and Ingresses, reducing the attack surface. For example, limiting LoadBalancer services prevents accidental exposure of internal services to the internet.
Extend the quota with:
spec:
hard:
services.loadbalancers: "1"
ingresses: "5"
Apply the updated quota and verify:
kubectl describe resourcequota team-a-quota -n team-a
Output snippet:
Name: team-a-quota
Namespace: team-a
Resource Used Hard
-------- ---- ----
services.loadbalancers 0 1
ingresses 0 5
Verification and Diagnostics
After applying hardening measures, you must verify that quotas are enforced and that permissions are correct. Use the following commands and interpret outputs.
Check Quota Status
kubectl get resourcequota -n team-a
kubectl describe resourcequota team-a-quota -n team-a
The describe output shows used vs hard limits. If used exceeds hard, new resource creation is blocked.
Test Quota Enforcement
Attempt to create a pod that would exceed the CPU limit. Create a pod spec with high CPU request:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: team-a
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "5"
Apply:
kubectl apply -f test-pod.yaml
Expected error:
Error from server (Forbidden): error when creating "test-pod.yaml": pods "test-pod" is forbidden: exceeded quota: team-a-quota, requested: requests.cpu=5, used: requests.cpu=0, limited: requests.cpu=10
This confirms quota enforcement.
Verify RBAC Permissions
Use kubectl auth can-i as shown earlier. Check if a user can delete quotas:
kubectl auth can-i delete resourcequotas -n team-a --as=developer1
Expected:
no
Audit Secret Creation
Simulate a developer trying to create a secret:
kubectl create secret generic test-secret --from-literal=password=test -n team-a --as=developer1 --dry-run=client
If the developer lacks create permission, the dry-run will fail with a forbidden error. If they have permission but quota is exceeded, it will also fail.
Failure Modes and Recovery
Despite best efforts, misconfigurations can occur. Here are common failure modes and how to recover.
Failure: Quota Too Restrictive Causing Workload Evictions
If a quota is set too low, existing pods may be evicted or new deployments fail. To recover, temporarily increase the quota or delete it (if safe).
kubectl edit resourcequota team-a-quota -n team-a
# Increase limits
Or delete the quota to stop enforcement (emergency only):
kubectl delete resourcequota team-a-quota -n team-a
Failure: Accidentally Locked Out of Namespace
If RBAC misconfiguration prevents even admins from managing quotas, use cluster-admin role to override. A cluster-admin can always edit any resource. Ensure you have a break-glass account.
Failure: Secret Quota Exhaustion Blocks Legitimate Secrets
If the secret quota is full, legitimate applications cannot create secrets. Identify and delete unused secrets:
kubectl get secrets -n team-a
kubectl delete secret <unused-secret> -n team-a
Then adjust the quota if needed.
Rollback Plan
Always keep versioned copies of your quota and RBAC YAML files. To rollback, apply the previous version:
kubectl apply -f previous-quota.yaml
Also, monitor events for quota-related warnings:
kubectl get events -n team-a --sort-by=.lastTimestamp
Operations Checklist
Use this checklist for ongoing operations and periodic reviews.
| Check | Command | Expected |
|---|---|---|
| ResourceQuota exists | kubectl get resourcequota -n team-a | At least one quota |
| Quota limits are appropriate | kubectl describe resourcequota team-a-quota -n team-a | Hard limits match policy |
| No excessive secret count | kubectl get secrets -n team-a | wc -l | Less than hard limit | | RBAC: only admins can edit quotas | kubectl auth can-i update resourcequotas -n team-a --as=developer1 | no | | LimitRange defaults in place | kubectl get limitrange -n team-a | LimitRange exists | | Pod creation respects quota | Attempt test pod | Forbidden if exceeding | | Network exposure limited | kubectl get svc -n team-a | No unexpected LoadBalancers |
Review quotas quarterly or after any change in team structure or workload patterns. Use kubectl get resourcequota --all-namespaces for a cluster-wide view.
Conclusion
Securing Kubernetes Resource Quotas is a multi-layered effort that combines admission control, RBAC, LimitRange, and careful monitoring. By implementing the steps in this guide, you can prevent resource abuse, limit the blast radius of compromised pods, and maintain fair allocation across teams. Start with a narrow pilot in a test namespace, verify the behavior, and then roll out to production with the operations checklist. Regular audits and a clear rollback plan ensure that your quotas remain effective security controls rather than operational bottlenecks. Use the provided commands and YAML examples as a foundation, and adapt them to your organizational policies and cluster topology.