Skip to content

Commit

Permalink
Add the type match label
Browse files Browse the repository at this point in the history
When using the `autoscaler` we are still letting `kube-metric-adapter`
to rely in the metric name. This commit adds the `type` label to the
ZMON and SQS queue len metrics.

Co-authored-by: Katyanna Moura <amelie.kn@gmail.com>

Signed-off-by: Jonathan Juares Beber <jonathanbeber@gmail.com>
  • Loading branch information
jonathanbeber committed Nov 29, 2021
1 parent e2b3a78 commit 23a3676
Show file tree
Hide file tree
Showing 3 changed files with 686 additions and 26 deletions.
101 changes: 84 additions & 17 deletions pkg/core/autoscaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ import (
)

const (
metricsTypeLabel = "type"
requestsPerSecondName = "requests-per-second"
metricConfigJSONPath = "metric-config.pods.%s.json-path/path"
metricConfigJSONKey = "metric-config.pods.%s.json-path/json-key"
metricConfigJSONPort = "metric-config.pods.%s.json-path/port"
sqsQueueLengthTag = "sqs-queue-length"
zmonCheckMetricName = "zmon-check"
zmonCheckMetricType = "zmon"
zmonCheckCheckIDTag = "check-id"
zmonCheckAggregatorsTag = "aggregators"
zmonCheckDurationTag = "duration"
zmonCheckStackTag = "stack"
zmonCheckKeyAnnotation = "metric-config.external.zmon-check.zmon/key"
zmonCheckTagAnnotationPrefix = "metric-config.external.zmon-check.zmon/tag-"
sqsMetricType = "sqs-queue-length"
sqsMetricName = "sqs-queue-len"
sqsQueueNameTag = "queue-name"
sqsQueueRegionTag = "region"
scalingScheduleAPIVersion = "zalando.org/v1"
Expand All @@ -42,43 +45,103 @@ var (
errMissingClusterScalingScheduleName = errors.New("missing ClusterScalingSchedule metric object name")
)

type MetricsList []autoscaling.MetricSpec
type autoscalerMetricsList []zv1.AutoscalerMetrics

func (l MetricsList) Len() int {
func (l autoscalerMetricsList) Len() int {
return len(l)
}

func (l MetricsList) Swap(i, j int) {
func (l autoscalerMetricsList) Swap(i, j int) {
temp := l[i]
l[i] = l[j]
l[j] = temp
}

func (l MetricsList) Less(i, j int) bool {
return l[i].Type < l[j].Type
func (l autoscalerMetricsList) Less(i, j int) bool {
if l[i].Type != l[j].Type {
return l[i].Type < l[j].Type
}

if l[i].Average != nil && l[j].Average != nil {
iAverage, ok := l[i].Average.AsInt64()
if !ok {
iAverage = l[i].Average.AsDec().UnscaledBig().Int64()
}

jAverage, ok := l[j].Average.AsInt64()
if !ok {
jAverage = l[j].Average.AsDec().UnscaledBig().Int64()
}

if iAverage != jAverage {
return iAverage < jAverage
}
}

if l[i].AverageUtilization != nil && l[j].AverageUtilization != nil {
if *l[i].AverageUtilization != *l[j].AverageUtilization {
return *l[i].AverageUtilization < *l[j].AverageUtilization
}
}

// CPUAutoscalerMetric, MemoryAutoscalerMetric
if l[i].Container != "" && l[j].Container != "" {
return l[i].Container < l[j].Container
}

// AmazonSQSAutoscalerMetric
if l[i].Queue != nil && l[j].Queue != nil {
return l[i].Queue.Name < l[j].Queue.Name
}

// PodJSONAutoscalerMetric
if l[i].Endpoint != nil && l[j].Endpoint != nil {
return l[i].Endpoint.Name < l[j].Endpoint.Name
}
// ZMONAutoscalerMetric
if l[i].ZMON != nil && l[j].ZMON != nil {
return l[i].ZMON.CheckID < l[j].ZMON.CheckID
}

// ClusterScalingScheduleMetric
if l[i].ClusterScalingSchedule != nil && l[j].ClusterScalingSchedule != nil {
return l[i].ClusterScalingSchedule.Name < l[j].ClusterScalingSchedule.Name
}

// ScalingScheduleMetric
if l[i].ScalingSchedule != nil && l[j].ScalingSchedule != nil {
return l[i].ScalingSchedule.Name < l[j].ScalingSchedule.Name
}

// IngressAutoscalerMetric, RouteGroupAutoscalerMetric are both
// checked just by the Average value.

return false
}

func convertCustomMetrics(stacksetName, stackName, namespace string, metrics []zv1.AutoscalerMetrics) ([]autoscaling.MetricSpec, map[string]string, error) {
var resultMetrics MetricsList
func convertCustomMetrics(stacksetName, stackName, namespace string, metrics autoscalerMetricsList) ([]autoscaling.MetricSpec, map[string]string, error) {
var resultMetrics []autoscaling.MetricSpec
resultAnnotations := make(map[string]string)

for _, m := range metrics {
sort.Sort(metrics)

for i, m := range metrics {
var (
generated *autoscaling.MetricSpec
annotations map[string]string
err error
)
switch m.Type {
case zv1.AmazonSQSAutoscalerMetric:
generated, err = sqsMetric(m)
generated, err = sqsMetric(m, i)
case zv1.PodJSONAutoscalerMetric:
generated, annotations, err = podJsonMetric(m)
case zv1.IngressAutoscalerMetric:
generated, err = ingressMetric(m, stacksetName, stackName)
case zv1.RouteGroupAutoscalerMetric:
generated, err = routegroupMetric(m, stacksetName, stackName)
case zv1.ZMONAutoscalerMetric:
generated, annotations, err = zmonMetric(m, stackName, namespace)
generated, annotations, err = zmonMetric(m, i, stackName, namespace)
case zv1.ScalingScheduleMetric:
generated, err = scalingScheduleMetric(m, stackName, namespace)
case zv1.ClusterScalingScheduleMetric:
Expand All @@ -100,7 +163,6 @@ func convertCustomMetrics(stacksetName, stackName, namespace string, metrics []z
}
}

sort.Sort(resultMetrics)
return resultMetrics, resultAnnotations, nil
}

Expand Down Expand Up @@ -165,7 +227,7 @@ func cpuMetric(metrics zv1.AutoscalerMetrics) (*autoscaling.MetricSpec, error) {
}, nil
}

func sqsMetric(metrics zv1.AutoscalerMetrics) (*autoscaling.MetricSpec, error) {
func sqsMetric(metrics zv1.AutoscalerMetrics, position int) (*autoscaling.MetricSpec, error) {
if metrics.Average == nil {
return nil, fmt.Errorf("average not specified")
}
Expand All @@ -177,9 +239,13 @@ func sqsMetric(metrics zv1.AutoscalerMetrics) (*autoscaling.MetricSpec, error) {
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
Metric: autoscaling.MetricIdentifier{
Name: sqsQueueLengthTag,
Name: fmt.Sprintf("%s-%d", sqsMetricName, position),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{sqsQueueNameTag: metrics.Queue.Name, sqsQueueRegionTag: metrics.Queue.Region},
MatchLabels: map[string]string{
metricsTypeLabel: sqsMetricType,
sqsQueueNameTag: metrics.Queue.Name,
sqsQueueRegionTag: metrics.Queue.Region,
},
},
},
Target: autoscaling.MetricTarget{
Expand Down Expand Up @@ -284,7 +350,7 @@ func routegroupMetric(metrics zv1.AutoscalerMetrics, rgName, backendName string)
return generated, nil
}

func zmonMetric(metrics zv1.AutoscalerMetrics, stackName, namespace string) (*autoscaling.MetricSpec, map[string]string, error) {
func zmonMetric(metrics zv1.AutoscalerMetrics, position int, stackName, namespace string) (*autoscaling.MetricSpec, map[string]string, error) {
if metrics.Average == nil {
return nil, nil, fmt.Errorf("average not specified")
}
Expand All @@ -310,9 +376,10 @@ func zmonMetric(metrics zv1.AutoscalerMetrics, stackName, namespace string) (*au
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
Metric: autoscaling.MetricIdentifier{
Name: zmonCheckMetricName,
Name: fmt.Sprintf("%s-%d", zmonCheckMetricName, position),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
metricsTypeLabel: zmonCheckMetricType,
zmonCheckCheckIDTag: metrics.ZMON.CheckID,
zmonCheckDurationTag: metrics.ZMON.Duration,
// uniquely identifies the metric to this
Expand Down

0 comments on commit 23a3676

Please sign in to comment.