Configure Quotas for Storage
This page shows how to configure quotas for PersistentVolumeClaims. You specify quotas in a ResourceQuota object.
Before you begin
You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a cluster, you can create one by using minikube or you can use one of these Kubernetes playgrounds:
To check the version, enter kubectl version
.
Create a namespace
Create a namespace so that the resources you create in this exercise are isolated from the rest of your cluster.
kubectl create namespace quota-object-example
Create a ResourceQuota
Here is the configuration file for a ResourceQuota object:
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota-demo
spec:
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"
Create the ResourceQuota:
kubectl apply -f https://k8s.io/examples/admin/resource/quota-objects.yaml --namespace=quota-object-example
View detailed information about the ResourceQuota:
kubectl get resourcequota object-quota-demo --namespace=quota-object-example --output=yaml
The output shows that in the quota-object-example namespace, there can be at most one PersistentVolumeClaim, at most two Services of type LoadBalancer, and no Services of type NodePort.
status:
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"
used:
persistentvolumeclaims: "0"
services.loadbalancers: "0"
services.nodeports: "0"
Create a PersistentVolumeClaim
Here is the configuration file for a PersistentVolumeClaim object:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-quota-demo
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
Create the PersistentVolumeClaim:
kubectl apply -f https://k8s.io/examples/admin/resource/quota-objects-pvc.yaml --namespace=quota-object-example
Verify that the PersistentVolumeClaim was created:
kubectl get persistentvolumeclaims --namespace=quota-object-example
The output shows that the PersistentVolumeClaim exists and has status Pending:
NAME STATUS
pvc-quota-demo Pending
Attempt to create a second PersistentVolumeClaim
Here is the configuration file for a second PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-quota-demo-2
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
Attempt to create the second PersistentVolumeClaim:
kubectl apply -f https://k8s.io/examples/admin/resource/quota-objects-pvc-2.yaml --namespace=quota-object-example
The output shows that the second PersistentVolumeClaim was not created, because it would have exceeded the quota for the namespace.
persistentvolumeclaims "pvc-quota-demo-2" is forbidden:
exceeded quota: object-quota-demo, requested: persistentvolumeclaims=1,
used: persistentvolumeclaims=1, limited: persistentvolumeclaims=1
Associate a ResourceQuota with a VolumeAttributesClass
This example creates a quota object and matches it with PVC at specific volume attributes classes. The example works as follows:
- PVCs in the cluster have at least one of the three VolumeAttributesClasses: "gold", "silver", "copper".
- One quota object is created for each volume attributes class.
Take a look at the following manifest:
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pvcs-gold
spec:
hard:
requests.storage: "10Gi"
persistentvolumeclaims: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: VolumeAttributesClass
values: ["gold"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pvcs-silver
spec:
hard:
requests.storage: "20Gi"
persistentvolumeclaims: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: VolumeAttributesClass
values: ["silver"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pvcs-copper
spec:
hard:
requests.storage: "30Gi"
persistentvolumeclaims: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: VolumeAttributesClass
values: ["copper"]
Apply the manifest using kubectl create
.
kubectl create -f https://k8s.io/examples/policy/quota-vax.yaml --namespace=quota-object-example
resourcequota/pvcs-gold created
resourcequota/pvcs-silver created
resourcequota/pvcs-copper created
Verify that Used
quota is 0
using kubectl describe quota
.
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 30Gi
Take a look at the following manifest:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gold-vac-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: # change this to the name of the storage class you want to use
volumeAttributesClassName: gold
Apply it with kubectl create
.
kubectl apply -f https://k8s.io/examples/policy/gold-vac-pvc.yaml --namespace=quota-object-example
Verify that "Used" stats for "gold" volume attributes class quota, pvcs-gold
has changed and that the other two quotas are unchanged.
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 30Gi
Once the PVC is bound, it is allowed to modify the desired volume attributes class. Let's change it to "silver" with kubectl patch
:
kubectl patch pvc gold-vac-pvc --type='merge' -p '{"spec":{"volumeAttributesClassName":"silver"}}'
Verify that "Used" stats for "silver" volume attributes class quota, pvcs-silver
has changed, pvcs-copper
is unchanged, and pvcs-gold
might be unchanged or released, which depends on the PVC's status.
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 30Gi
Let's change it to "copper" with kubectl patch
:
kubectl patch pvc gold-vac-pvc --type='merge' -p '{"spec":{"volumeAttributesClassName":"copper"}}'
Verify that "Used" stats for "copper" volume attributes class quota, pvcs-copper
has changed, pvcs-silver
and pvcs-gold
might be unchanged or released, which depends on the PVC's status.
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 30Gi
Print the manifest of the PVC using the following command:
kubectl get pvc gold-vac-pvc -o yaml
It might show the following output:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gold-vac-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: default
volumeAttributesClassName: copper
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 2Gi
currentVolumeAttributesClassName: gold
phase: Bound
modifyVolumeStatus:
status: InProgress
targetVolumeAttributesClassName: silver
storageClassName: default
Wait a moment for the volume modification to complete, then verify the quota again.
kubectl describe quota
Name: pvcs-gold
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 10Gi
Name: pvcs-silver
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
requests.storage 0 20Gi
Name: pvcs-copper
Namespace: default
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 1 10
requests.storage 2Gi 30Gi
Clean up
Delete your namespace:
kubectl delete namespace quota-object-example
What's next
You can also read Limit Storage Consumption
For cluster administrators
-
Configure Default Memory Requests and Limits for a Namespace
-
Configure Minimum and Maximum Memory Constraints for a Namespace
-
Configure Minimum and Maximum CPU Constraints for a Namespace