From 8a5239575adbbc124746f17dcf0c9d3515d45241 Mon Sep 17 00:00:00 2001 From: StevenLeiZhang Date: Tue, 3 Jan 2023 11:17:31 +0800 Subject: [PATCH] Feat: need one new Trait to support HorizontalPodAutoscaler of CPU/MEM/PodCustomMetrcs (#5225) Signed-off-by: StevenLeiZhang Signed-off-by: StevenLeiZhang --- .../templates/defwithtemplate/hpa.yaml | 110 ++++++++++++++++++ .../templates/defwithtemplate/hpa.yaml | 110 ++++++++++++++++++ references/docgen/def-doc/trait/hpa.eg.md | 55 +++++++++ .../definitions/internal/trait/hpa.cue | 106 +++++++++++++++++ .../usage-examples/application-with-hpa.yaml | 54 +++++++++ 5 files changed, 435 insertions(+) create mode 100644 charts/vela-core/templates/defwithtemplate/hpa.yaml create mode 100644 charts/vela-minimal/templates/defwithtemplate/hpa.yaml create mode 100644 references/docgen/def-doc/trait/hpa.eg.md create mode 100644 vela-templates/definitions/internal/trait/hpa.cue create mode 100644 vela-templates/definitions/usage-examples/application-with-hpa.yaml diff --git a/charts/vela-core/templates/defwithtemplate/hpa.yaml b/charts/vela-core/templates/defwithtemplate/hpa.yaml new file mode 100644 index 000000000..67a4a3c13 --- /dev/null +++ b/charts/vela-core/templates/defwithtemplate/hpa.yaml @@ -0,0 +1,110 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/hpa.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Configure k8s HPA for Deployment or Statefulsets + name: hpa + namespace: {{ include "systemDefinitionNamespace" . }} +spec: + appliesToWorkloads: + - deployments.apps + - statefulsets.apps + podDisruptive: false + schematic: + cue: + template: | + outputs: hpa: { + if context.clusterVersion.minor < 23 { + apiVersion: "autoscaling/v2beta2" + } + if context.clusterVersion.minor >= 23 { + apiVersion: "autoscaling/v2" + } + kind: "HorizontalPodAutoscaler" + metadata: name: context.name + spec: { + scaleTargetRef: { + apiVersion: parameter.targetAPIVersion + kind: parameter.targetKind + name: context.name + } + minReplicas: parameter.min + maxReplicas: parameter.max + metrics: [ + { + type: "Resource" + resource: { + name: "cpu" + target: { + type: parameter.cpu.type + if parameter.cpu.type == "Utilization" { + averageUtilization: parameter.cpu.value + } + if parameter.cpu.type == "AverageValue" { + averageValue: parameter.cpu.value + } + } + } + }, + if parameter.mem != _|_ { + { + type: "Resource" + resource: { + name: "memory" + target: { + type: parameter.mem.type + if parameter.cpu.type == "Utilization" { + averageUtilization: parameter.cpu.value + } + if parameter.cpu.type == "AverageValue" { + averageValue: parameter.cpu.value + } + } + } + } + }, + if parameter.podCustomMetrics != _|_ for m in parameter.podCustomMetrics { + type: "Pods" + pods: { + metric: name: m.name + target: { + type: "AverageValue" + averageValue: m.value + } + } + }, + ] + } + } + parameter: { + // +usage=Specify the minimal number of replicas to which the autoscaler can scale down + min: *1 | int + // +usage=Specify the maximum number of of replicas to which the autoscaler can scale up + max: *10 | int + // +usage=Specify the apiVersion of scale target + targetAPIVersion: *"apps/v1" | string + // +usage=Specify the kind of scale target + targetKind: *"Deployment" | string + cpu: { + // +usage=Specify resource metrics in terms of percentage("Utilization") or direct value("AverageValue") + type: *"Utilization" | "AverageValue" + // +usage=Specify the value of CPU utilization or averageValue + value: *50 | int + } + mem?: { + // +usage=Specify resource metrics in terms of percentage("Utilization") or direct value("AverageValue") + type: *"Utilization" | "AverageValue" + // +usage=Specify the value of MEM utilization or averageValue + value: *50 | int + } + // +usage=Specify custom metrics of pod type + podCustomMetrics?: [...{ + // +usage=Specify name of custom metrics + name: string + // +usage=Specify target value of custom metrics + value: string + }] + } + diff --git a/charts/vela-minimal/templates/defwithtemplate/hpa.yaml b/charts/vela-minimal/templates/defwithtemplate/hpa.yaml new file mode 100644 index 000000000..67a4a3c13 --- /dev/null +++ b/charts/vela-minimal/templates/defwithtemplate/hpa.yaml @@ -0,0 +1,110 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/hpa.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Configure k8s HPA for Deployment or Statefulsets + name: hpa + namespace: {{ include "systemDefinitionNamespace" . }} +spec: + appliesToWorkloads: + - deployments.apps + - statefulsets.apps + podDisruptive: false + schematic: + cue: + template: | + outputs: hpa: { + if context.clusterVersion.minor < 23 { + apiVersion: "autoscaling/v2beta2" + } + if context.clusterVersion.minor >= 23 { + apiVersion: "autoscaling/v2" + } + kind: "HorizontalPodAutoscaler" + metadata: name: context.name + spec: { + scaleTargetRef: { + apiVersion: parameter.targetAPIVersion + kind: parameter.targetKind + name: context.name + } + minReplicas: parameter.min + maxReplicas: parameter.max + metrics: [ + { + type: "Resource" + resource: { + name: "cpu" + target: { + type: parameter.cpu.type + if parameter.cpu.type == "Utilization" { + averageUtilization: parameter.cpu.value + } + if parameter.cpu.type == "AverageValue" { + averageValue: parameter.cpu.value + } + } + } + }, + if parameter.mem != _|_ { + { + type: "Resource" + resource: { + name: "memory" + target: { + type: parameter.mem.type + if parameter.cpu.type == "Utilization" { + averageUtilization: parameter.cpu.value + } + if parameter.cpu.type == "AverageValue" { + averageValue: parameter.cpu.value + } + } + } + } + }, + if parameter.podCustomMetrics != _|_ for m in parameter.podCustomMetrics { + type: "Pods" + pods: { + metric: name: m.name + target: { + type: "AverageValue" + averageValue: m.value + } + } + }, + ] + } + } + parameter: { + // +usage=Specify the minimal number of replicas to which the autoscaler can scale down + min: *1 | int + // +usage=Specify the maximum number of of replicas to which the autoscaler can scale up + max: *10 | int + // +usage=Specify the apiVersion of scale target + targetAPIVersion: *"apps/v1" | string + // +usage=Specify the kind of scale target + targetKind: *"Deployment" | string + cpu: { + // +usage=Specify resource metrics in terms of percentage("Utilization") or direct value("AverageValue") + type: *"Utilization" | "AverageValue" + // +usage=Specify the value of CPU utilization or averageValue + value: *50 | int + } + mem?: { + // +usage=Specify resource metrics in terms of percentage("Utilization") or direct value("AverageValue") + type: *"Utilization" | "AverageValue" + // +usage=Specify the value of MEM utilization or averageValue + value: *50 | int + } + // +usage=Specify custom metrics of pod type + podCustomMetrics?: [...{ + // +usage=Specify name of custom metrics + name: string + // +usage=Specify target value of custom metrics + value: string + }] + } + diff --git a/references/docgen/def-doc/trait/hpa.eg.md b/references/docgen/def-doc/trait/hpa.eg.md new file mode 100644 index 000000000..82e8cc62f --- /dev/null +++ b/references/docgen/def-doc/trait/hpa.eg.md @@ -0,0 +1,55 @@ +```yaml +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: helloworld +spec: + components: + - name: helloworld + type: webservice + properties: + cpu: "0.5" + exposeType: ClusterIP + image: oamdev/hello-world + memory: 1024Mi + ports: + - expose: true + port: 80 + protocol: TCP + traits: + - type: scaler + properties: + replicas: 1 + - type: hpa + properties: + targetAPIVersion: apps/v1 + targetKind: Deployment + max: 10 + min: 1 + cpu: + type: Utilization + value: 80 + mem: + type: AverageValue + value: 90 + podCustomMetrics: + # here are custom metric names and values. Please replace them to be your metrics + - name: pod_net_received_rate + value: "77" + - name: pod_net_transmitted_rate + value: "88" + - name: pod_net_received_packets_rate + value: "95" + - name: pod_net_transmitted_packets_rate + value: "99" + policies: + - name: apply-once + type: apply-once + properties: + enable: true + rules: + - strategy: + path: ["spec.replicas"] + selector: + resourceTypes: ["Deployment","StatefulSet"] +``` \ No newline at end of file diff --git a/vela-templates/definitions/internal/trait/hpa.cue b/vela-templates/definitions/internal/trait/hpa.cue new file mode 100644 index 000000000..c153dd23a --- /dev/null +++ b/vela-templates/definitions/internal/trait/hpa.cue @@ -0,0 +1,106 @@ +hpa: { + type: "trait" + annotations: {} + labels: {} + description: "Configure k8s HPA for Deployment or Statefulsets" + attributes: { + podDisruptive: false + appliesToWorkloads: ["deployments.apps", "statefulsets.apps"] + } +} +template: { + outputs: hpa: { + if context.clusterVersion.minor < 23 { + apiVersion: "autoscaling/v2beta2" + } + if context.clusterVersion.minor >= 23 { + apiVersion: "autoscaling/v2" + } + kind: "HorizontalPodAutoscaler" + metadata: name: context.name + spec: { + scaleTargetRef: { + apiVersion: parameter.targetAPIVersion + kind: parameter.targetKind + name: context.name + } + minReplicas: parameter.min + maxReplicas: parameter.max + metrics: [ + { + type: "Resource" + resource: { + name: "cpu" + target: { + type: parameter.cpu.type + if parameter.cpu.type == "Utilization" { + averageUtilization: parameter.cpu.value + } + if parameter.cpu.type == "AverageValue" { + averageValue: parameter.cpu.value + } + } + } + }, + if parameter.mem != _|_ { + { + type: "Resource" + resource: { + name: "memory" + target: { + type: parameter.mem.type + if parameter.cpu.type == "Utilization" { + averageUtilization: parameter.cpu.value + } + if parameter.cpu.type == "AverageValue" { + averageValue: parameter.cpu.value + } + } + } + } + }, + if parameter.podCustomMetrics != _|_ for m in parameter.podCustomMetrics { + type: "Pods" + pods: { + metric: { + name: m.name + } + target: { + type: "AverageValue" + averageValue: m.value + } + } + }, + ] + } + } + parameter: { + // +usage=Specify the minimal number of replicas to which the autoscaler can scale down + min: *1 | int + // +usage=Specify the maximum number of of replicas to which the autoscaler can scale up + max: *10 | int + // +usage=Specify the apiVersion of scale target + targetAPIVersion: *"apps/v1" | string + // +usage=Specify the kind of scale target + targetKind: *"Deployment" | string + cpu: { + // +usage=Specify resource metrics in terms of percentage("Utilization") or direct value("AverageValue") + type: *"Utilization" | "AverageValue" + // +usage=Specify the value of CPU utilization or averageValue + value: *50 | int + } + mem?: { + // +usage=Specify resource metrics in terms of percentage("Utilization") or direct value("AverageValue") + type: *"Utilization" | "AverageValue" + // +usage=Specify the value of MEM utilization or averageValue + value: *50 | int + } + // +usage=Specify custom metrics of pod type + podCustomMetrics?: [...{ + // +usage=Specify name of custom metrics + name: string + // +usage=Specify target value of custom metrics + value: string + }] + } +} diff --git a/vela-templates/definitions/usage-examples/application-with-hpa.yaml b/vela-templates/definitions/usage-examples/application-with-hpa.yaml new file mode 100644 index 000000000..a0e09ac5c --- /dev/null +++ b/vela-templates/definitions/usage-examples/application-with-hpa.yaml @@ -0,0 +1,54 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: helloworld +spec: + components: + - name: helloworld + type: webservice + properties: + cpu: "0.5" + exposeType: ClusterIP + image: oamdev/hello-world + memory: 1024Mi + ports: + - expose: true + port: 80 + protocol: TCP + traits: + - type: scaler + properties: + replicas: 1 + - type: hpa + properties: + targetAPIVersion: apps/v1 + targetKind: Deployment + max: 10 + min: 1 + cpu: + type: Utilization + value: 80 + mem: + type: AverageValue + value: 90 + podCustomMetrics: + # here are custom metric names and values. Please replace them to be your metrics + - name: pod_net_received_rate + value: "77" + - name: pod_net_transmitted_rate + value: "88" + - name: pod_net_received_packets_rate + value: "95" + - name: pod_net_transmitted_packets_rate + value: "99" + policies: + - name: apply-once + type: apply-once + properties: + enable: true + rules: + - strategy: + path: ["spec.replicas"] + selector: + resourceTypes: ["Deployment","StatefulSet"] +