Policy: quota-and-limit-range-in-ns
Create ResourceQuota and LimitRange objects in organization namespaces.
Category |
Resource Quota |
Minimum Kyverno version |
v1 |
Subject |
APPUiO Organizations |
Policy types |
|
Implementation |
This policy generates ResourceQuota
and LimitRange
objects in namespaces which have the appuio.io/organization
label.
The default values for the generated ResourceQuota
and LimitRange
objects are configured in component parameters generatedResourceQuota
and generatedLimitRange
respectively.
Quota entries can be overridden for single namespaces by annotating the namespace, see the parameter docs for an example.
If field synchronize
in the ResourceQuota
or LimitRange
component parameter is set to true
, the policy is configured to continuously keep the generated objects in sync with the specification in the policy.
Policy Definition
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
annotations:
policies.kyverno.io/category: Resource Quota
policies.kyverno.io/description: |
This policy generates `ResourceQuota` and `LimitRange` objects in namespaces which have the `appuio.io/organization` label.
The default values for the generated `ResourceQuota` and `LimitRange` objects are configured in component parameters xref:references/parameters.adoc#_generatedresourcequota[`generatedResourceQuota`] and xref:references/parameters.adoc#_generatedlimitrange[`generatedLimitRange`] respectively.
Quota entries can be overridden for single namespaces by annotating the namespace, see the xref:references/parameters.adoc#_generatedresourcequota_spec[parameter docs] for an example.
If field `synchronize` in the `ResourceQuota` or `LimitRange` component parameter is set to `true`, the policy is configured to continuously keep the generated objects in sync with the specification in the policy.
policies.kyverno.io/jsonnet: component/quota-limitrange.jsonnet
policies.kyverno.io/minversion: v1
policies.kyverno.io/subject: APPUiO Organizations
policies.kyverno.io/title: Create ResourceQuota and LimitRange objects in organization
namespaces.
labels:
app.kubernetes.io/component: appuio-cloud
app.kubernetes.io/managed-by: commodore
app.kubernetes.io/name: appuio-cloud
name: quota-and-limit-range-in-ns
name: quota-and-limit-range-in-ns
spec:
rules:
- generate:
data:
spec:
limits:
- default:
cpu: 600m
memory: 768Mi
defaultRequest:
cpu: 10m
memory: 100Mi
min:
cpu: 10m
ephemeral-storage: 100Ki
memory: 4Mi
type: Container
kind: LimitRange
name: organization
namespace: '{{request.object.metadata.name}}'
synchronize: true
match:
all:
- resources:
kinds:
- Namespace
selector:
matchExpressions:
- key: appuio.io/organization
operator: Exists
name: generate-limit-range
- generate:
data:
spec:
hard:
limits.cpu: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute.limits.cpu"
|| ''8'' }}'
limits.memory: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute.limits.memory"
|| ''20Gi'' }}'
pods: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute.pods"
|| ''45'' }}'
requests.cpu: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute.requests.cpu"
|| ''4'' }}'
requests.memory: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute.requests.memory"
|| ''4Gi'' }}'
scopes:
- NotTerminating
kind: ResourceQuota
name: organization-compute
namespace: '{{request.object.metadata.name}}'
synchronize: true
match:
all:
- resources:
kinds:
- Namespace
selector:
matchExpressions:
- key: appuio.io/organization
operator: Exists
name: generate-quota-organization-compute
- generate:
data:
spec:
hard:
limits.cpu: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute-terminating.limits.cpu"
|| ''4000m'' }}'
limits.memory: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute-terminating.limits.memory"
|| ''4Gi'' }}'
pods: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute-terminating.pods"
|| ''5'' }}'
requests.cpu: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute-terminating.requests.cpu"
|| ''500m'' }}'
requests.memory: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-compute-terminating.requests.memory"
|| ''2Gi'' }}'
scopes:
- Terminating
kind: ResourceQuota
name: organization-compute-terminating
namespace: '{{request.object.metadata.name}}'
synchronize: true
match:
all:
- resources:
kinds:
- Namespace
selector:
matchExpressions:
- key: appuio.io/organization
operator: Exists
name: generate-quota-organization-compute-terminating
- generate:
data:
spec:
hard:
cephfs-fspool-cluster.storageclass.storage.k8s.io/requests.storage: '{{
parse_json(request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.storageclasses"
|| ''{}'')."cephfs-fspool-cluster.storageclass.storage.k8s.io/requests.storage"
|| ''25Gi'' }}'
count/configmaps: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_configmaps"
|| ''150'' }}'
count/jobs.batch: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_jobs.batch"
|| ''150'' }}'
count/replicationcontrollers: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_replicationcontrollers"
|| ''100'' }}'
count/secrets: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_secrets"
|| ''150'' }}'
count/services: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_services"
|| ''20'' }}'
count/services.loadbalancers: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_services.loadbalancers"
|| ''0'' }}'
count/services.nodeports: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.count_services.nodeports"
|| ''0'' }}'
limits.ephemeral-storage: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.limits.ephemeral-storage"
|| ''500Mi'' }}'
localblock-storage.storageclass.storage.k8s.io/persistentvolumeclaims: '{{
parse_json(request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.storageclasses"
|| ''{}'')."localblock-storage.storageclass.storage.k8s.io/persistentvolumeclaims"
|| ''0'' }}'
openshift.io/imagestreams: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.openshift.io_imagestreams"
|| ''20'' }}'
openshift.io/imagestreamtags: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.openshift.io_imagestreamtags"
|| ''50'' }}'
persistentvolumeclaims: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.persistentvolumeclaims"
|| ''10'' }}'
rbd-storagepool-cluster.storageclass.storage.k8s.io/requests.storage: '{{
parse_json(request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.storageclasses"
|| ''{}'')."rbd-storagepool-cluster.storageclass.storage.k8s.io/requests.storage"
|| ''25Gi'' }}'
requests.ephemeral-storage: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.requests.ephemeral-storage"
|| ''250Mi'' }}'
requests.storage: '{{ request.object.metadata.annotations."resourcequota.appuio.io/organization-objects.requests.storage"
|| ''1000Gi'' }}'
kind: ResourceQuota
name: organization-objects
namespace: '{{request.object.metadata.name}}'
synchronize: true
match:
all:
- resources:
kinds:
- Namespace
selector:
matchExpressions:
- key: appuio.io/organization
operator: Exists
name: generate-quota-organization-objects