Inhoudsopgave
- Waarom namespaces resource-limieten nodig hebben
- ResourceQuota vs. LimitRange: wat elk afdwingt
- Pas een LimitRange toe voor de ResourceQuota
- Een ResourceQuota voor compute, storage en object counts
- De "must specify limits.memory"-fout: oorzaak en oplossing
- Huidig quotagebruik bekijken met kubectl describe
- Quota-templates: productie vs staging
- Hoe HPA met ResourceQuota interacteert
- ResourceQuota-scopes
- Wat ResourceQuota en LimitRange niet doen
- Referentie: elk ResourceQuota-veld
- Referentie: elk LimitRange-veld
Waarom namespaces resource-limieten nodig hebben
Een Kubernetes-namespace is een label, geen hek. Zonder expliciete limieten kan elke pod in elke namespace zoveel CPU en geheugen claimen als het cluster vrij heeft, alle beschikbare IP's opeisen, etcd vullen met ConfigMaps, of een node in MemoryPressure duwen waardoor onverwante workloads worden geëvicteerd. ResourceQuota en LimitRange zijn de twee admission-controls die een namespace omtoveren van een label tot een echte resource-grens.
Allebei zijn admission controllers, allebei zijn standaard ingeschakeld op elk standaard-conform cluster (de plugins LimitRanger en ResourceQuota staan in de default-plugins-lijst sinds Kubernetes 1.36), en allebei doen ze niets totdat je daadwerkelijk de bijbehorende objecten in een namespace aanmaakt. De aanwezigheid van de admission plugin is de motor; een ResourceQuota- of LimitRange-object is de brandstof.
Dit artikel behandelt allebei: hoe je ze veilig toepast, de foutmelding die elk team de eerste keer raakt bij een quota-uitrol, en een complete referentie voor elk spec-veld.
ResourceQuota vs. LimitRange: wat elk afdwingt
Deze twee objecten lijken oppervlakkig op elkaar (beide zijn namespace-scoped, beide begrenzen resourceverbruik) maar ze handhaven verschillende dingen op verschillende momenten in de admission-pipeline.
| Aspect | ResourceQuota | LimitRange |
|---|---|---|
| Bereik | Totalen over alle pods in de namespace | Per pod of per container |
| Wat het doet | Begrenst totale CPU, geheugen, storage en object counts | Zet default requests/limits en bodems en plafonds per container |
| Wanneer het werkt | Validateert bij admission; wijst verzoeken af die het plafond zouden overschrijden | Muteert bij admission (injecteert defaults), valideert tegen min/max |
| Admission plugin | ResourceQuota (validating) |
LimitRanger (mutating + validating) |
| Foutgedrag | Pod-creatie geweigerd met HTTP 403 Forbidden | Pod-creatie geweigerd als buiten min/max-grenzen |
| Typische units | requests.cpu: "10", pods: "100" |
default.cpu: 500m, max.memory: 8Gi |
| Stopt een hebberige pod | Nee, alleen het totaal | Ja, via max |
| Stopt de hele tenant | Ja, via hard-totalen |
Nee, alleen individuele pods |
Je wilt bijna altijd allebei. ResourceQuota voorkomt dat een tenant collectief het cluster opslokt. LimitRange voorkomt dat een container in die tenant in een enkele pod het hele quotum opmaakt, en biedt defaults zodat developers niet bij elke workload requests en limits hoeven mee te geven.
Pas een LimitRange toe voor de ResourceQuota
De volgorde doet ertoe. Zodra een ResourceQuota cpu of memory tracked, weigert de admission controller elke nieuwe pod die de bijbehorende requests of limits niet specificeert. LimitRange-defaults worden geïnjecteerd voor die check, dus door de LimitRange als eerste neer te zetten voorkom je dat bestaande workloads breken zodra de quota erbij komt.
# limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: team-payments
spec:
limits:
- type: Container
default: # geïnjecteerd als limits wanneer de container ze weglaat
cpu: 500m
memory: 512Mi
defaultRequest: # geïnjecteerd als requests wanneer de container ze weglaat
cpu: 100m
memory: 128Mi
max: # plafond per container
cpu: "4"
memory: 8Gi
min: # bodem per container
cpu: 50m
memory: 64Mi
maxLimitRequestRatio: # begrens de verhouding limit/request
cpu: "10" # limit mag maximaal 10x de request zijn
kubectl apply -f limitrange.yaml
Twee operationele opmerkingen. Houd één LimitRange per namespace aan. Meerdere LimitRange-objecten geven niet-deterministische default-injectie omdat de admission plugin er doorheen loopt en per resource de laatste match wint. Als default en defaultRequest identiek zijn, krijgt elke pod die resource-specs weglaat Guaranteed QoS, wat invloed heeft op eviction-prioriteit. Voor Burstable QoS als default (de gebruikelijkere keuze voor generieke workloads), zet defaultRequest lager dan default. De mechanica van QoS-klassen staat in Kubernetes resource requests en limits.
Een ResourceQuota voor compute, storage en object counts
Zodra de LimitRange staat, pas je de ResourceQuota toe. Een complete productie-stijl quota dekt vier families: compute (cpu, memory), storage (PVC-aantal en totale grootte), object counts (pods, services, secrets), en optioneel object counts voor willekeurige API-resources via de generieke count/<resource>.<group>-syntax.
# resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-payments-quota
namespace: team-payments
spec:
hard:
# Compute
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
# Object counts (ingebouwde shortcuts)
pods: "100"
services: "10"
services.loadbalancers: "2"
secrets: "30"
configmaps: "30"
persistentvolumeclaims: "5"
# Storage
requests.storage: 100Gi
fast-ssd.storageclass.storage.k8s.io/requests.storage: 50Gi
fast-ssd.storageclass.storage.k8s.io/persistentvolumeclaims: "3"
# Generieke count/* voor elke API-resource
count/deployments.apps: "20"
count/jobs.batch: "10"
count/ingresses.networking.k8s.io: "5"
kubectl apply -f resourcequota.yaml
De count/<resource>.<group>-syntax is beschikbaar sinds Kubernetes 1.9 en werkt voor elke API-resource, inclusief third-party CRD's (je kunt count/argocd-applications.argoproj.io quoten als Argo CD geïnstalleerd staat). Het is de juiste keuze wanneer je een resource-type wilt begrenzen dat de ingebouwde shortcuts niet dekken.
Quota voor extended resources (meestal GPU's) is toegevoegd in Kubernetes 1.10 en gebruikt de vorm requests.nvidia.com/gpu: "4". Voor extended resources is alleen het requests.-prefix toegestaan; overcommit via limits niet.
De "must specify limits.memory"-fout: oorzaak en oplossing
Dit is de foutmelding die elk team de eerste keer ziet bij een ResourceQuota:
Error from server (Forbidden): error when creating "deployment.yaml":
pods is forbidden: failed quota: team-payments-quota:
must specify limits.memory,requests.memory
Wat het betekent. De namespace heeft een ResourceQuota die requests.memory of limits.memory tracked. De pod die de deployment probeert aan te maken specificeert die velden niet, en er staat geen LimitRange in de namespace om defaults te injecteren. De admission controller weigert een pod waarvan hij het geheugenverbruik niet kan toerekenen aan de quota.
Drie oplossingen, op volgorde van voorkeur.
1. Voeg een LimitRange toe die defaults injecteert. Dit is voor de meeste teams de juiste oplossing. De LimitRange uit de vorige sectie definieert default en defaultRequest, die de admission plugin injecteert in elke pod die ze weglaat. Pods die zonder resource-specs zijn geschreven, worden zo automatisch geldig tegen de quota. Een LimitRange toepassen herstelt al gefaalde pods niet met terugwerkende kracht; je moet de deployment opnieuw uitrollen nadat de LimitRange staat.
2. Voeg expliciete requests en limits toe in de pod-spec. Pas het deployment-manifest aan:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
Dit is de aanpak wanneer je elk resourceprofiel hard in het manifest wilt hebben, zonder impliciete defaults uit een LimitRange. Het levert de meest reviewbare manifests op, maar elke developer in de namespace moet weten dat dit moet.
3. Haal limits.memory uit de quota. Wil je alleen totalen voor requests begrenzen (geen limits), verwijder dan limits.cpu en limits.memory uit de ResourceQuota-spec. De admission plugin verplicht alleen velden die de quota daadwerkelijk tracked. Dit past bij namespaces waar limits met opzet sterk variëren en je geen vast plafond op cumulatieve limits wilt.
Je weet dat het werkt wanneer kubectl apply -f deployment.yaml succesvol terugkomt en kubectl get pods -n team-payments de nieuwe pods running laat zien.
Een subtiel gedrag verrast veel teams. Het aanmaken van een Deployment die de quota overschrijdt laat het Deployment-object zelf gewoon slagen. De Deployment wordt aangemaakt. Alleen de Pod-creatie daarbinnen faalt. kubectl get deployment toont een gezond ogende resource met nul ready replicas; kubectl describe deployment <naam> of kubectl get events -n <namespace> --field-selector reason=FailedCreate onthult de 403-fout. Check altijd events wanneer een deployment er gezond uitziet maar nooit ready pods produceert.
Huidig quotagebruik bekijken met kubectl describe
kubectl describe resourcequota is het werkpaard voor quota-debugging. Het laat het huidige verbruik zien tegen elke getrackte dimensie:
kubectl describe resourcequota team-payments-quota -n team-payments
Verwachte output:
Name: team-payments-quota
Namespace: team-payments
Resource Used Hard
-------- ---- ----
configmaps 8 30
count/deployments.apps 5 20
count/ingresses.networking.k8s.io 1 5
count/jobs.batch 0 10
limits.cpu 4500m 20
limits.memory 9Gi 40Gi
persistentvolumeclaims 2 5
pods 12 100
requests.cpu 2100m 10
requests.memory 4Gi 20Gi
requests.storage 20Gi 100Gi
secrets 14 30
services 3 10
services.loadbalancers 1 2
Twee dingen om af te lezen. De Used-kolom is wat operationeel telt. Alles boven 80% van Hard is een vroege indicator dat de volgende deployment gaat falen. Daarnaast: quota is niet retroactief. Als pods al draaiden voordat de quota werd toegepast, verschijnt hun verbruik direct onder Used, maar ze worden niet geëvicteerd om ruimte te maken.
Voor monitoring op schaal: installeer kube-state-metrics en alarmeer op de ratio kube_resourcequota{type="used"} / kube_resourcequota{type="hard"} boven 0,85. De Prometheus-monitoring-gids behandelt de installatie van kube-state-metrics in detail.
Quota-templates: productie vs staging
Twee quota-templates die ik in version control bewaar en per tenant aanpas. Het zijn startpunten, geen absolute waarden; observeer een sprint of twee en stel bij.
Productie-tenant (klein tot middelgroot serviceteam)
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: team-payments
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "200"
persistentvolumeclaims: "10"
requests.storage: 200Gi
services: "20"
services.loadbalancers: "3"
secrets: "50"
configmaps: "50"
count/deployments.apps: "30"
De compute-headroom staat ongeveer 30% boven het verwachte steady-state-verbruik om ruimte te laten voor rolling updates zonder dat de quota uitgeput raakt. Service- en LoadBalancer-aantallen zijn strak om onbedoelde kosten te voorkomen (elke LoadBalancer mapt naar een cloud load balancer met eigen maandkosten).
Staging-tenant (kleiner, wegwerp-vriendelijk)
apiVersion: v1
kind: ResourceQuota
metadata:
name: staging-quota
namespace: team-payments-staging
spec:
hard:
requests.cpu: "5"
requests.memory: 10Gi
limits.cpu: "10"
limits.memory: 20Gi
pods: "50"
persistentvolumeclaims: "5"
requests.storage: 50Gi
services: "10"
services.loadbalancers: "0" # geen cloud load balancers in staging
secrets: "30"
Staging schroeft compute aan, weigert LoadBalancers volledig (gebruik port-forward of een Ingress voor staging-toegang) en gaat uit van vluchtige workloads. De lagere pod-cap dwingt developers ook om hun oude staging-namespaces op te ruimen, wat precies de bedoeling is.
Een multi-tenant cluster wil meestal beide templates parametriseerbaar via een Helm-chart of Kustomize-overlay zodat het onboarden van een tenant één PR is.
Hoe HPA met ResourceQuota interacteert
HPA omzeilt de quota niet. De Horizontal Pod Autoscaler schaalt door het spec.replicas-veld van een Deployment of ander workload-controller-object aan te passen. De controller probeert dan nieuwe pods aan te maken, en die pod-creatie loopt door dezelfde admission-pipeline als elke andere pod. Als de nieuwe replicas het verbruik boven de quota zouden duwen, faalt de pod-creatie met HTTP 403 en stopt HPA effectief met opschalen, ook al zegt de metric dat hij omhoog moet.
Het zichtbare symptoom: HPA meldt desiredReplicas: 12 in kubectl describe hpa <naam>, maar kubectl get deployment <naam> toont READY 8/12. Events op de deployment of replicaset laten FailedCreate met een quota-fout zien.
Drie aanpakken:
- Stel de quota in op HPA's max replicas. Als HPA tot 20 replicas van 500m CPU kan opschalen, moet de quota minimaal 10 CPU bovenop andere workloads accommoderen. Dit is de juiste aanpak voor namespaces waar HPA het belangrijkste schaalmechanisme is.
- Zet HPA's
maxReplicaszodat het binnen de quota past. Begrens de autoscaler zodat hij de quota nooit probeert te overschrijden. De trade-off: verkeer boven wat de cap kan bedienen wordt gedropt of in een queue gezet. - Ontkoppel staging- en productie-quota's. Hou strakke quota's op staging waar bursten niet nodig is, en ruime quota's op productie waar HPA zijn werk moet kunnen doen. De
prod- enstaging-templates hierboven implementeren dit impliciet.
Wat je ook kiest, zet de alert op used/hard > 0,85 uit de vorige sectie op. HPA-gedreven quota-uitputting is op Deployment-niveau stil totdat je events leest.
ResourceQuota-scopes
Een ResourceQuota tracked standaard elke pod in de namespace. Met scopes kun je aparte quota's maken die alleen specifieke subsets pods tellen, wat de juiste tool is wanneer je verschillende plafonds wilt voor batch-jobs versus services, of voor pods met hoge versus lage prioriteit.
Er zijn zes scopes beschikbaar, met verschillende stabiliteitsniveaus:
| Scope | Wat het matched | Stabiliteit |
|---|---|---|
BestEffort |
Pods zonder requests of limits op enige container | Core (altijd beschikbaar) |
NotBestEffort |
Pods met minstens één request of limit gezet | Core |
Terminating |
Pods met .spec.activeDeadlineSeconds >= 0 (meestal Jobs) |
Core |
NotTerminating |
Pods met .spec.activeDeadlineSeconds niet gezet (services) |
Core |
PriorityClass |
Pods die een specifieke PriorityClass referencen | Stabiel sinds Kubernetes 1.17 |
CrossNamespacePodAffinity |
Pods die cross-namespace pod-affinity-termen gebruiken | Stabiel sinds Kubernetes 1.24 |
Scope-voorbeelden:
# Begrens batch-jobs (Terminating) zonder service-quota's te raken
apiVersion: v1
kind: ResourceQuota
metadata:
name: batch-jobs-quota
namespace: team-payments
spec:
hard:
requests.cpu: "5"
requests.memory: 10Gi
pods: "20"
scopes:
- Terminating
# Reserveer capaciteit voor alleen high-priority pods
apiVersion: v1
kind: ResourceQuota
metadata:
name: high-priority-quota
namespace: team-payments
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values:
- high-priority
# Blokkeer cross-namespace pod-affinity in een tenant-namespace
apiVersion: v1
kind: ResourceQuota
metadata:
name: deny-cross-ns-affinity
namespace: team-payments
spec:
hard:
pods: "0"
scopeSelector:
matchExpressions:
- operator: Exists
scopeName: CrossNamespacePodAffinity
Het laatste voorbeeld is een bewust deny-patroon: pods: "0" op de scope CrossNamespacePodAffinity zetten weigert elke pod die een cross-namespace affinity-term probeert te gebruiken, en dat is de aanbevolen manier om te voorkomen dat tenants failure domains blokkeren voor andere tenants.
Scopes kunnen worden gecombineerd. Een quota die alleen op niet-best-effort, niet-terminerende, high-priority pods slaat is een geldige constructie, al wordt alles boven twee scopes lastig om over na te denken.
Wat ResourceQuota en LimitRange niet doen
Deze sectie staat hier omdat elk veelvoorkomend misverstand over deze objecten een outage in de wachtrij is.
Ze zijn niet hetzelfde. Een ResourceQuota zonder LimitRange werkt wel, maar breekt elke pod die resource-specs weglaat. Een LimitRange zonder ResourceQuota injecteert defaults maar begrenst totaalverbruik niet. Ze hebben een ander doel en zijn ontworpen om samen gebruikt te worden.
Geen LimitRange betekent niet dat pods zonder limits prima zijn. Zodra een ResourceQuota cpu of memory tracked, falen pods zonder die velden bij admission. De foutmelding must specify limits.memory is het zichtbare gevolg. LimitRange is de tool die pods zonder expliciete specs alsnog geldig maakt; het is niet optioneel zodra er een ResourceQuota staat.
ResourceQuota beschermt nodes niet tegen overcommit. Het rekent requests en limits af bij admission, maar dwingt op runtime niets af. Een namespace met limits.memory: 100Gi quota op een cluster met in totaal 50Gi geheugen accepteert pods tot 100Gi limiet. Als die pods allemaal tegelijk geheugen gaan gebruiken, is het geheugen op voordat de kubelet kan ingrijpen. Bescherming op nodeniveau komt van eviction-thresholds en de reserved-memory-config van de kubelet, niet van quota's.
CPU-throttling gebeurt op limits, niet op requests. requests.cpu in ResourceQuota is een scheduling-tijd accounting-veld. Daadwerkelijke CPU-throttling, wanneer een container zijn allocatie overschrijdt, wordt door de Linux-kernel afgedwongen op basis van de limits.cpu per container. Een container met requests.cpu: 100m zonder limit burst vrijuit. De quota voorkomt dat niet; alleen de limit per container doet dat.
LimitRange max is geen quota. Het begrenst individuele containers (geen container in deze namespace mag meer dan 4 CPU's vragen) maar zegt niets over de som binnen de namespace. Een namespace met max.cpu: 4 en geen quota kan duizend pods elk met 4 CPU draaien.
Quota is niet retroactief. Bestaande pods worden niet geëvicteerd wanneer een quota wordt toegepast die ze zouden overschrijden. Hun verbruik staat direct onder Used, maar ze blijven draaien. Alleen nieuwe pod-creatie loopt door de quotacheck. Wil je een striktere quota op bestaande workloads afdwingen, restart dan hun controllers (kubectl rollout restart deployment <naam>) en laat de nieuwe pods erin passen of falen.
Referentie: elk ResourceQuota-veld
Deze sectie catalogiseert elk veld dat een ResourceQuota-object kan dragen. Het schema dekt API-versie v1, stabiel sinds Kubernetes 1.0; nieuwe resource-types en scopes worden binnen het bestaande schema toegevoegd, niet via breaking API-changes.
spec.hard
Een map van benoemde resources naar quantities. Elke resource die de quota tracked, staat hier.
Compute-resources:
| Veld | Beschrijving |
|---|---|
requests.cpu (of cpu) |
Som van requests.cpu over alle niet-terminale pods mag dit niet overschrijden. |
requests.memory (of memory) |
Som van requests.memory over alle niet-terminale pods mag dit niet overschrijden. |
limits.cpu |
Som van limits.cpu over alle niet-terminale pods. |
limits.memory |
Som van limits.memory over alle niet-terminale pods. |
hugepages-<size> |
Som van huge-page-requests van de gegeven grootte (bijvoorbeeld hugepages-2Mi). |
requests.ephemeral-storage |
Som van ephemeral-storage-requests over alle pods. |
limits.ephemeral-storage |
Som van ephemeral-storage-limits over alle pods. |
requests.<extended-resource> |
Som van requests voor een extended resource (bijvoorbeeld requests.nvidia.com/gpu). Beschikbaar sinds Kubernetes 1.10. |
Storage-resources:
| Veld | Beschrijving |
|---|---|
requests.storage |
Som van spec.resources.requests.storage over alle PVC's in de namespace. |
persistentvolumeclaims |
Totaal aantal PVC's dat in de namespace mag bestaan. |
<storage-class>.storageclass.storage.k8s.io/requests.storage |
Som van requests.storage voor PVC's die een specifieke StorageClass referencen. |
<storage-class>.storageclass.storage.k8s.io/persistentvolumeclaims |
Aantal toegestane PVC's voor een specifieke StorageClass. |
Object counts (ingebouwde shortcuts):
| Veld | Beschrijving |
|---|---|
pods |
Totaal niet-terminale pods. |
services |
Totaal Services. |
services.loadbalancers |
Services van type LoadBalancer. |
services.nodeports |
Services van type NodePort. |
secrets |
Totaal Secrets. |
configmaps |
Totaal ConfigMaps. |
persistentvolumeclaims |
Totaal PVC's (staat ook onder storage). |
replicationcontrollers |
Totaal ReplicationControllers. |
resourcequotas |
Totaal ResourceQuotas (zelden getrackt). |
Object counts (generieke syntax, beschikbaar sinds Kubernetes 1.9):
| Veld | Beschrijving |
|---|---|
count/<resource>.<group> |
Totaal objecten van het gegeven type. Werkt voor core API-resources (count/pods), built-in groepen (count/deployments.apps, count/jobs.batch, count/ingresses.networking.k8s.io) en CRD's (count/argocd-applications.argoproj.io). |
spec.scopes
Een optionele lijst van scope-namen. De quota telt alleen objecten die op alle opgegeven scopes matchen. Geldige waarden:
| Scope | Beschrijving | Stabiliteit |
|---|---|---|
BestEffort |
Pods zonder requests of limits op enige container. | Core |
NotBestEffort |
Pods met minstens één request of limit gezet. | Core |
Terminating |
Pods met spec.activeDeadlineSeconds >= 0. |
Core |
NotTerminating |
Pods met spec.activeDeadlineSeconds niet gezet. |
Core |
PriorityClass |
Pods die een PriorityClass referencen (gebruik met scopeSelector). |
Stabiel sinds 1.17 |
CrossNamespacePodAffinity |
Pods met cross-namespace pod-affinity-termen. | Stabiel sinds 1.24 |
BestEffort en NotBestEffort sluiten elkaar uit, net als Terminating en NotTerminating. Onverenigbare scopes combineren levert een quota op die niets matched.
spec.scopeSelector
Een uitdrukkingsrijker alternatief voor spec.scopes. Verplicht bij scopen op PriorityClass.
scopeSelector:
matchExpressions:
- operator: In | NotIn | Exists | DoesNotExist
scopeName: PriorityClass | CrossNamespacePodAffinity | <ander>
values:
- <waarde>
operator moet In of NotIn zijn als values niet leeg is, en Exists of DoesNotExist als values leeg is.
status.hard en status.used
Read-only velden die de ResourceQuota-controller invult. hard spiegelt spec.hard; used rapporteert het huidige verbruik per getrackte resource. Dit is wat kubectl describe resourcequota afleest.
Referentie: elk LimitRange-veld
LimitRange is ook een stabiele v1-API. Elke entry in spec.limits is één constraint-blok.
spec.limits[].type
Het type object waarop de constraint slaat. Drie waarden worden ondersteund:
| Type | Wat het begrenst |
|---|---|
Container |
Individuele containers (de meest voorkomende). Accepteert default, defaultRequest, min, max, maxLimitRequestRatio. |
Pod |
Totaal over alle containers in een pod. Accepteert min, max, maxLimitRequestRatio. Accepteert default of defaultRequest niet. |
PersistentVolumeClaim |
Storage gevraagd door PVC's in de namespace. Accepteert min en max voor de storage-resource. |
spec.limits[].default
Een map van resource-namen naar quantities. Wordt geïnjecteerd als limits in elke container die ze niet specificeert. Werkt alleen bij type: Container.
default:
cpu: 500m
memory: 512Mi
spec.limits[].defaultRequest
Zelfde vorm als default, maar geïnjecteerd als requests. Werkt alleen bij type: Container.
defaultRequest:
cpu: 100m
memory: 128Mi
Als defaultRequest gelijk is aan default, is de resulterende pod Guaranteed QoS. Wil je standaard Burstable QoS-pods, zet defaultRequest lager dan default.
spec.limits[].min
Bodem per resource. Een container of PVC die er minder dan vraagt wordt geweigerd bij admission met een duidelijke foutmelding die de resource benoemt.
min:
cpu: 50m
memory: 64Mi
storage: 1Gi # alleen bij type: PersistentVolumeClaim
spec.limits[].max
Plafond per resource. Een container of PVC die er meer dan vraagt wordt geweigerd.
max:
cpu: "4"
memory: 8Gi
storage: 100Gi # alleen bij type: PersistentVolumeClaim
spec.limits[].maxLimitRequestRatio
Een plafond op de verhouding limit / request voor een gegeven resource, uitgedrukt als quantity. Een waarde van "4" betekent dat de limit van een container maximaal 4x de request mag zijn.
maxLimitRequestRatio:
cpu: "10"
memory: "4"
Dit is het veld dat voorkomt dat een developer requests.cpu: 100m zet met limits.cpu: 8000m, waardoor één container alsnog naar 8 cores kan bursten op een node waar hij gescheduled werd op basis van slechts 100m. In multi-tenant clusters is een ratio-cap van 4 tot 10 een verdedigbare default.
Hoe LimitRange met admission werkt
De LimitRanger admission plugin draait in twee fases. Eerst muteert hij pod-specs door default- en defaultRequest-waarden te injecteren voor containers die ze weglaten. Daarna valideert hij de resulterende pod tegen min, max en maxLimitRequestRatio. De mutatie gebeurt voordat de validatie van ResourceQuota loopt, en daarom werken LimitRange en ResourceQuota samen: de LimitRange vult de gaten op voordat de quota op missende velden checkt.
Meerdere LimitRange-objecten in een namespace zijn technisch toegestaan, maar leveren niet-deterministische injectie omdat de plugin er doorheen loopt en per resource de laatste match wint. Hou het bij één LimitRange per namespace.
Voor het bredere namespace-isolatie-patroon dat ResourceQuota en LimitRange combineert met NetworkPolicy, RBAC en Pod Security Standards, zie de multi-tenancy-walkthrough.