Created
June 28, 2024 08:09
-
-
Save iyalang/5129795a26176140eab5bbe5b267450c to your computer and use it in GitHub Desktop.
Kyverno policy for automated creation of Vertical Pod Autoscalers (VPAs)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
apiVersion: kyverno.io/v1 | |
kind: ClusterPolicy | |
metadata: | |
name: auto-vpa-creation | |
annotations: | |
policies.kyverno.io/title: Add default VPA | |
policies.kyverno.io/category: Cost Optimization | |
policies.kyverno.io/subject: Vertical Pod Autoscaler | |
policies.kyverno.io/description: >- | |
This policy creates a Vertical Pod Autoscaler for each new workload unless it already has one or is using a Horizontal Pod Autoscaler. | |
spec: | |
validationFailureAction: Enforce | |
background: true | |
generateExistingOnPolicyUpdate: true | |
rules: | |
- name: create-default-vpa-one-container | |
match: | |
any: | |
- resources: | |
kinds: | |
- DaemonSet | |
- Deployment | |
- StatefulSet | |
context: | |
- name: existingHPA | |
apiCall: | |
urlPath: '/apis/autoscaling/v2/namespaces/{{request.namespace}}/horizontalpodautoscalers' | |
jmesPath: "items[].spec.scaleTargetRef.name" | |
- name: existingVPA | |
apiCall: | |
urlPath: "/apis/autoscaling.k8s.io/v1/namespaces/{{request.namespace}}/verticalpodautoscalers" | |
jmesPath: "items[].spec.targetRef.name" | |
- name: autoVPACount | |
apiCall: | |
urlPath: '/apis/autoscaling.k8s.io/v1/namespaces/{{request.namespace}}/verticalpodautoscalers' | |
jmesPath: items[?metadata.labels."auto-vpa"] | [?spec.targetRef.name=='{{request.object.metadata.name}}'] | length(@) | |
- name: totalContainers | |
variable: | |
value: '{{ request.object.spec.template.spec.containers }}' | |
jmesPath: 'length(@)' | |
preconditions: | |
all: | |
- key: '{{request.operation}}' | |
operator: NotEquals | |
value: DELETE | |
- key: '{{request.object.metadata.name}}' | |
operator: AllNotIn | |
value: '{{existingHPA}}' | |
- key: '{{totalContainers}}' | |
operator: Equals | |
value: "1" | |
# Make sure there are no existing VPAs for this object | |
# UNLESS there is an auto VPA (then it's ok to update it). | |
any: | |
- key: '{{request.object.metadata.name}}' | |
operator: AllNotIn | |
value: '{{existingVPA}}' | |
- key: '{{ autoVPACount }}' | |
operator: Equals | |
value: 1 | |
exclude: | |
any: | |
- resources: | |
selector: | |
matchLabels: | |
auto-vpa/create: "false" | |
- resources: | |
namespaces: | |
- kube-system | |
- resources: | |
namespaceSelector: | |
matchExpressions: | |
- key: "auto-vpa/create" | |
operator: In | |
values: | |
- "false" | |
generate: | |
synchronize: true | |
apiVersion: autoscaling.k8s.io/v1 | |
kind: VerticalPodAutoscaler | |
name: '{{request.object.metadata.name}}-auto-vpa' | |
namespace: '{{request.object.metadata.namespace}}' | |
data: | |
metadata: | |
labels: | |
auto-vpa: "true" | |
ownerReferences: | |
- apiVersion: apps/v1 | |
kind: '{{request.object.kind}}' | |
name: '{{request.object.metadata.name}}' | |
uid: '{{request.object.metadata.uid}}' | |
spec: | |
targetRef: | |
apiVersion: "apps/v1" | |
kind: '{{request.object.kind}}' | |
name: '{{request.object.metadata.name}}' | |
updatePolicy: | |
updateMode: "Auto" | |
resourcePolicy: | |
containerPolicies: | |
- containerName: "*" | |
minAllowed: | |
cpu: 10m | |
memory: 32Mi | |
maxAllowed: | |
cpu: '{{request.object.spec.template.spec.containers[0].resources.requests.cpu}}' | |
memory: '{{request.object.spec.template.spec.containers[0].resources.requests.memory}}' | |
controlledResources: ["cpu", "memory"] | |
controlledValues: "RequestsOnly" | |
- name: create-default-vpa-multiple-containers | |
match: | |
any: | |
- resources: | |
kinds: | |
- DaemonSet | |
- Deployment | |
- StatefulSet | |
context: | |
- name: existingHPA | |
apiCall: | |
urlPath: "/apis/autoscaling/v2/namespaces/{{request.namespace}}/horizontalpodautoscalers" | |
jmesPath: "items[].spec.scaleTargetRef.name" | |
- name: existingVPA | |
apiCall: | |
urlPath: "/apis/autoscaling.k8s.io/v1/namespaces/{{request.namespace}}/verticalpodautoscalers" | |
jmesPath: "items[].spec.targetRef.name" | |
- name: autoVPACount | |
apiCall: | |
urlPath: '/apis/autoscaling.k8s.io/v1/namespaces/{{request.namespace}}/verticalpodautoscalers' | |
jmesPath: items[?metadata.labels."auto-vpa"] | [?spec.targetRef.name=='{{request.object.metadata.name}}'] | length(@) | |
- name: totalContainers | |
variable: | |
value: '{{request.object.spec.template.spec.containers}}' | |
jmesPath: 'length(@)' | |
preconditions: | |
all: | |
- key: '{{request.operation}}' | |
operator: NotEquals | |
value: DELETE | |
- key: '{{request.object.metadata.name}}' | |
operator: AllNotIn | |
value: '{{existingHPA}}' | |
- key: '{{totalContainers}}' | |
operator: NotEquals | |
value: "1" | |
# Make sure there are no existing VPAs for this object | |
# UNLESS there is an auto VPA (then it's ok to update it). | |
any: | |
- key: '{{request.object.metadata.name}}' | |
operator: AllNotIn | |
value: '{{existingVPA}}' | |
- key: '{{ autoVPACount }}' | |
operator: Equals | |
value: 1 | |
exclude: | |
any: | |
- resources: | |
selector: | |
matchLabels: | |
auto-vpa/create: "false" | |
- resources: | |
namespaces: | |
- kube-system | |
- resources: | |
namespaceSelector: | |
matchExpressions: | |
- key: "auto-vpa/create" | |
operator: In | |
values: | |
- "false" | |
generate: | |
synchronize: true | |
apiVersion: autoscaling.k8s.io/v1 | |
kind: VerticalPodAutoscaler | |
name: '{{request.object.metadata.name}}-auto-vpa' | |
namespace: '{{request.object.metadata.namespace}}' | |
data: | |
metadata: | |
labels: | |
auto-vpa: "true" | |
ownerReferences: | |
- apiVersion: apps/v1 | |
kind: '{{request.object.kind}}' | |
name: '{{request.object.metadata.name}}' | |
uid: '{{request.object.metadata.uid}}' | |
spec: | |
targetRef: | |
apiVersion: "apps/v1" | |
kind: '{{request.object.kind}}' | |
name: '{{request.object.metadata.name}}' | |
updatePolicy: | |
updateMode: "Auto" | |
resourcePolicy: | |
containerPolicies: | |
- containerName: "*" | |
minAllowed: | |
cpu: 10m | |
memory: 32Mi | |
controlledResources: ["cpu", "memory"] | |
controlledValues: "RequestsOnly" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment