mirror of
https://github.com/zalando-incubator/kube-metrics-adapter.git
synced 2026-05-30 17:37:25 +00:00
Only support autoscaling/v2beta2
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
This commit is contained in:
@@ -1,7 +1,4 @@
|
|||||||
run:
|
run:
|
||||||
skip-files:
|
|
||||||
- "pkg/provider/generated.conversion.go"
|
|
||||||
- "pkg/provider/conversion.go"
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0.9
|
min-confidence: 0.9
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Here's an example of a `HorizontalPodAutoscaler` resource configured to get
|
|||||||
`requests-per-second` metrics from each pod of the deployment `myapp`.
|
`requests-per-second` metrics from each pod of the deployment `myapp`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: myapp-hpa
|
name: myapp-hpa
|
||||||
@@ -36,8 +36,11 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: Pods
|
- type: Pods
|
||||||
pods:
|
pods:
|
||||||
metricName: requests-per-second
|
metric:
|
||||||
targetAverageValue: 1k
|
name: requests-per-second
|
||||||
|
target:
|
||||||
|
averageValue: 1k
|
||||||
|
type: AverageValue
|
||||||
```
|
```
|
||||||
|
|
||||||
The `metric-config.*` annotations are used by the `kube-metrics-adapter` to
|
The `metric-config.*` annotations are used by the `kube-metrics-adapter` to
|
||||||
@@ -51,10 +54,10 @@ policy](https://kubernetes.io/docs/setup/release/version-skew-policy/) offered
|
|||||||
for Kubernetes, this project aims to support the latest three minor releases of
|
for Kubernetes, this project aims to support the latest three minor releases of
|
||||||
Kubernetes.
|
Kubernetes.
|
||||||
|
|
||||||
Currently the default supported API is `autoscaling/v2beta1`. However we aim to
|
The default supported API is `autoscaling/v2beta2` (available since `v1.12`).
|
||||||
move to `autoscaling/v2beta2` (available since `v1.12`) in the near future as
|
This API MUST be available in the cluster which is the default. However for
|
||||||
this adds a lot of improvements over `v2beta1`. The move to `v2beta2` will most
|
GKE, this requires GKE v1.15.7 according to this [GKE
|
||||||
likely happen as soon as [GKE adds support for it](https://issuetracker.google.com/issues/135624588).
|
Issue](https://issuetracker.google.com/issues/135624588).
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@@ -88,7 +91,7 @@ Currently only `json-path` collection is supported.
|
|||||||
|
|
||||||
| Metric | Description | Type | K8s Versions |
|
| Metric | Description | Type | K8s Versions |
|
||||||
| ------------ | -------------- | ------- | -- |
|
| ------------ | -------------- | ------- | -- |
|
||||||
| *custom* | No predefined metrics. Metrics are generated from user defined queries. | Pods | `>=1.10` |
|
| *custom* | No predefined metrics. Metrics are generated from user defined queries. | Pods | `>=1.12` |
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -96,7 +99,7 @@ This is an example of using the pod collector to collect metrics from a json
|
|||||||
metrics endpoint of each pod matched by the HPA.
|
metrics endpoint of each pod matched by the HPA.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: myapp-hpa
|
name: myapp-hpa
|
||||||
@@ -117,8 +120,11 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: Pods
|
- type: Pods
|
||||||
pods:
|
pods:
|
||||||
metricName: requests-per-second
|
metric:
|
||||||
targetAverageValue: 1k
|
name: requests-per-second
|
||||||
|
target:
|
||||||
|
averageValue: 1k
|
||||||
|
type: AverageValue
|
||||||
```
|
```
|
||||||
|
|
||||||
The pod collector is configured through the annotations which specify the
|
The pod collector is configured through the annotations which specify the
|
||||||
@@ -174,8 +180,8 @@ the trade-offs between the two approaches.
|
|||||||
|
|
||||||
| Metric | Description | Type | Kind | K8s Versions |
|
| Metric | Description | Type | Kind | K8s Versions |
|
||||||
| ------------ | -------------- | ------- | -- | -- |
|
| ------------ | -------------- | ------- | -- | -- |
|
||||||
| `prometheus-query` | Generic metric which requires a user defined query. | External | | `>=1.10` |
|
| `prometheus-query` | Generic metric which requires a user defined query. | External | | `>=1.12` |
|
||||||
| *custom* | No predefined metrics. Metrics are generated from user defined queries. | Object | *any* | `>=1.10` |
|
| *custom* | No predefined metrics. Metrics are generated from user defined queries. | Object | *any* | `>=1.12` |
|
||||||
|
|
||||||
### Example: External Metric
|
### Example: External Metric
|
||||||
|
|
||||||
@@ -188,7 +194,7 @@ the `matchLabels` of the metric definition. This allows having multiple
|
|||||||
prometheus queries associated with a single HPA.
|
prometheus queries associated with a single HPA.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: myapp-hpa
|
name: myapp-hpa
|
||||||
@@ -211,11 +217,14 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: External
|
- type: External
|
||||||
external:
|
external:
|
||||||
metricName: prometheus-query
|
metric:
|
||||||
metricSelector:
|
name: prometheus-query
|
||||||
matchLabels:
|
selector:
|
||||||
query-name: processed-events-per-second
|
matchLabels:
|
||||||
targetAverageValue: 10
|
query-name: processed-events-per-second
|
||||||
|
target:
|
||||||
|
type: AverageValue
|
||||||
|
averageValue: "10"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example: Object Metric [DEPRECATED]
|
### Example: Object Metric [DEPRECATED]
|
||||||
@@ -282,7 +291,7 @@ box so users don't have to define those manually.
|
|||||||
|
|
||||||
| Metric | Description | Type | Kind | K8s Versions |
|
| Metric | Description | Type | Kind | K8s Versions |
|
||||||
| ----------- | -------------- | ------ | ---- | ---- |
|
| ----------- | -------------- | ------ | ---- | ---- |
|
||||||
| `requests-per-second` | Scale based on requests per second for a certain ingress. | Object | `Ingress` | `>=1.14` (can work with `>=1.10`) |
|
| `requests-per-second` | Scale based on requests per second for a certain ingress. | Object | `Ingress` | `>=1.14` |
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -290,7 +299,7 @@ This is an example of an HPA that will scale based on `requests-per-second` for
|
|||||||
an ingress called `myapp`.
|
an ingress called `myapp`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: myapp-hpa
|
name: myapp-hpa
|
||||||
@@ -304,38 +313,28 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: Object
|
- type: Object
|
||||||
object:
|
object:
|
||||||
metricName: requests-per-second
|
describedObject:
|
||||||
target:
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
name: myapp
|
name: myapp
|
||||||
averageValue: 10 # Only works with Kubernetes >=1.14
|
metric:
|
||||||
# for Kubernetes <1.14 you can use `targetValue` instead:
|
name: requests-per-second
|
||||||
targetValue: 10 # this must be set, but has no effect if `averageValue` is defined.
|
target:
|
||||||
# Otherwise it will be treated as targetAverageValue
|
averageValue: "10"
|
||||||
|
type: AverageValue
|
||||||
```
|
```
|
||||||
|
|
||||||
### Metric weighting based on backend
|
### Metric weighting based on backend
|
||||||
|
|
||||||
Skipper supports sending traffic to different backend based on annotations present on the
|
Skipper supports sending traffic to different backend based on annotations
|
||||||
`Ingress` object. When the metric name is specified without a backend as `requests-per-second`
|
present on the `Ingress` object. When the metric name is specified without a
|
||||||
then the number of replicas will be calculated based on the full traffic served by that ingress.
|
backend as `requests-per-second` then the number of replicas will be calculated
|
||||||
If however only the traffic being routed to a specific backend should be used then the
|
based on the full traffic served by that ingress. If however only the traffic
|
||||||
backend name can be specified as a metric name like `requests-per-second,backend1` which would
|
being routed to a specific backend should be used then the backend name can be
|
||||||
return the requests-per-second being sent to the `backend1`. The ingress annotation where
|
specified as a metric name like `requests-per-second,backend1` which would
|
||||||
the backend weights can be obtained can be specified through the flag `--skipper-backends-annotation`.
|
return the requests-per-second being sent to the `backend1`. The ingress
|
||||||
|
annotation where the backend weights can be obtained can be specified through
|
||||||
|
the flag `--skipper-backends-annotation`.
|
||||||
**Note:** For Kubernetes `<v1.14` the HPA does not support `averageValue` for
|
|
||||||
metrics of type `Object`. In case of requests per second it does not make sense
|
|
||||||
to scale on a summed value because you can not make the total requests per
|
|
||||||
second go down by adding more pods. For this reason the skipper collector will
|
|
||||||
automatically treat the value you define in `targetValue` as an average per pod
|
|
||||||
instead of a total sum.
|
|
||||||
|
|
||||||
**ONLY use `targetValue` if you are on Kubernetes
|
|
||||||
`<1.14`, it is not as percise as using `averageValue` and will not be supported
|
|
||||||
after Kubernetes `v1.16` is released according to the [support policy](https://kubernetes.io/docs/setup/release/version-skew-policy/).**
|
|
||||||
|
|
||||||
## InfluxDB collector
|
## InfluxDB collector
|
||||||
|
|
||||||
@@ -360,10 +359,10 @@ A matching `query-name` label must be defined in the `matchLabels` of the metric
|
|||||||
This allows having multiple flux queries associated with a single HPA.
|
This allows having multiple flux queries associated with a single HPA.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: my-hpa
|
name: myapp-hpa
|
||||||
annotations:
|
annotations:
|
||||||
# These annotations are optional.
|
# These annotations are optional.
|
||||||
# If specified, then they are used for setting up the InfluxDB client properly,
|
# If specified, then they are used for setting up the InfluxDB client properly,
|
||||||
@@ -395,11 +394,14 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: External
|
- type: External
|
||||||
external:
|
external:
|
||||||
metricName: flux-query
|
metric:
|
||||||
metricSelector:
|
name: flux-query
|
||||||
matchLabels:
|
selector:
|
||||||
query-name: queue_depth
|
matchLabels:
|
||||||
targetValue: 1
|
query-name: queue_depth
|
||||||
|
target:
|
||||||
|
type: Value
|
||||||
|
value: "1"
|
||||||
```
|
```
|
||||||
|
|
||||||
## AWS collector
|
## AWS collector
|
||||||
@@ -435,7 +437,7 @@ PolicyDocument:
|
|||||||
|
|
||||||
| Metric | Description | Type | K8s Versions |
|
| Metric | Description | Type | K8s Versions |
|
||||||
| ------------ | ------- | -- | -- |
|
| ------------ | ------- | -- | -- |
|
||||||
| `sqs-queue-length` | Scale based on SQS queue length | External | `>=1.10` |
|
| `sqs-queue-length` | Scale based on SQS queue length | External | `>=1.12` |
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -443,7 +445,7 @@ This is an example of an HPA that will scale based on the length of an SQS
|
|||||||
queue.
|
queue.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: myapp-hpa
|
name: myapp-hpa
|
||||||
@@ -457,12 +459,15 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: External
|
- type: External
|
||||||
external:
|
external:
|
||||||
metricName: sqs-queue-length
|
metric:
|
||||||
metricSelector:
|
name: sqs-queue-length
|
||||||
matchLabels:
|
selector:
|
||||||
queue-name: foobar
|
matchLabels:
|
||||||
region: eu-central-1
|
queue-name: foobar
|
||||||
targetAverageValue: 30
|
region: eu-central-1
|
||||||
|
target:
|
||||||
|
averageValue: "30"
|
||||||
|
type: AverageValue
|
||||||
```
|
```
|
||||||
|
|
||||||
The `matchLabels` are used by `kube-metrics-adapter` to configure a collector
|
The `matchLabels` are used by `kube-metrics-adapter` to configure a collector
|
||||||
@@ -483,7 +488,7 @@ The ZMON collector allows scaling based on external metrics exposed by
|
|||||||
|
|
||||||
| Metric | Description | Type | K8s Versions |
|
| Metric | Description | Type | K8s Versions |
|
||||||
| ------------ | ------- | -- | -- |
|
| ------------ | ------- | -- | -- |
|
||||||
| `zmon-check` | Scale based on any ZMON check results | External | `>=1.10` |
|
| `zmon-check` | Scale based on any ZMON check results | External | `>=1.12` |
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -491,7 +496,7 @@ This is an example of an HPA that will scale based on the specified value
|
|||||||
exposed by a ZMON check with id `1234`.
|
exposed by a ZMON check with id `1234`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: myapp-hpa
|
name: myapp-hpa
|
||||||
@@ -509,15 +514,18 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
- type: External
|
- type: External
|
||||||
external:
|
external:
|
||||||
metricName: zmon-check
|
metric:
|
||||||
metricSelector:
|
name: zmon-check
|
||||||
matchLabels:
|
selector:
|
||||||
check-id: "1234" # the ZMON check to query for metrics
|
matchLabels:
|
||||||
key: "custom.value"
|
check-id: "1234" # the ZMON check to query for metrics
|
||||||
tag-application: my-custom-app
|
key: "custom.value"
|
||||||
aggregators: avg # comma separated list of aggregation functions, default: last
|
tag-application: my-custom-app
|
||||||
duration: 5m # default: 10m
|
aggregators: avg # comma separated list of aggregation functions, default: last
|
||||||
targetAverageValue: 30
|
duration: 5m # default: 10m
|
||||||
|
target:
|
||||||
|
averageValue: "30"
|
||||||
|
type: AverageValue
|
||||||
```
|
```
|
||||||
|
|
||||||
The `check-id` specifies the ZMON check to query for the metrics. `key`
|
The `check-id` specifies the ZMON check to query for the metrics. `key`
|
||||||
|
|||||||
+25
-14
@@ -1,4 +1,4 @@
|
|||||||
apiVersion: autoscaling/v2beta1
|
apiVersion: autoscaling/v2beta2
|
||||||
kind: HorizontalPodAutoscaler
|
kind: HorizontalPodAutoscaler
|
||||||
metadata:
|
metadata:
|
||||||
name: custom-metrics-consumer
|
name: custom-metrics-consumer
|
||||||
@@ -25,25 +25,36 @@ spec:
|
|||||||
# - type: Resource
|
# - type: Resource
|
||||||
# resource:
|
# resource:
|
||||||
# name: cpu
|
# name: cpu
|
||||||
# targetAverageUtilization: 50
|
# current:
|
||||||
|
# averageUtilization: 50
|
||||||
|
|
||||||
- type: Pods
|
- type: Pods
|
||||||
pods:
|
pods:
|
||||||
metricName: queue-length
|
metric:
|
||||||
targetAverageValue: 1k
|
name: queue-length
|
||||||
|
target:
|
||||||
|
averageValue: 1k
|
||||||
|
type: AverageValue
|
||||||
|
|
||||||
- type: Object
|
- type: Object
|
||||||
object:
|
object:
|
||||||
metricName: requests-per-second
|
describedObject:
|
||||||
target:
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
name: custom-metrics-consumer
|
name: custom-metrics-consumer
|
||||||
averageValue: 10
|
metric:
|
||||||
targetValue: 10 # this must be set, but has no effect if `averageValue` is defined.
|
name: requests-per-second
|
||||||
|
target:
|
||||||
|
averageValue: "10"
|
||||||
|
type: AverageValue
|
||||||
- type: External
|
- type: External
|
||||||
external:
|
external:
|
||||||
metricName: sqs-queue-length
|
metric:
|
||||||
metricSelector:
|
name: sqs-queue-length
|
||||||
matchLabels:
|
selector:
|
||||||
queue-name: foobar
|
matchLabels:
|
||||||
region: eu-central-1
|
queue-name: foobar
|
||||||
targetAverageValue: 30
|
region: eu-central-1
|
||||||
|
target:
|
||||||
|
averageValue: "30"
|
||||||
|
type: AverageValue
|
||||||
|
|||||||
@@ -1,247 +0,0 @@
|
|||||||
package provider
|
|
||||||
|
|
||||||
import (
|
|
||||||
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
|
|
||||||
autoscaling "k8s.io/api/autoscaling/v2beta2"
|
|
||||||
core "k8s.io/api/core/v1"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/conversion"
|
|
||||||
)
|
|
||||||
|
|
||||||
// from: https://github.com/kubernetes/kubernetes/blob/v1.14.4/pkg/apis/autoscaling/v2beta1/conversion.go
|
|
||||||
|
|
||||||
func Convert_autoscaling_MetricTarget_To_v2beta1_CrossVersionObjectReference(in *autoscaling.MetricTarget, out *autoscalingv2beta1.CrossVersionObjectReference, s conversion.Scope) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_CrossVersionObjectReference_To_autoscaling_MetricTarget(in *autoscalingv2beta1.CrossVersionObjectReference, out *autoscaling.MetricTarget, s conversion.Scope) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_ResourceMetricStatus_To_autoscaling_ResourceMetricStatus(in *autoscalingv2beta1.ResourceMetricStatus, out *autoscaling.ResourceMetricStatus, s conversion.Scope) error {
|
|
||||||
out.Name = core.ResourceName(in.Name)
|
|
||||||
utilization := in.CurrentAverageUtilization
|
|
||||||
averageValue := in.CurrentAverageValue
|
|
||||||
out.Current = autoscaling.MetricValueStatus{
|
|
||||||
AverageValue: &averageValue,
|
|
||||||
AverageUtilization: utilization,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_ResourceMetricStatus_To_v2beta1_ResourceMetricStatus(in *autoscaling.ResourceMetricStatus, out *autoscalingv2beta1.ResourceMetricStatus, s conversion.Scope) error {
|
|
||||||
out.Name = v1.ResourceName(in.Name)
|
|
||||||
out.CurrentAverageUtilization = in.Current.AverageUtilization
|
|
||||||
if in.Current.AverageValue != nil {
|
|
||||||
out.CurrentAverageValue = *in.Current.AverageValue
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_ResourceMetricSource_To_autoscaling_ResourceMetricSource(in *autoscalingv2beta1.ResourceMetricSource, out *autoscaling.ResourceMetricSource, s conversion.Scope) error {
|
|
||||||
out.Name = core.ResourceName(in.Name)
|
|
||||||
utilization := in.TargetAverageUtilization
|
|
||||||
averageValue := in.TargetAverageValue
|
|
||||||
|
|
||||||
var metricType autoscaling.MetricTargetType
|
|
||||||
if utilization == nil {
|
|
||||||
metricType = autoscaling.AverageValueMetricType
|
|
||||||
} else {
|
|
||||||
metricType = autoscaling.UtilizationMetricType
|
|
||||||
}
|
|
||||||
out.Target = autoscaling.MetricTarget{
|
|
||||||
Type: metricType,
|
|
||||||
AverageValue: averageValue,
|
|
||||||
AverageUtilization: utilization,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_ResourceMetricSource_To_v2beta1_ResourceMetricSource(in *autoscaling.ResourceMetricSource, out *autoscalingv2beta1.ResourceMetricSource, s conversion.Scope) error {
|
|
||||||
out.Name = v1.ResourceName(in.Name)
|
|
||||||
out.TargetAverageUtilization = in.Target.AverageUtilization
|
|
||||||
out.TargetAverageValue = in.Target.AverageValue
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource(in *autoscaling.ExternalMetricSource, out *autoscalingv2beta1.ExternalMetricSource, s conversion.Scope) error {
|
|
||||||
out.MetricName = in.Metric.Name
|
|
||||||
out.TargetValue = in.Target.Value
|
|
||||||
out.TargetAverageValue = in.Target.AverageValue
|
|
||||||
out.MetricSelector = in.Metric.Selector
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in *autoscalingv2beta1.ExternalMetricSource, out *autoscaling.ExternalMetricSource, s conversion.Scope) error {
|
|
||||||
value := in.TargetValue
|
|
||||||
averageValue := in.TargetAverageValue
|
|
||||||
|
|
||||||
var metricType autoscaling.MetricTargetType
|
|
||||||
if value == nil {
|
|
||||||
metricType = autoscaling.AverageValueMetricType
|
|
||||||
} else {
|
|
||||||
metricType = autoscaling.ValueMetricType
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Target = autoscaling.MetricTarget{
|
|
||||||
Type: metricType,
|
|
||||||
Value: value,
|
|
||||||
AverageValue: averageValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Metric = autoscaling.MetricIdentifier{
|
|
||||||
Name: in.MetricName,
|
|
||||||
Selector: in.MetricSelector,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_ObjectMetricSource_To_v2beta1_ObjectMetricSource(in *autoscaling.ObjectMetricSource, out *autoscalingv2beta1.ObjectMetricSource, s conversion.Scope) error {
|
|
||||||
if in.Target.Value != nil {
|
|
||||||
out.TargetValue = *in.Target.Value
|
|
||||||
}
|
|
||||||
out.AverageValue = in.Target.AverageValue
|
|
||||||
|
|
||||||
out.Target = autoscalingv2beta1.CrossVersionObjectReference{
|
|
||||||
Kind: in.DescribedObject.Kind,
|
|
||||||
Name: in.DescribedObject.Name,
|
|
||||||
APIVersion: in.DescribedObject.APIVersion,
|
|
||||||
}
|
|
||||||
out.MetricName = in.Metric.Name
|
|
||||||
out.Selector = in.Metric.Selector
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_ObjectMetricSource_To_autoscaling_ObjectMetricSource(in *autoscalingv2beta1.ObjectMetricSource, out *autoscaling.ObjectMetricSource, s conversion.Scope) error {
|
|
||||||
var metricType autoscaling.MetricTargetType
|
|
||||||
if in.AverageValue == nil {
|
|
||||||
metricType = autoscaling.ValueMetricType
|
|
||||||
} else {
|
|
||||||
metricType = autoscaling.AverageValueMetricType
|
|
||||||
}
|
|
||||||
out.Target = autoscaling.MetricTarget{
|
|
||||||
Type: metricType,
|
|
||||||
Value: &in.TargetValue,
|
|
||||||
AverageValue: in.AverageValue,
|
|
||||||
}
|
|
||||||
out.DescribedObject = autoscaling.CrossVersionObjectReference{
|
|
||||||
Kind: in.Target.Kind,
|
|
||||||
Name: in.Target.Name,
|
|
||||||
APIVersion: in.Target.APIVersion,
|
|
||||||
}
|
|
||||||
out.Metric = autoscaling.MetricIdentifier{
|
|
||||||
Name: in.MetricName,
|
|
||||||
Selector: in.Selector,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_PodsMetricSource_To_v2beta1_PodsMetricSource(in *autoscaling.PodsMetricSource, out *autoscalingv2beta1.PodsMetricSource, s conversion.Scope) error {
|
|
||||||
if in.Target.AverageValue != nil {
|
|
||||||
targetAverageValue := *in.Target.AverageValue
|
|
||||||
out.TargetAverageValue = targetAverageValue
|
|
||||||
}
|
|
||||||
|
|
||||||
out.MetricName = in.Metric.Name
|
|
||||||
out.Selector = in.Metric.Selector
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_PodsMetricSource_To_autoscaling_PodsMetricSource(in *autoscalingv2beta1.PodsMetricSource, out *autoscaling.PodsMetricSource, s conversion.Scope) error {
|
|
||||||
targetAverageValue := &in.TargetAverageValue
|
|
||||||
var metricType autoscaling.MetricTargetType
|
|
||||||
metricType = autoscaling.AverageValueMetricType
|
|
||||||
|
|
||||||
out.Target = autoscaling.MetricTarget{
|
|
||||||
Type: metricType,
|
|
||||||
AverageValue: targetAverageValue,
|
|
||||||
}
|
|
||||||
out.Metric = autoscaling.MetricIdentifier{
|
|
||||||
Name: in.MetricName,
|
|
||||||
Selector: in.Selector,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_ExternalMetricStatus_To_v2beta1_ExternalMetricStatus(in *autoscaling.ExternalMetricStatus, out *autoscalingv2beta1.ExternalMetricStatus, s conversion.Scope) error {
|
|
||||||
if &in.Current.AverageValue != nil {
|
|
||||||
out.CurrentAverageValue = in.Current.AverageValue
|
|
||||||
}
|
|
||||||
out.MetricName = in.Metric.Name
|
|
||||||
if in.Current.Value != nil {
|
|
||||||
out.CurrentValue = *in.Current.Value
|
|
||||||
}
|
|
||||||
out.MetricSelector = in.Metric.Selector
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in *autoscalingv2beta1.ExternalMetricStatus, out *autoscaling.ExternalMetricStatus, s conversion.Scope) error {
|
|
||||||
value := in.CurrentValue
|
|
||||||
averageValue := in.CurrentAverageValue
|
|
||||||
out.Current = autoscaling.MetricValueStatus{
|
|
||||||
Value: &value,
|
|
||||||
AverageValue: averageValue,
|
|
||||||
}
|
|
||||||
out.Metric = autoscaling.MetricIdentifier{
|
|
||||||
Name: in.MetricName,
|
|
||||||
Selector: in.MetricSelector,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_ObjectMetricStatus_To_v2beta1_ObjectMetricStatus(in *autoscaling.ObjectMetricStatus, out *autoscalingv2beta1.ObjectMetricStatus, s conversion.Scope) error {
|
|
||||||
if in.Current.Value != nil {
|
|
||||||
out.CurrentValue = *in.Current.Value
|
|
||||||
}
|
|
||||||
out.Target = autoscalingv2beta1.CrossVersionObjectReference{
|
|
||||||
Kind: in.DescribedObject.Kind,
|
|
||||||
Name: in.DescribedObject.Name,
|
|
||||||
APIVersion: in.DescribedObject.APIVersion,
|
|
||||||
}
|
|
||||||
out.MetricName = in.Metric.Name
|
|
||||||
out.Selector = in.Metric.Selector
|
|
||||||
if in.Current.AverageValue != nil {
|
|
||||||
currentAverageValue := *in.Current.AverageValue
|
|
||||||
out.AverageValue = ¤tAverageValue
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_ObjectMetricStatus_To_autoscaling_ObjectMetricStatus(in *autoscalingv2beta1.ObjectMetricStatus, out *autoscaling.ObjectMetricStatus, s conversion.Scope) error {
|
|
||||||
out.Current = autoscaling.MetricValueStatus{
|
|
||||||
Value: &in.CurrentValue,
|
|
||||||
AverageValue: in.AverageValue,
|
|
||||||
}
|
|
||||||
out.DescribedObject = autoscaling.CrossVersionObjectReference{
|
|
||||||
Kind: in.Target.Kind,
|
|
||||||
Name: in.Target.Name,
|
|
||||||
APIVersion: in.Target.APIVersion,
|
|
||||||
}
|
|
||||||
out.Metric = autoscaling.MetricIdentifier{
|
|
||||||
Name: in.MetricName,
|
|
||||||
Selector: in.Selector,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_autoscaling_PodsMetricStatus_To_v2beta1_PodsMetricStatus(in *autoscaling.PodsMetricStatus, out *autoscalingv2beta1.PodsMetricStatus, s conversion.Scope) error {
|
|
||||||
if in.Current.AverageValue != nil {
|
|
||||||
out.CurrentAverageValue = *in.Current.AverageValue
|
|
||||||
}
|
|
||||||
out.MetricName = in.Metric.Name
|
|
||||||
out.Selector = in.Metric.Selector
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Convert_v2beta1_PodsMetricStatus_To_autoscaling_PodsMetricStatus(in *autoscalingv2beta1.PodsMetricStatus, out *autoscaling.PodsMetricStatus, s conversion.Scope) error {
|
|
||||||
out.Current = autoscaling.MetricValueStatus{
|
|
||||||
AverageValue: &in.CurrentAverageValue,
|
|
||||||
}
|
|
||||||
out.Metric = autoscaling.MetricIdentifier{
|
|
||||||
Name: in.MetricName,
|
|
||||||
Selector: in.Selector,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
+2
-10
@@ -116,7 +116,7 @@ func (p *HPAProvider) Run(ctx context.Context) {
|
|||||||
func (p *HPAProvider) updateHPAs() error {
|
func (p *HPAProvider) updateHPAs() error {
|
||||||
p.logger.Info("Looking for HPAs")
|
p.logger.Info("Looking for HPAs")
|
||||||
|
|
||||||
hpas, err := p.client.AutoscalingV2beta1().HorizontalPodAutoscalers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
hpas, err := p.client.AutoscalingV2beta2().HorizontalPodAutoscalers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -125,15 +125,7 @@ func (p *HPAProvider) updateHPAs() error {
|
|||||||
|
|
||||||
newHPAs := 0
|
newHPAs := 0
|
||||||
|
|
||||||
for _, hpav1 := range hpas.Items {
|
for _, hpa := range hpas.Items {
|
||||||
hpav1 := hpav1
|
|
||||||
hpa := autoscalingv2.HorizontalPodAutoscaler{}
|
|
||||||
err := Convert_v2beta1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutoscaler(&hpav1, &hpa, nil)
|
|
||||||
if err != nil {
|
|
||||||
p.logger.Errorf("Failed to convert HPA to v2beta2: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceRef := resourceReference{
|
resourceRef := resourceReference{
|
||||||
Name: hpa.Name,
|
Name: hpa.Name,
|
||||||
Namespace: hpa.Namespace,
|
Namespace: hpa.Namespace,
|
||||||
|
|||||||
+17
-13
@@ -7,8 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/zalando-incubator/kube-metrics-adapter/pkg/collector"
|
"github.com/zalando-incubator/kube-metrics-adapter/pkg/collector"
|
||||||
autoscalingv1 "k8s.io/api/autoscaling/v2beta1"
|
autoscaling "k8s.io/api/autoscaling/v2beta2"
|
||||||
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
@@ -16,7 +15,7 @@ import (
|
|||||||
|
|
||||||
type mockCollectorPlugin struct{}
|
type mockCollectorPlugin struct{}
|
||||||
|
|
||||||
func (m mockCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *collector.MetricConfig, interval time.Duration) (collector.Collector, error) {
|
func (m mockCollectorPlugin) NewCollector(hpa *autoscaling.HorizontalPodAutoscaler, config *collector.MetricConfig, interval time.Duration) (collector.Collector, error) {
|
||||||
return mockCollector{}, nil
|
return mockCollector{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@ func (c mockCollector) Interval() time.Duration {
|
|||||||
func TestUpdateHPAs(t *testing.T) {
|
func TestUpdateHPAs(t *testing.T) {
|
||||||
value := resource.MustParse("1k")
|
value := resource.MustParse("1k")
|
||||||
|
|
||||||
hpa := &autoscalingv1.HorizontalPodAutoscaler{
|
hpa := &autoscaling.HorizontalPodAutoscaler{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "hpa1",
|
Name: "hpa1",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
@@ -43,20 +42,25 @@ func TestUpdateHPAs(t *testing.T) {
|
|||||||
"metric-config.pods.requests-per-second.json-path/port": "9090",
|
"metric-config.pods.requests-per-second.json-path/port": "9090",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
Name: "app",
|
Name: "app",
|
||||||
APIVersion: "apps/v1",
|
APIVersion: "apps/v1",
|
||||||
},
|
},
|
||||||
MinReplicas: &[]int32{1}[0],
|
MinReplicas: &[]int32{1}[0],
|
||||||
MaxReplicas: 10,
|
MaxReplicas: 10,
|
||||||
Metrics: []autoscalingv1.MetricSpec{
|
Metrics: []autoscaling.MetricSpec{
|
||||||
{
|
{
|
||||||
Type: autoscalingv1.PodsMetricSourceType,
|
Type: autoscaling.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv1.PodsMetricSource{
|
Pods: &autoscaling.PodsMetricSource{
|
||||||
MetricName: "requests-per-second",
|
Metric: autoscaling.MetricIdentifier{
|
||||||
TargetAverageValue: value,
|
Name: "requests-per-second",
|
||||||
|
},
|
||||||
|
Target: autoscaling.MetricTarget{
|
||||||
|
Type: autoscaling.AverageValueMetricType,
|
||||||
|
AverageValue: &value,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -66,7 +70,7 @@ func TestUpdateHPAs(t *testing.T) {
|
|||||||
fakeClient := fake.NewSimpleClientset()
|
fakeClient := fake.NewSimpleClientset()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
hpa, err = fakeClient.AutoscalingV2beta1().HorizontalPodAutoscalers("default").Create(hpa)
|
hpa, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Create(hpa)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
collectorFactory := collector.NewCollectorFactory()
|
collectorFactory := collector.NewCollectorFactory()
|
||||||
@@ -82,7 +86,7 @@ func TestUpdateHPAs(t *testing.T) {
|
|||||||
|
|
||||||
// update HPA
|
// update HPA
|
||||||
hpa.Annotations["metric-config.pods.requests-per-second.json-path/port"] = "8080"
|
hpa.Annotations["metric-config.pods.requests-per-second.json-path/port"] = "8080"
|
||||||
_, err = fakeClient.AutoscalingV2beta1().HorizontalPodAutoscalers("default").Update(hpa)
|
_, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Update(hpa)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = provider.updateHPAs()
|
err = provider.updateHPAs()
|
||||||
|
|||||||
Reference in New Issue
Block a user