mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Add support for external metrics in kubectl
This commit is contained in:
parent
15b7d4666d
commit
afe1724695
@ -2823,6 +2823,22 @@ func describeHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, e
|
|||||||
w.Write(LEVEL_0, "Metrics:\t( current / target )\n")
|
w.Write(LEVEL_0, "Metrics:\t( current / target )\n")
|
||||||
for i, metric := range hpa.Spec.Metrics {
|
for i, metric := range hpa.Spec.Metrics {
|
||||||
switch metric.Type {
|
switch metric.Type {
|
||||||
|
case autoscaling.ExternalMetricSourceType:
|
||||||
|
if metric.External.TargetAverageValue != nil {
|
||||||
|
current := "<unknown>"
|
||||||
|
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].External != nil &&
|
||||||
|
hpa.Status.CurrentMetrics[i].External.CurrentAverageValue != nil {
|
||||||
|
current = hpa.Status.CurrentMetrics[i].External.CurrentAverageValue.String()
|
||||||
|
}
|
||||||
|
w.Write(LEVEL_1, "%q:\t%s / %s\n", metric.External.MetricName, current, metric.External.TargetAverageValue.String())
|
||||||
|
} else {
|
||||||
|
current := "<unknown>"
|
||||||
|
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].External != nil {
|
||||||
|
current = hpa.Status.CurrentMetrics[i].External.CurrentValue.String()
|
||||||
|
}
|
||||||
|
w.Write(LEVEL_1, "%q:\t%s / %s\n", metric.External.MetricName, current, metric.External.TargetValue.String())
|
||||||
|
|
||||||
|
}
|
||||||
case autoscaling.PodsMetricSourceType:
|
case autoscaling.PodsMetricSourceType:
|
||||||
current := "<unknown>"
|
current := "<unknown>"
|
||||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Pods != nil {
|
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Pods != nil {
|
||||||
|
@ -1212,6 +1212,158 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"external source type, target average value (no current)",
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"external source type, target average value (with current)",
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
CurrentMetrics: []autoscaling.MetricStatus{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricStatus{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
CurrentAverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"external source type, target value (no current)",
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"external source type, target value (with current)",
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
CurrentMetrics: []autoscaling.MetricStatus{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricStatus{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
CurrentValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pods source type (no current)",
|
"pods source type (no current)",
|
||||||
autoscaling.HorizontalPodAutoscaler{
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
@ -1491,6 +1491,20 @@ func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.Met
|
|||||||
count := 0
|
count := 0
|
||||||
for i, spec := range specs {
|
for i, spec := range specs {
|
||||||
switch spec.Type {
|
switch spec.Type {
|
||||||
|
case autoscaling.ExternalMetricSourceType:
|
||||||
|
if spec.External.TargetAverageValue != nil {
|
||||||
|
current := "<unknown>"
|
||||||
|
if len(statuses) > i && statuses[i].External != nil && statuses[i].External.CurrentAverageValue != nil {
|
||||||
|
current = statuses[i].External.CurrentAverageValue.String()
|
||||||
|
}
|
||||||
|
list = append(list, fmt.Sprintf("%s/%s", current, spec.External.TargetAverageValue.String()))
|
||||||
|
} else {
|
||||||
|
current := "<unknown>"
|
||||||
|
if len(statuses) > i && statuses[i].External != nil {
|
||||||
|
current = statuses[i].External.CurrentValue.String()
|
||||||
|
}
|
||||||
|
list = append(list, fmt.Sprintf("%s/%s", current, spec.External.TargetValue.String()))
|
||||||
|
}
|
||||||
case autoscaling.PodsMetricSourceType:
|
case autoscaling.PodsMetricSourceType:
|
||||||
current := "<unknown>"
|
current := "<unknown>"
|
||||||
if len(statuses) > i && statuses[i].Pods != nil {
|
if len(statuses) > i && statuses[i].Pods != nil {
|
||||||
|
@ -2169,6 +2169,161 @@ func TestPrintHPA(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"some-hpa\tReplicationController/some-rc\t<none>\t<unset>\t10\t4\t<unknown>\n",
|
"some-hpa\tReplicationController/some-rc\t<none>\t<unset>\t10\t4\t<unknown>\n",
|
||||||
},
|
},
|
||||||
|
// external source type, target average value (no current)
|
||||||
|
{
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"some-hpa\tReplicationController/some-rc\t<unknown>/100m\t2\t10\t4\t<unknown>\n",
|
||||||
|
},
|
||||||
|
// external source type, target average value
|
||||||
|
{
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
CurrentMetrics: []autoscaling.MetricStatus{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricStatus{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
CurrentAverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"some-hpa\tReplicationController/some-rc\t50m/100m\t2\t10\t4\t<unknown>\n",
|
||||||
|
},
|
||||||
|
// external source type, target value (no current)
|
||||||
|
{
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-service-metric",
|
||||||
|
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"some-hpa\tReplicationController/some-rc\t<unknown>/100m\t2\t10\t4\t<unknown>\n",
|
||||||
|
},
|
||||||
|
// external source type, target value
|
||||||
|
{
|
||||||
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||||
|
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||||
|
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||||
|
Name: "some-rc",
|
||||||
|
Kind: "ReplicationController",
|
||||||
|
},
|
||||||
|
MinReplicas: &minReplicasVal,
|
||||||
|
MaxReplicas: 10,
|
||||||
|
Metrics: []autoscaling.MetricSpec{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricSource{
|
||||||
|
MetricSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||||
|
CurrentReplicas: 4,
|
||||||
|
DesiredReplicas: 5,
|
||||||
|
CurrentMetrics: []autoscaling.MetricStatus{
|
||||||
|
{
|
||||||
|
Type: autoscaling.ExternalMetricSourceType,
|
||||||
|
External: &autoscaling.ExternalMetricStatus{
|
||||||
|
MetricName: "some-external-metric",
|
||||||
|
CurrentValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"some-hpa\tReplicationController/some-rc\t50m/100m\t2\t10\t4\t<unknown>\n",
|
||||||
|
},
|
||||||
// pods source type (no current)
|
// pods source type (no current)
|
||||||
{
|
{
|
||||||
autoscaling.HorizontalPodAutoscaler{
|
autoscaling.HorizontalPodAutoscaler{
|
||||||
|
Loading…
Reference in New Issue
Block a user