Namespaces, ResourceQuotas and LimitRanges
Requests and limits are set by whoever writes the Deployment. But what if a team forgets them, or asks for 50 CPUs? Cluster admins set rules per namespace: a ResourceQuota caps the namespace's total, and a LimitRange sets defaults and bounds for each container.
Namespaces in two minutes
A namespace is a folder inside the cluster. Names only have to be unique within one, and many rules, quotas and permissions included, apply per namespace.
$ kubectl create namespace team-a
$ kubectl apply -f all.yaml -n team-a # deploy into it
$ kubectl get pods -n team-a # look inside it
$ kubectl get pods -A # every namespace
$ kubectl config set-context --current --namespace=team-a # make it your default
Services in another namespace are reached as http://posts-srv.team-a (chapter 11). kube-system holds Kubernetes' own components; leave it alone.
Three levels of rules
| Object | Applies to | Answers | Written by |
|---|---|---|---|
resources (chapter 22) | One container | "This container needs 250m and may use 500m" | App developer |
| LimitRange | Each container (or Pod) in a namespace | "If you forget, you get 250m. Nobody may ask for more than 2 CPU." | Admin |
| ResourceQuota | The namespace's total | "All of team-a together: at most 2 CPU, 4Gi and 10 Pods." | Admin |
ResourceQuota
A budget for the whole namespace. Every new object is checked against it; anything that would go over is refused at creation, not killed later.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: team-a
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "4"
limits.memory: 8Gi
pods: "10"
services: "5"
configmaps: "10"
secrets: "10"
services.loadbalancers: "1"
persistentvolumeclaims: "4"
requests.storage: 20Gi
namespace: team-a
A quota lives in, and only counts, its own namespace.
Compute
Caps the sum of requests and limits of all Pods in the namespace. Important side effect: once a quota covers requests.cpu, every new Pod must declare a CPU request, or it is rejected. A LimitRange with defaults fixes that.
Object counts
How many Pods, Services, ConfigMaps… may exist. services.loadbalancers: "1" is a cheap way to stop surprise cloud bills.
Storage
Caps disk claims (covered with volumes later).
kubectl apply still says "created". The ReplicaSet just cannot create Pods. Look with kubectl describe rs or kubectl get events:Warning FailedCreate replicaset/posts-depl-7d9f8 Error creating: pods "posts-depl-7d9f8-x2k" is forbidden:
exceeded quota: team-quota, requested: requests.cpu=500m, used: requests.cpu=1800m, limited: requests.cpu=2LimitRange
Rules for each container in the namespace: fill in what is missing, and refuse what is out of bounds.
apiVersion: v1
kind: LimitRange
metadata:
name: container-defaults
namespace: team-a
spec:
limits:
- type: Container
defaultRequest:
cpu: 250m
memory: 256Mi
default:
cpu: 500m
memory: 512Mi
min:
cpu: 50m
memory: 64Mi
max:
cpu: "2"
memory: 2Gi
defaultRequest
A container with no request gets this one, filled in automatically when the Pod is created. Your YAML stays unchanged; kubectl get pod -o yaml shows the injected values.
default
The default limit for containers that set none. (Yes, the field for limits is just called default.)
min
Asking for less is refused. Stops "1m CPU" tricks to squeeze past a quota.
max
Asking for more is refused: no single container may grab 8 CPUs in this namespace.
Error: pods "big" is forbidden: maximum cpu usage per Container is 2, but limit is 4Try them together
Namespace team-a has a quota of 2 CPU, 4Gi and 4 Pods. First add Pods with "not set" requests and the LimitRange off, then turn it on:
- No requests + quota on requests → rejected ("must specify").
- Same Pod with a LimitRange → defaults filled in, accepted.
- Going past the total → rejected with exactly which resource is exhausted.
Checking with kubectl
$ kubectl describe resourcequota team-quota -n team-a
Name: team-quota
Namespace: team-a
Resource Used Hard
-------- ---- ----
pods 3 10
requests.cpu 1500m 2
requests.memory 2Gi 4Gi
limits.cpu 3 4
limits.memory 4Gi 8Gi
services 2 5Used versus allowed: the first place to look when Pods will not appear.
$ kubectl describe limitrange container-defaults -n team-a
Type Resource Min Max Default Request Default Limit
---- -------- --- --- --------------- -------------
Container cpu 50m 2 250m 500m
Container memory 64Mi 2Gi 256Mi 512MiRecap
- A namespace is a folder in the cluster; quotas and LimitRanges apply per namespace.
- ResourceQuota: a total budget (CPU, memory, object counts) for the namespace. Over budget means refused at creation.
- LimitRange: per-container defaults (
defaultRequest,default) and bounds (min,max). - A compute quota requires every Pod to set requests, so pair it with a LimitRange.
- Blocked Deployment Pods show up in
kubectl get events, not inapplyoutput.
Quick check
team-a. kubectl get deploy shows READY 1/3 and only one Pod exists, not even Pending ones. What do you check?Show answer
The quota. Pods that would exceed it are never created, so they do not even appear as Pending. kubectl describe resourcequota -n team-a and kubectl get events -n team-a will show "exceeded quota".
ResourceQuota and LimitRange: common questions
What is the difference between ResourceQuota and LimitRange?
A ResourceQuota caps the total resources and objects in a namespace. A LimitRange sets default requests and limits, and minimum and maximum values, for each container.