mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
Merge pull request #90691 from arjunrn/container-resource-hpa
Add container based scaling to HPA
This commit is contained in:
commit
ec453ffb1a
125
api/openapi-spec/swagger.json
generated
125
api/openapi-spec/swagger.json
generated
@ -3024,6 +3024,61 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.autoscaling.v2beta1.ContainerResourceMetricSource": {
|
||||
"description": "ContainerResourceMetricSource indicates how to scale on a resource metric known to Kubernetes, as specified in requests and limits, describing each pod in the current scale target (e.g. CPU or memory). The values will be averaged together before being compared to the target. Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. Only one \"target\" type should be set.",
|
||||
"properties": {
|
||||
"container": {
|
||||
"description": "container is the name of the container in the pods of the scaling target",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "name is the name of the resource in question.",
|
||||
"type": "string"
|
||||
},
|
||||
"targetAverageUtilization": {
|
||||
"description": "targetAverageUtilization is the target value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods.",
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"targetAverageValue": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity",
|
||||
"description": "targetAverageValue is the target value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"container"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.autoscaling.v2beta1.ContainerResourceMetricStatus": {
|
||||
"description": "ContainerResourceMetricStatus indicates the current value of a resource metric known to Kubernetes, as specified in requests and limits, describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"properties": {
|
||||
"container": {
|
||||
"description": "container is the name of the container in the pods of the scaling target",
|
||||
"type": "string"
|
||||
},
|
||||
"currentAverageUtilization": {
|
||||
"description": "currentAverageUtilization is the current value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods. It will only be present if `targetAverageValue` was set in the corresponding metric specification.",
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"currentAverageValue": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity",
|
||||
"description": "currentAverageValue is the current value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type. It will always be set, regardless of the corresponding metric specification."
|
||||
},
|
||||
"name": {
|
||||
"description": "name is the name of the resource in question.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"currentAverageValue",
|
||||
"container"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.autoscaling.v2beta1.CrossVersionObjectReference": {
|
||||
"description": "CrossVersionObjectReference contains enough information to let you identify the referred resource.",
|
||||
"properties": {
|
||||
@ -3273,6 +3328,10 @@
|
||||
"io.k8s.api.autoscaling.v2beta1.MetricSpec": {
|
||||
"description": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"properties": {
|
||||
"containerResource": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta1.ContainerResourceMetricSource",
|
||||
"description": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod of the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag."
|
||||
},
|
||||
"external": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta1.ExternalMetricSource",
|
||||
"description": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster)."
|
||||
@ -3290,7 +3349,7 @@
|
||||
"description": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source."
|
||||
},
|
||||
"type": {
|
||||
"description": "type is the type of metric source. It should be one of \"Object\", \"Pods\", \"Resource\" or \"External\", each mapping to a matching field in the object.",
|
||||
"description": "type is the type of metric source. It should be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3302,6 +3361,10 @@
|
||||
"io.k8s.api.autoscaling.v2beta1.MetricStatus": {
|
||||
"description": "MetricStatus describes the last-read state of a single metric.",
|
||||
"properties": {
|
||||
"containerResource": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta1.ContainerResourceMetricStatus",
|
||||
"description": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source."
|
||||
},
|
||||
"external": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta1.ExternalMetricStatus",
|
||||
"description": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster)."
|
||||
@ -3319,7 +3382,7 @@
|
||||
"description": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source."
|
||||
},
|
||||
"type": {
|
||||
"description": "type is the type of metric source. It will be one of \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object.",
|
||||
"description": "type is the type of metric source. It will be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3479,6 +3542,52 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.autoscaling.v2beta2.ContainerResourceMetricSource": {
|
||||
"description": "ContainerResourceMetricSource indicates how to scale on a resource metric known to Kubernetes, as specified in requests and limits, describing each pod in the current scale target (e.g. CPU or memory). The values will be averaged together before being compared to the target. Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. Only one \"target\" type should be set.",
|
||||
"properties": {
|
||||
"container": {
|
||||
"description": "container is the name of the container in the pods of the scaling target",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "name is the name of the resource in question.",
|
||||
"type": "string"
|
||||
},
|
||||
"target": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta2.MetricTarget",
|
||||
"description": "target specifies the target value for the given metric"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"target",
|
||||
"container"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.autoscaling.v2beta2.ContainerResourceMetricStatus": {
|
||||
"description": "ContainerResourceMetricStatus indicates the current value of a resource metric known to Kubernetes, as specified in requests and limits, describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"properties": {
|
||||
"container": {
|
||||
"description": "Container is the name of the container in the pods of the scaling target",
|
||||
"type": "string"
|
||||
},
|
||||
"current": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta2.MetricValueStatus",
|
||||
"description": "current contains the current value for the given metric"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name is the name of the resource in question.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"current",
|
||||
"container"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.autoscaling.v2beta2.CrossVersionObjectReference": {
|
||||
"description": "CrossVersionObjectReference contains enough information to let you identify the referred resource.",
|
||||
"properties": {
|
||||
@ -3795,6 +3904,10 @@
|
||||
"io.k8s.api.autoscaling.v2beta2.MetricSpec": {
|
||||
"description": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"properties": {
|
||||
"containerResource": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta2.ContainerResourceMetricSource",
|
||||
"description": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod of the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag."
|
||||
},
|
||||
"external": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta2.ExternalMetricSource",
|
||||
"description": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster)."
|
||||
@ -3812,7 +3925,7 @@
|
||||
"description": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source."
|
||||
},
|
||||
"type": {
|
||||
"description": "type is the type of metric source. It should be one of \"Object\", \"Pods\", \"Resource\" or \"External\", each mapping to a matching field in the object.",
|
||||
"description": "type is the type of metric source. It should be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3824,6 +3937,10 @@
|
||||
"io.k8s.api.autoscaling.v2beta2.MetricStatus": {
|
||||
"description": "MetricStatus describes the last-read state of a single metric.",
|
||||
"properties": {
|
||||
"containerResource": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta2.ContainerResourceMetricStatus",
|
||||
"description": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source."
|
||||
},
|
||||
"external": {
|
||||
"$ref": "#/definitions/io.k8s.api.autoscaling.v2beta2.ExternalMetricStatus",
|
||||
"description": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster)."
|
||||
@ -3841,7 +3958,7 @@
|
||||
"description": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source."
|
||||
},
|
||||
"type": {
|
||||
"description": "type is the type of metric source. It will be one of \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object.",
|
||||
"description": "type is the type of metric source. It will be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
|
@ -204,6 +204,12 @@ const (
|
||||
// (for example length of queue in cloud messaging service, or
|
||||
// QPS from loadbalancer running outside of cluster).
|
||||
ExternalMetricSourceType MetricSourceType = "External"
|
||||
// ContainerResourceMetricSourceType is a resource metric known to Kubernetes, as
|
||||
// specified in requests and limits, describing a single container in each pod in the current
|
||||
// scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ContainerResourceMetricSourceType MetricSourceType = "ContainerResource"
|
||||
)
|
||||
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
@ -229,6 +235,13 @@ type MetricSpec struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricSource
|
||||
// ContainerResource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod of the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricSource
|
||||
// External refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -271,6 +284,22 @@ type ResourceMetricSource struct {
|
||||
Target MetricTarget
|
||||
}
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in the requests and limits, describing a single container in
|
||||
// each of the pods of the current scale target(e.g. CPU or memory). The values will be
|
||||
// averaged together before being compared to the target. Such metrics are built into
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
type ContainerResourceMetricSource struct {
|
||||
// name is the name of the of the resource
|
||||
Name api.ResourceName
|
||||
// container is the name of the container in the pods of the scaling target.
|
||||
Container string
|
||||
// target specifies the target value for the given metric
|
||||
Target MetricTarget
|
||||
}
|
||||
|
||||
// ExternalMetricSource indicates how to scale on a metric not associated with
|
||||
// any Kubernetes object (for example length of queue in cloud
|
||||
// messaging service, or QPS from loadbalancer running outside of cluster).
|
||||
@ -420,6 +449,13 @@ type MetricStatus struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricStatus
|
||||
// ContainerResource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricStatus
|
||||
// External refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -456,6 +492,18 @@ type ResourceMetricStatus struct {
|
||||
Current MetricValueStatus
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
type ContainerResourceMetricStatus struct {
|
||||
// Name is the name of the resource in question.
|
||||
Name api.ResourceName
|
||||
Container string
|
||||
Current MetricValueStatus
|
||||
}
|
||||
|
||||
// ExternalMetricStatus indicates the current value of a global metric
|
||||
// not associated with any Kubernetes object.
|
||||
type ExternalMetricStatus struct {
|
||||
|
@ -235,6 +235,28 @@ func Convert_autoscaling_ResourceMetricSource_To_v1_ResourceMetricSource(in *aut
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *autoscalingv1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
utilization := in.CurrentAverageUtilization
|
||||
averageValue := &in.CurrentAverageValue
|
||||
out.Current = autoscaling.MetricValueStatus{
|
||||
AverageValue: averageValue,
|
||||
AverageUtilization: utilization,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *autoscalingv1.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
out.CurrentAverageUtilization = in.Current.AverageUtilization
|
||||
if in.Current.AverageValue != nil {
|
||||
out.CurrentAverageValue = *in.Current.AverageValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_ResourceMetricStatus_To_autoscaling_ResourceMetricStatus(in *autoscalingv1.ResourceMetricStatus, out *autoscaling.ResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
utilization := in.CurrentAverageUtilization
|
||||
@ -517,3 +539,30 @@ func Convert_v1_HorizontalPodAutoscalerStatus_To_autoscaling_HorizontalPodAutosc
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *autoscalingv1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
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_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *autoscalingv1.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
out.TargetAverageUtilization = in.Target.AverageUtilization
|
||||
out.TargetAverageValue = in.Target.AverageValue
|
||||
return nil
|
||||
}
|
||||
|
86
pkg/apis/autoscaling/v1/zz_generated.conversion.go
generated
86
pkg/apis/autoscaling/v1/zz_generated.conversion.go
generated
@ -119,6 +119,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricSource)(nil), (*v1.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(a.(*autoscaling.ContainerResourceMetricSource), b.(*v1.ContainerResourceMetricSource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricStatus)(nil), (*v1.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(a.(*autoscaling.ContainerResourceMetricStatus), b.(*v1.ContainerResourceMetricStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*autoscaling.ExternalMetricSource)(nil), (*v1.ExternalMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource(a.(*autoscaling.ExternalMetricSource), b.(*v1.ExternalMetricSource), scope)
|
||||
}); err != nil {
|
||||
@ -179,6 +189,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*v1.ContainerResourceMetricSource)(nil), (*autoscaling.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(a.(*v1.ContainerResourceMetricSource), b.(*autoscaling.ContainerResourceMetricSource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*v1.ContainerResourceMetricStatus)(nil), (*autoscaling.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(a.(*v1.ContainerResourceMetricStatus), b.(*autoscaling.ContainerResourceMetricStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*v1.CrossVersionObjectReference)(nil), (*autoscaling.MetricTarget)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_CrossVersionObjectReference_To_autoscaling_MetricTarget(a.(*v1.CrossVersionObjectReference), b.(*autoscaling.MetricTarget), scope)
|
||||
}); err != nil {
|
||||
@ -242,6 +262,36 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
// WARNING: in.TargetAverageUtilization requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.TargetAverageValue requires manual conversion: does not exist in peer-type
|
||||
out.Container = in.Container
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v1.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = corev1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
// WARNING: in.Target requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
// WARNING: in.CurrentAverageUtilization requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.CurrentAverageValue requires manual conversion: does not exist in peer-type
|
||||
out.Container = in.Container
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v1.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = corev1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
// WARNING: in.Current requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(in *v1.CrossVersionObjectReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
@ -455,6 +505,15 @@ func autoConvert_v1_MetricSpec_To_autoscaling_MetricSpec(in *v1.MetricSpec, out
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(autoscaling.ContainerResourceMetricSource)
|
||||
if err := Convert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(autoscaling.ExternalMetricSource)
|
||||
@ -501,6 +560,15 @@ func autoConvert_autoscaling_MetricSpec_To_v1_MetricSpec(in *autoscaling.MetricS
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(v1.ContainerResourceMetricSource)
|
||||
if err := Convert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(v1.ExternalMetricSource)
|
||||
@ -547,6 +615,15 @@ func autoConvert_v1_MetricStatus_To_autoscaling_MetricStatus(in *v1.MetricStatus
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(autoscaling.ContainerResourceMetricStatus)
|
||||
if err := Convert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(autoscaling.ExternalMetricStatus)
|
||||
@ -593,6 +670,15 @@ func autoConvert_autoscaling_MetricStatus_To_v1_MetricStatus(in *autoscaling.Met
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(v1.ContainerResourceMetricStatus)
|
||||
if err := Convert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(v1.ExternalMetricStatus)
|
||||
|
@ -35,6 +35,28 @@ func Convert_v2beta1_CrossVersionObjectReference_To_autoscaling_MetricTarget(in
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *autoscalingv2beta1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
utilization := in.CurrentAverageUtilization
|
||||
averageValue := in.CurrentAverageValue
|
||||
out.Current = autoscaling.MetricValueStatus{
|
||||
AverageValue: &averageValue,
|
||||
AverageUtilization: utilization,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *autoscalingv2beta1.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
out.CurrentAverageUtilization = in.Current.AverageUtilization
|
||||
if in.Current.AverageValue != nil {
|
||||
out.CurrentAverageValue = *in.Current.AverageValue
|
||||
}
|
||||
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
|
||||
@ -309,3 +331,29 @@ func Convert_v2beta1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutosca
|
||||
func Convert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta1_HorizontalPodAutoscalerSpec(in *autoscaling.HorizontalPodAutoscalerSpec, out *autoscalingv2beta1.HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta1_HorizontalPodAutoscalerSpec(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *autoscalingv2beta1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, 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_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *autoscalingv2beta1.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.TargetAverageUtilization = in.Target.AverageUtilization
|
||||
out.TargetAverageValue = in.Target.AverageValue
|
||||
return nil
|
||||
}
|
||||
|
@ -104,6 +104,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricSource)(nil), (*v2beta1.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(a.(*autoscaling.ContainerResourceMetricSource), b.(*v2beta1.ContainerResourceMetricSource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricStatus)(nil), (*v2beta1.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(a.(*autoscaling.ContainerResourceMetricStatus), b.(*v2beta1.ContainerResourceMetricStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*autoscaling.ExternalMetricSource)(nil), (*v2beta1.ExternalMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource(a.(*autoscaling.ExternalMetricSource), b.(*v2beta1.ExternalMetricSource), scope)
|
||||
}); err != nil {
|
||||
@ -159,6 +169,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*v2beta1.ContainerResourceMetricSource)(nil), (*autoscaling.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(a.(*v2beta1.ContainerResourceMetricSource), b.(*autoscaling.ContainerResourceMetricSource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*v2beta1.ContainerResourceMetricStatus)(nil), (*autoscaling.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(a.(*v2beta1.ContainerResourceMetricStatus), b.(*autoscaling.ContainerResourceMetricStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*v2beta1.CrossVersionObjectReference)(nil), (*autoscaling.MetricTarget)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v2beta1_CrossVersionObjectReference_To_autoscaling_MetricTarget(a.(*v2beta1.CrossVersionObjectReference), b.(*autoscaling.MetricTarget), scope)
|
||||
}); err != nil {
|
||||
@ -212,6 +232,36 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v2beta1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
// WARNING: in.TargetAverageUtilization requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.TargetAverageValue requires manual conversion: does not exist in peer-type
|
||||
out.Container = in.Container
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v2beta1.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
// WARNING: in.Target requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v2beta1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
// WARNING: in.CurrentAverageUtilization requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.CurrentAverageValue requires manual conversion: does not exist in peer-type
|
||||
out.Container = in.Container
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v2beta1.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
// WARNING: in.Current requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v2beta1_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(in *v2beta1.CrossVersionObjectReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
@ -481,6 +531,15 @@ func autoConvert_v2beta1_MetricSpec_To_autoscaling_MetricSpec(in *v2beta1.Metric
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(autoscaling.ContainerResourceMetricSource)
|
||||
if err := Convert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(autoscaling.ExternalMetricSource)
|
||||
@ -527,6 +586,15 @@ func autoConvert_autoscaling_MetricSpec_To_v2beta1_MetricSpec(in *autoscaling.Me
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(v2beta1.ContainerResourceMetricSource)
|
||||
if err := Convert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(v2beta1.ExternalMetricSource)
|
||||
@ -573,6 +641,15 @@ func autoConvert_v2beta1_MetricStatus_To_autoscaling_MetricStatus(in *v2beta1.Me
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(autoscaling.ContainerResourceMetricStatus)
|
||||
if err := Convert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(autoscaling.ExternalMetricStatus)
|
||||
@ -619,6 +696,15 @@ func autoConvert_autoscaling_MetricStatus_To_v2beta1_MetricStatus(in *autoscalin
|
||||
} else {
|
||||
out.Resource = nil
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(v2beta1.ContainerResourceMetricStatus)
|
||||
if err := Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(v2beta1.ExternalMetricStatus)
|
||||
|
160
pkg/apis/autoscaling/v2beta2/zz_generated.conversion.go
generated
160
pkg/apis/autoscaling/v2beta2/zz_generated.conversion.go
generated
@ -40,6 +40,26 @@ func init() {
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta2.ContainerResourceMetricSource)(nil), (*autoscaling.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(a.(*v2beta2.ContainerResourceMetricSource), b.(*autoscaling.ContainerResourceMetricSource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*autoscaling.ContainerResourceMetricSource)(nil), (*v2beta2.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(a.(*autoscaling.ContainerResourceMetricSource), b.(*v2beta2.ContainerResourceMetricSource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta2.ContainerResourceMetricStatus)(nil), (*autoscaling.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(a.(*v2beta2.ContainerResourceMetricStatus), b.(*autoscaling.ContainerResourceMetricStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*autoscaling.ContainerResourceMetricStatus)(nil), (*v2beta2.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(a.(*autoscaling.ContainerResourceMetricStatus), b.(*v2beta2.ContainerResourceMetricStatus), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta2.CrossVersionObjectReference)(nil), (*autoscaling.CrossVersionObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v2beta2_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(a.(*v2beta2.CrossVersionObjectReference), b.(*autoscaling.CrossVersionObjectReference), scope)
|
||||
}); err != nil {
|
||||
@ -263,6 +283,62 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v2beta2.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
if err := Convert_v2beta2_MetricTarget_To_autoscaling_MetricTarget(&in.Target, &out.Target, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Container = in.Container
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource is an autogenerated conversion function.
|
||||
func Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v2beta2.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
return autoConvert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v2beta2.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
if err := Convert_autoscaling_MetricTarget_To_v2beta2_MetricTarget(&in.Target, &out.Target, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource is an autogenerated conversion function.
|
||||
func Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v2beta2.ContainerResourceMetricSource, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v2beta2.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = core.ResourceName(in.Name)
|
||||
if err := Convert_v2beta2_MetricValueStatus_To_autoscaling_MetricValueStatus(&in.Current, &out.Current, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Container = in.Container
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus is an autogenerated conversion function.
|
||||
func Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v2beta2.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
return autoConvert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v2beta2.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Container = in.Container
|
||||
if err := Convert_autoscaling_MetricValueStatus_To_v2beta2_MetricValueStatus(&in.Current, &out.Current, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus is an autogenerated conversion function.
|
||||
func Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v2beta2.ContainerResourceMetricStatus, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v2beta2_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(in *v2beta2.CrossVersionObjectReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
@ -515,7 +591,17 @@ func autoConvert_v2beta2_HorizontalPodAutoscalerSpec_To_autoscaling_HorizontalPo
|
||||
}
|
||||
out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas))
|
||||
out.MaxReplicas = in.MaxReplicas
|
||||
out.Metrics = *(*[]autoscaling.MetricSpec)(unsafe.Pointer(&in.Metrics))
|
||||
if in.Metrics != nil {
|
||||
in, out := &in.Metrics, &out.Metrics
|
||||
*out = make([]autoscaling.MetricSpec, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v2beta2_MetricSpec_To_autoscaling_MetricSpec(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Metrics = nil
|
||||
}
|
||||
out.Behavior = (*autoscaling.HorizontalPodAutoscalerBehavior)(unsafe.Pointer(in.Behavior))
|
||||
return nil
|
||||
}
|
||||
@ -531,7 +617,17 @@ func autoConvert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta2_HorizontalPo
|
||||
}
|
||||
out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas))
|
||||
out.MaxReplicas = in.MaxReplicas
|
||||
out.Metrics = *(*[]v2beta2.MetricSpec)(unsafe.Pointer(&in.Metrics))
|
||||
if in.Metrics != nil {
|
||||
in, out := &in.Metrics, &out.Metrics
|
||||
*out = make([]v2beta2.MetricSpec, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_autoscaling_MetricSpec_To_v2beta2_MetricSpec(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Metrics = nil
|
||||
}
|
||||
out.Behavior = (*v2beta2.HorizontalPodAutoscalerBehavior)(unsafe.Pointer(in.Behavior))
|
||||
return nil
|
||||
}
|
||||
@ -546,7 +642,17 @@ func autoConvert_v2beta2_HorizontalPodAutoscalerStatus_To_autoscaling_Horizontal
|
||||
out.LastScaleTime = (*metav1.Time)(unsafe.Pointer(in.LastScaleTime))
|
||||
out.CurrentReplicas = in.CurrentReplicas
|
||||
out.DesiredReplicas = in.DesiredReplicas
|
||||
out.CurrentMetrics = *(*[]autoscaling.MetricStatus)(unsafe.Pointer(&in.CurrentMetrics))
|
||||
if in.CurrentMetrics != nil {
|
||||
in, out := &in.CurrentMetrics, &out.CurrentMetrics
|
||||
*out = make([]autoscaling.MetricStatus, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v2beta2_MetricStatus_To_autoscaling_MetricStatus(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.CurrentMetrics = nil
|
||||
}
|
||||
out.Conditions = *(*[]autoscaling.HorizontalPodAutoscalerCondition)(unsafe.Pointer(&in.Conditions))
|
||||
return nil
|
||||
}
|
||||
@ -561,7 +667,17 @@ func autoConvert_autoscaling_HorizontalPodAutoscalerStatus_To_v2beta2_Horizontal
|
||||
out.LastScaleTime = (*metav1.Time)(unsafe.Pointer(in.LastScaleTime))
|
||||
out.CurrentReplicas = in.CurrentReplicas
|
||||
out.DesiredReplicas = in.DesiredReplicas
|
||||
out.CurrentMetrics = *(*[]v2beta2.MetricStatus)(unsafe.Pointer(&in.CurrentMetrics))
|
||||
if in.CurrentMetrics != nil {
|
||||
in, out := &in.CurrentMetrics, &out.CurrentMetrics
|
||||
*out = make([]v2beta2.MetricStatus, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_autoscaling_MetricStatus_To_v2beta2_MetricStatus(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.CurrentMetrics = nil
|
||||
}
|
||||
out.Conditions = *(*[]v2beta2.HorizontalPodAutoscalerCondition)(unsafe.Pointer(&in.Conditions))
|
||||
return nil
|
||||
}
|
||||
@ -598,6 +714,15 @@ func autoConvert_v2beta2_MetricSpec_To_autoscaling_MetricSpec(in *v2beta2.Metric
|
||||
out.Object = (*autoscaling.ObjectMetricSource)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*autoscaling.PodsMetricSource)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*autoscaling.ResourceMetricSource)(unsafe.Pointer(in.Resource))
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(autoscaling.ContainerResourceMetricSource)
|
||||
if err := Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
out.External = (*autoscaling.ExternalMetricSource)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
@ -612,6 +737,15 @@ func autoConvert_autoscaling_MetricSpec_To_v2beta2_MetricSpec(in *autoscaling.Me
|
||||
out.Object = (*v2beta2.ObjectMetricSource)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*v2beta2.PodsMetricSource)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*v2beta2.ResourceMetricSource)(unsafe.Pointer(in.Resource))
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(v2beta2.ContainerResourceMetricSource)
|
||||
if err := Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
out.External = (*v2beta2.ExternalMetricSource)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
@ -626,6 +760,15 @@ func autoConvert_v2beta2_MetricStatus_To_autoscaling_MetricStatus(in *v2beta2.Me
|
||||
out.Object = (*autoscaling.ObjectMetricStatus)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*autoscaling.PodsMetricStatus)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*autoscaling.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(autoscaling.ContainerResourceMetricStatus)
|
||||
if err := Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
out.External = (*autoscaling.ExternalMetricStatus)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
@ -640,6 +783,15 @@ func autoConvert_autoscaling_MetricStatus_To_v2beta2_MetricStatus(in *autoscalin
|
||||
out.Object = (*v2beta2.ObjectMetricStatus)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*v2beta2.PodsMetricStatus)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*v2beta2.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(v2beta2.ContainerResourceMetricStatus)
|
||||
if err := Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ContainerResource = nil
|
||||
}
|
||||
out.External = (*v2beta2.ExternalMetricStatus)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/autoscaling/validation",
|
||||
deps = [
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/core/v1/validation:go_default_library",
|
||||
"//pkg/apis/core/validation:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
|
||||
|
@ -18,14 +18,13 @@ package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
pathvalidation "k8s.io/apimachinery/pkg/api/validation/path"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
corevalidation "k8s.io/kubernetes/pkg/apis/core/v1/validation"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
@ -239,7 +238,10 @@ func validateScalingPolicy(policy autoscaling.HPAScalingPolicy, fldPath *field.P
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var validMetricSourceTypes = sets.NewString(string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType), string(autoscaling.ResourceMetricSourceType), string(autoscaling.ExternalMetricSourceType))
|
||||
var validMetricSourceTypes = sets.NewString(
|
||||
string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType),
|
||||
string(autoscaling.ResourceMetricSourceType), string(autoscaling.ExternalMetricSourceType),
|
||||
string(autoscaling.ContainerResourceMetricSourceType))
|
||||
var validMetricSourceTypesList = validMetricSourceTypes.List()
|
||||
|
||||
func validateMetricSpec(spec autoscaling.MetricSpec, fldPath *field.Path) field.ErrorList {
|
||||
@ -282,10 +284,47 @@ func validateMetricSpec(spec autoscaling.MetricSpec, fldPath *field.Path) field.
|
||||
}
|
||||
}
|
||||
|
||||
expectedField := strings.ToLower(string(spec.Type))
|
||||
if spec.ContainerResource != nil {
|
||||
typesPresent.Insert("containerResource")
|
||||
if typesPresent.Len() == 1 {
|
||||
allErrs = append(allErrs, validateContainerResourceSource(spec.ContainerResource, fldPath.Child("containerResource"))...)
|
||||
}
|
||||
}
|
||||
|
||||
if !typesPresent.Has(expectedField) {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child(expectedField), "must populate information for the given metric source"))
|
||||
var expectedField string
|
||||
switch spec.Type {
|
||||
|
||||
case autoscaling.ObjectMetricSourceType:
|
||||
if spec.Object == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("object"), "must populate information for the given metric source"))
|
||||
}
|
||||
expectedField = "object"
|
||||
case autoscaling.PodsMetricSourceType:
|
||||
if spec.Pods == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("pods"), "must populate information for the given metric source"))
|
||||
}
|
||||
expectedField = "pods"
|
||||
case autoscaling.ResourceMetricSourceType:
|
||||
if spec.Resource == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("resource"), "must populate information for the given metric source"))
|
||||
}
|
||||
expectedField = "resource"
|
||||
case autoscaling.ExternalMetricSourceType:
|
||||
if spec.External == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("external"), "must populate information for the given metric source"))
|
||||
}
|
||||
expectedField = "external"
|
||||
case autoscaling.ContainerResourceMetricSourceType:
|
||||
if spec.ContainerResource == nil {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.HPAContainerMetrics) {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("containerResource"), "must populate information for the given metric source"))
|
||||
} else {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("containerResource"), "must populate information for the given metric source (only allowed when HPAContainerMetrics feature is enabled)"))
|
||||
}
|
||||
}
|
||||
expectedField = "containerResource"
|
||||
default:
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), spec.Type, validMetricSourceTypesList))
|
||||
}
|
||||
|
||||
if typesPresent.Len() != 1 {
|
||||
@ -342,6 +381,34 @@ func validatePodsSource(src *autoscaling.PodsMetricSource, fldPath *field.Path)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateContainerResourceSource(src *autoscaling.ContainerResourceMetricSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(src.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must specify a resource name"))
|
||||
} else {
|
||||
allErrs = append(allErrs, corevalidation.ValidateContainerResourceName(string(src.Name), fldPath.Child("name"))...)
|
||||
}
|
||||
|
||||
if len(src.Container) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("container"), "must specify a container"))
|
||||
} else {
|
||||
allErrs = append(allErrs, apivalidation.ValidateDNS1123Label(src.Container, fldPath.Child("container"))...)
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validateMetricTarget(src.Target, fldPath.Child("target"))...)
|
||||
|
||||
if src.Target.AverageUtilization == nil && src.Target.AverageValue == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("target").Child("averageUtilization"), "must set either a target raw value or a target utilization"))
|
||||
}
|
||||
|
||||
if src.Target.AverageUtilization != nil && src.Target.AverageValue != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("target").Child("averageValue"), "may not set both a target raw value and a target utilization"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateResourceSource(src *autoscaling.ResourceMetricSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
|
@ -565,6 +565,60 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-container",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-container",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.AverageValueMetricType,
|
||||
AverageValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
@ -689,6 +743,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "scaleTargetRef.kind: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.kind: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -712,6 +790,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "scaleTargetRef.kind: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "..", Name: "myrc"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.kind: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -735,6 +837,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "scaleTargetRef.name: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.name: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -758,6 +884,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "scaleTargetRef.name: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "ReplicationController", Name: ".."},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.name: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -813,6 +963,34 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "may not set both a target raw value and a target utilization",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
AverageValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "may not set both a target raw value and a target utilization",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -835,6 +1013,53 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "must specify a resource name",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must specify a resource name",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: "InvalidResource",
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(70),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "Invalid value: \"InvalidResource\": must be a standard resource type or fully qualified",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -858,6 +1083,77 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(-10),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(-10),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must specify a container",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "---***",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(-10),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "Invalid value: \"---***\"",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -880,6 +1176,29 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "must set either a target raw value or a target utilization",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: utilpointer.Int32Ptr(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.ValueMetricType,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must set either a target raw value or a target utilization",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
@ -1321,6 +1640,16 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
autoscaling.ContainerResourceMetricSourceType: {
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "test-application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.AverageValueMetricType,
|
||||
AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
autoscaling.PodsMetricSourceType: {
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
Metric: autoscaling.MetricIdentifier{
|
||||
|
44
pkg/apis/autoscaling/zz_generated.deepcopy.go
generated
44
pkg/apis/autoscaling/zz_generated.deepcopy.go
generated
@ -25,6 +25,40 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricSource) DeepCopyInto(out *ContainerResourceMetricSource) {
|
||||
*out = *in
|
||||
in.Target.DeepCopyInto(&out.Target)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricSource.
|
||||
func (in *ContainerResourceMetricSource) DeepCopy() *ContainerResourceMetricSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopyInto(out *ContainerResourceMetricStatus) {
|
||||
*out = *in
|
||||
in.Current.DeepCopyInto(&out.Current)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricStatus.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopy() *ContainerResourceMetricStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CrossVersionObjectReference) DeepCopyInto(out *CrossVersionObjectReference) {
|
||||
*out = *in
|
||||
@ -340,6 +374,11 @@ func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
|
||||
*out = new(ResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricSource)
|
||||
@ -376,6 +415,11 @@ func (in *MetricStatus) DeepCopyInto(out *MetricStatus) {
|
||||
*out = new(ResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricStatus)
|
||||
|
@ -42,7 +42,7 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
||||
for resourceName, quantity := range requirements.Limits {
|
||||
fldPath := limPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
allErrs = append(allErrs, ValidateContainerResourceName(string(resourceName), fldPath)...)
|
||||
|
||||
// Validate resource quantity.
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
||||
@ -51,7 +51,7 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
||||
for resourceName, quantity := range requirements.Requests {
|
||||
fldPath := reqPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
allErrs = append(allErrs, ValidateContainerResourceName(string(resourceName), fldPath)...)
|
||||
// Validate resource quantity.
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
||||
|
||||
@ -70,7 +70,8 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
// ValidateContainerResourceName checks the name of resource specified for a container
|
||||
func ValidateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !helper.IsStandardContainerResourceName(value) {
|
||||
|
@ -129,6 +129,62 @@ func TestValidateResourceRequirements(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateContainerResourceName(t *testing.T) {
|
||||
successCase := []struct {
|
||||
Name string
|
||||
ResourceName string
|
||||
}{
|
||||
{
|
||||
Name: "CPU resource",
|
||||
ResourceName: "cpu",
|
||||
},
|
||||
{
|
||||
Name: "Memory resource",
|
||||
ResourceName: "memory",
|
||||
},
|
||||
{
|
||||
Name: "Hugepages resource",
|
||||
ResourceName: "hugepages-2Mi",
|
||||
},
|
||||
{
|
||||
Name: "Namespaced resource",
|
||||
ResourceName: "kubernetes.io/resource-foo",
|
||||
},
|
||||
{
|
||||
Name: "Extended Resource",
|
||||
ResourceName: "my.org/resource-bar",
|
||||
},
|
||||
}
|
||||
for _, tc := range successCase {
|
||||
if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) != 0 {
|
||||
t.Errorf("%q unexpected error: %v", tc.Name, errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCase := []struct {
|
||||
Name string
|
||||
ResourceName string
|
||||
}{
|
||||
{
|
||||
Name: "Invalid standard resource",
|
||||
ResourceName: "cpu-core",
|
||||
},
|
||||
{
|
||||
Name: "Invalid namespaced resource",
|
||||
ResourceName: "kubernetes.io/",
|
||||
},
|
||||
{
|
||||
Name: "Invalid extended resource",
|
||||
ResourceName: "my.org-foo-resource",
|
||||
},
|
||||
}
|
||||
for _, tc := range errorCase {
|
||||
if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) == 0 {
|
||||
t.Errorf("%q expected error", tc.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatePodLogOptions(t *testing.T) {
|
||||
|
||||
var (
|
||||
|
@ -329,6 +329,11 @@ func (a *HorizontalController) computeReplicasForMetric(hpa *autoscalingv2.Horiz
|
||||
if err != nil {
|
||||
return 0, "", time.Time{}, condition, err
|
||||
}
|
||||
case autoscalingv2.ContainerResourceMetricSourceType:
|
||||
replicaCountProposal, timestampProposal, metricNameProposal, condition, err = a.computeStatusForContainerResourceMetric(specReplicas, spec, hpa, selector, status)
|
||||
if err != nil {
|
||||
return 0, "", time.Time{}, condition, err
|
||||
}
|
||||
case autoscalingv2.ExternalMetricSourceType:
|
||||
replicaCountProposal, timestampProposal, metricNameProposal, condition, err = a.computeStatusForExternalMetric(specReplicas, statusReplicas, spec, hpa, selector, status)
|
||||
if err != nil {
|
||||
@ -435,51 +440,80 @@ func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32,
|
||||
return replicaCountProposal, timestampProposal, fmt.Sprintf("pods metric %s", metricSpec.Pods.Metric.Name), autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
|
||||
}
|
||||
|
||||
// computeStatusForResourceMetric computes the desired number of replicas for the specified metric of type ResourceMetricSourceType.
|
||||
func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (replicaCountProposal int32, timestampProposal time.Time, metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
|
||||
if metricSpec.Resource.Target.AverageValue != nil {
|
||||
func (a *HorizontalController) computeStatusForResourceMetricGeneric(currentReplicas int32, target autoscalingv2.MetricTarget,
|
||||
resourceName v1.ResourceName, namespace string, container string, selector labels.Selector) (replicaCountProposal int32,
|
||||
metricStatus *autoscalingv2.MetricValueStatus, timestampProposal time.Time, metricNameProposal string,
|
||||
condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
|
||||
if target.AverageValue != nil {
|
||||
var rawProposal int64
|
||||
replicaCountProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetRawResourceReplicas(currentReplicas, metricSpec.Resource.Target.AverageValue.MilliValue(), metricSpec.Resource.Name, hpa.Namespace, selector)
|
||||
replicaCountProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetRawResourceReplicas(currentReplicas, target.AverageValue.MilliValue(), resourceName, namespace, selector, container)
|
||||
if err != nil {
|
||||
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetResourceMetric", err)
|
||||
return 0, time.Time{}, "", condition, fmt.Errorf("failed to get %s utilization: %v", metricSpec.Resource.Name, err)
|
||||
return 0, nil, time.Time{}, "", condition, fmt.Errorf("failed to get %s utilization: %v", resourceName, err)
|
||||
}
|
||||
metricNameProposal = fmt.Sprintf("%s resource", metricSpec.Resource.Name)
|
||||
*status = autoscalingv2.MetricStatus{
|
||||
Type: autoscalingv2.ResourceMetricSourceType,
|
||||
Resource: &autoscalingv2.ResourceMetricStatus{
|
||||
Name: metricSpec.Resource.Name,
|
||||
Current: autoscalingv2.MetricValueStatus{
|
||||
AverageValue: resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
metricNameProposal = fmt.Sprintf("%s resource", resourceName.String())
|
||||
status := autoscalingv2.MetricValueStatus{
|
||||
AverageValue: resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
||||
}
|
||||
return replicaCountProposal, timestampProposal, metricNameProposal, autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
|
||||
return replicaCountProposal, &status, timestampProposal, metricNameProposal, autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
|
||||
}
|
||||
if metricSpec.Resource.Target.AverageUtilization == nil {
|
||||
|
||||
if target.AverageUtilization == nil {
|
||||
errMsg := "invalid resource metric source: neither a utilization target nor a value target was set"
|
||||
err = fmt.Errorf(errMsg)
|
||||
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetResourceMetric", err)
|
||||
return 0, time.Time{}, "", condition, fmt.Errorf(errMsg)
|
||||
return 0, nil, time.Time{}, "", condition, fmt.Errorf(errMsg)
|
||||
}
|
||||
targetUtilization := *metricSpec.Resource.Target.AverageUtilization
|
||||
replicaCountProposal, percentageProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetResourceReplicas(currentReplicas, targetUtilization, metricSpec.Resource.Name, hpa.Namespace, selector)
|
||||
|
||||
targetUtilization := *target.AverageUtilization
|
||||
replicaCountProposal, percentageProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetResourceReplicas(currentReplicas, targetUtilization, resourceName, namespace, selector, container)
|
||||
if err != nil {
|
||||
return 0, nil, time.Time{}, "", condition, fmt.Errorf("failed to get %s utilization: %v", resourceName, err)
|
||||
}
|
||||
|
||||
metricNameProposal = fmt.Sprintf("%s resource utilization (percentage of request)", resourceName)
|
||||
status := autoscalingv2.MetricValueStatus{
|
||||
AverageUtilization: &percentageProposal,
|
||||
AverageValue: resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
||||
}
|
||||
return replicaCountProposal, &status, timestampProposal, metricNameProposal, autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
|
||||
}
|
||||
|
||||
// computeStatusForResourceMetric computes the desired number of replicas for the specified metric of type ResourceMetricSourceType.
|
||||
func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler,
|
||||
selector labels.Selector, status *autoscalingv2.MetricStatus) (replicaCountProposal int32, timestampProposal time.Time,
|
||||
metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
|
||||
replicaCountProposal, metricValueStatus, timestampProposal, metricNameProposal, condition, err := a.computeStatusForResourceMetricGeneric(currentReplicas, metricSpec.Resource.Target, metricSpec.Resource.Name, hpa.Namespace, "", selector)
|
||||
if err != nil {
|
||||
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetResourceMetric", err)
|
||||
return 0, time.Time{}, "", condition, fmt.Errorf("failed to get %s utilization: %v", metricSpec.Resource.Name, err)
|
||||
return replicaCountProposal, timestampProposal, metricNameProposal, condition, err
|
||||
}
|
||||
metricNameProposal = fmt.Sprintf("%s resource utilization (percentage of request)", metricSpec.Resource.Name)
|
||||
*status = autoscalingv2.MetricStatus{
|
||||
Type: autoscalingv2.ResourceMetricSourceType,
|
||||
Resource: &autoscalingv2.ResourceMetricStatus{
|
||||
Name: metricSpec.Resource.Name,
|
||||
Current: autoscalingv2.MetricValueStatus{
|
||||
AverageUtilization: &percentageProposal,
|
||||
AverageValue: resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
||||
},
|
||||
Name: metricSpec.Resource.Name,
|
||||
Current: *metricValueStatus,
|
||||
},
|
||||
}
|
||||
return replicaCountProposal, timestampProposal, metricNameProposal, autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
|
||||
return replicaCountProposal, timestampProposal, metricNameProposal, condition, nil
|
||||
}
|
||||
|
||||
// computeStatusForContainerResourceMetric computes the desired number of replicas for the specified metric of type ResourceMetricSourceType.
|
||||
func (a *HorizontalController) computeStatusForContainerResourceMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler,
|
||||
selector labels.Selector, status *autoscalingv2.MetricStatus) (replicaCountProposal int32, timestampProposal time.Time,
|
||||
metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
|
||||
replicaCountProposal, metricValueStatus, timestampProposal, metricNameProposal, condition, err := a.computeStatusForResourceMetricGeneric(currentReplicas, metricSpec.ContainerResource.Target, metricSpec.ContainerResource.Name, hpa.Namespace, metricSpec.ContainerResource.Container, selector)
|
||||
if err != nil {
|
||||
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetContainerResourceMetric", err)
|
||||
return replicaCountProposal, timestampProposal, metricNameProposal, condition, err
|
||||
}
|
||||
*status = autoscalingv2.MetricStatus{
|
||||
Type: autoscalingv2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2.ContainerResourceMetricStatus{
|
||||
Name: metricSpec.ContainerResource.Name,
|
||||
Container: metricSpec.ContainerResource.Container,
|
||||
Current: *metricValueStatus,
|
||||
},
|
||||
}
|
||||
return replicaCountProposal, timestampProposal, metricNameProposal, condition, nil
|
||||
}
|
||||
|
||||
// computeStatusForExternalMetric computes the desired number of replicas for the specified metric of type ExternalMetricSourceType.
|
||||
@ -783,7 +817,7 @@ func getReplicasChangePerPeriod(periodSeconds int32, scaleEvents []timestampedSc
|
||||
|
||||
}
|
||||
|
||||
func (a *HorizontalController) getUnableComputeReplicaCountCondition(hpa *autoscalingv2.HorizontalPodAutoscaler, reason string, err error) (condition autoscalingv2.HorizontalPodAutoscalerCondition) {
|
||||
func (a *HorizontalController) getUnableComputeReplicaCountCondition(hpa runtime.Object, reason string, err error) (condition autoscalingv2.HorizontalPodAutoscalerCondition) {
|
||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, reason, err.Error())
|
||||
return autoscalingv2.HorizontalPodAutoscalerCondition{
|
||||
Type: autoscalingv2.ScalingActive,
|
||||
|
@ -336,9 +336,18 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "container1",
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: reportedCPURequest,
|
||||
v1.ResourceCPU: *resource.NewMilliQuantity(reportedCPURequest.MilliValue()/2, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "container2",
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: *resource.NewMilliQuantity(reportedCPURequest.MilliValue()/2, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -509,13 +518,24 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
|
||||
Window: metav1.Duration{Duration: time.Minute},
|
||||
Containers: []metricsapi.ContainerMetrics{
|
||||
{
|
||||
Name: "container",
|
||||
Name: "container1",
|
||||
Usage: v1.ResourceList{
|
||||
v1.ResourceCPU: *resource.NewMilliQuantity(
|
||||
int64(cpu),
|
||||
int64(cpu/2),
|
||||
resource.DecimalSI),
|
||||
v1.ResourceMemory: *resource.NewQuantity(
|
||||
int64(1024*1024),
|
||||
int64(1024*1024/2),
|
||||
resource.BinarySI),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "container2",
|
||||
Usage: v1.ResourceList{
|
||||
v1.ResourceCPU: *resource.NewMilliQuantity(
|
||||
int64(cpu/2),
|
||||
resource.DecimalSI),
|
||||
v1.ResourceMemory: *resource.NewQuantity(
|
||||
int64(1024*1024/2),
|
||||
resource.BinarySI),
|
||||
},
|
||||
},
|
||||
@ -773,6 +793,31 @@ func TestScaleUp(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestScaleUpContainer(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
maxReplicas: 6,
|
||||
specReplicas: 3,
|
||||
statusReplicas: 3,
|
||||
expectedDesiredReplicas: 5,
|
||||
metricsTarget: []autoscalingv2.MetricSpec{{
|
||||
Type: autoscalingv2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2.ContainerResourceMetricSource{
|
||||
Name: v1.ResourceCPU,
|
||||
Target: autoscalingv2.MetricTarget{
|
||||
Type: autoscalingv2.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(30),
|
||||
},
|
||||
Container: "container1",
|
||||
},
|
||||
}},
|
||||
reportedLevels: []uint64{300, 500, 700},
|
||||
reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
useMetricsAPI: true,
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestScaleUpUnreadyLessScale(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
@ -1269,6 +1314,32 @@ func TestScaleDown(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestScaleDownContainerResource(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
maxReplicas: 6,
|
||||
specReplicas: 5,
|
||||
statusReplicas: 5,
|
||||
expectedDesiredReplicas: 3,
|
||||
reportedLevels: []uint64{100, 300, 500, 250, 250},
|
||||
reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
metricsTarget: []autoscalingv2.MetricSpec{{
|
||||
Type: autoscalingv2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2.ContainerResourceMetricSource{
|
||||
Container: "container2",
|
||||
Name: v1.ResourceCPU,
|
||||
Target: autoscalingv2.MetricTarget{
|
||||
Type: autoscalingv2.UtilizationMetricType,
|
||||
AverageUtilization: utilpointer.Int32Ptr(50),
|
||||
},
|
||||
},
|
||||
}},
|
||||
useMetricsAPI: true,
|
||||
recommendations: []timestampedRecommendation{},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestScaleDownWithScalingRules(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
@ -2809,7 +2880,7 @@ func TestScaleDownRCImmediately(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestAvoidUncessaryUpdates(t *testing.T) {
|
||||
func TestAvoidUnnecessaryUpdates(t *testing.T) {
|
||||
now := metav1.Time{Time: time.Now().Add(-time.Hour)}
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
|
@ -126,14 +126,11 @@ func (tc *legacyReplicaCalcTestCase) prepareTestClient(t *testing.T) *fake.Clien
|
||||
Timestamp: metav1.Time{Time: tc.timestamp},
|
||||
Containers: make([]metricsapi.ContainerMetrics, numContainersPerPod),
|
||||
}
|
||||
|
||||
for i := 0; i < numContainersPerPod; i++ {
|
||||
for i, m := range resValue {
|
||||
podMetric.Containers[i] = metricsapi.ContainerMetrics{
|
||||
Name: fmt.Sprintf("container%v", i),
|
||||
Usage: v1.ResourceList{
|
||||
v1.ResourceName(tc.resource.name): *resource.NewMilliQuantity(
|
||||
int64(resValue),
|
||||
resource.DecimalSI),
|
||||
tc.resource.name: *resource.NewMilliQuantity(m, resource.DecimalSI),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -209,7 +206,7 @@ func (tc *legacyReplicaCalcTestCase) runTest(t *testing.T) {
|
||||
}
|
||||
|
||||
if tc.resource != nil {
|
||||
outReplicas, outUtilization, outRawValue, outTimestamp, err := replicaCalc.GetResourceReplicas(tc.currentReplicas, tc.resource.targetUtilization, tc.resource.name, testNamespace, selector)
|
||||
outReplicas, outUtilization, outRawValue, outTimestamp, err := replicaCalc.GetResourceReplicas(tc.currentReplicas, tc.resource.targetUtilization, tc.resource.name, testNamespace, selector, "")
|
||||
|
||||
if tc.expectedError != nil {
|
||||
require.Error(t, err, "there should be an error calculating the replica count")
|
||||
@ -244,7 +241,7 @@ func TestLegacyReplicaCalcDisjointResourcesMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0")},
|
||||
levels: []int64{100},
|
||||
levels: makePodMetricLevels(100),
|
||||
podNames: []string{"an-older-pod-name"},
|
||||
|
||||
targetUtilization: 100,
|
||||
@ -260,7 +257,7 @@ func TestLegacyReplicaCalcScaleUp(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{300, 500, 700},
|
||||
levels: makePodMetricLevels(300, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 50,
|
||||
@ -278,7 +275,7 @@ func TestLegacyReplicaCalcScaleUpUnreadyLessScale(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{300, 500, 700},
|
||||
levels: makePodMetricLevels(300, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
@ -296,7 +293,7 @@ func TestLegacyReplicaCalcScaleUpUnreadyNoScale(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{400, 500, 700},
|
||||
levels: makePodMetricLevels(400, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 40,
|
||||
@ -357,7 +354,7 @@ func TestLegacyReplicaCalcScaleDown(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
@ -389,7 +386,7 @@ func TestLegacyReplicaCalcScaleDownIgnoresUnreadyPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 30,
|
||||
@ -406,7 +403,7 @@ func TestLegacyReplicaCalcTolerance(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("0.9"), resource.MustParse("1.0"), resource.MustParse("1.1")},
|
||||
levels: []int64{1010, 1030, 1020},
|
||||
levels: makePodMetricLevels(1010, 1030, 1020),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 102,
|
||||
@ -437,7 +434,7 @@ func TestLegacyReplicaCalcSuperfluousMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{4000, 9500, 3000, 7000, 3200, 2000},
|
||||
levels: makePodMetricLevels(4000, 9500, 3000, 7000, 3200, 2000),
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 587,
|
||||
expectedValue: numContainersPerPod * 5875,
|
||||
@ -453,7 +450,7 @@ func TestLegacyReplicaCalcMissingMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{400, 95},
|
||||
levels: makePodMetricLevels(400, 95),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 24,
|
||||
@ -470,7 +467,7 @@ func TestLegacyReplicaCalcEmptyMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{},
|
||||
levels: makePodMetricLevels(),
|
||||
|
||||
targetUtilization: 100,
|
||||
},
|
||||
@ -485,7 +482,7 @@ func TestLegacyReplicaCalcEmptyCPURequest(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{},
|
||||
levels: []int64{200},
|
||||
levels: makePodMetricLevels(200),
|
||||
|
||||
targetUtilization: 100,
|
||||
},
|
||||
@ -500,7 +497,7 @@ func TestLegacyReplicaCalcMissingMetricsNoChangeEq(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{1000},
|
||||
levels: makePodMetricLevels(1000),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 100,
|
||||
@ -517,7 +514,7 @@ func TestLegacyReplicaCalcMissingMetricsNoChangeGt(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{1900},
|
||||
levels: makePodMetricLevels(1900),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 190,
|
||||
@ -534,7 +531,7 @@ func TestLegacyReplicaCalcMissingMetricsNoChangeLt(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{600},
|
||||
levels: makePodMetricLevels(600),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 60,
|
||||
@ -552,7 +549,7 @@ func TestLegacyReplicaCalcMissingMetricsUnreadyNoChange(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 450},
|
||||
levels: makePodMetricLevels(100, 450),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 45,
|
||||
@ -570,7 +567,7 @@ func TestLegacyReplicaCalcMissingMetricsUnreadyScaleUp(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 2000},
|
||||
levels: makePodMetricLevels(100, 2000),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 200,
|
||||
@ -588,7 +585,7 @@ func TestLegacyReplicaCalcMissingMetricsUnreadyScaleDown(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 100, 100},
|
||||
levels: makePodMetricLevels(100, 100, 100),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 10,
|
||||
@ -627,18 +624,18 @@ func TestLegacyReplicaCalcComputedToleranceAlgImplementation(t *testing.T) {
|
||||
expectedReplicas: finalPods,
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
levels: []int64{
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
},
|
||||
levels: makePodMetricLevels(
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
),
|
||||
requests: []resource.Quantity{
|
||||
resource.MustParse(fmt.Sprint(perPodRequested+100) + "m"),
|
||||
resource.MustParse(fmt.Sprint(perPodRequested-100) + "m"),
|
||||
|
@ -20,6 +20,7 @@ go_library(
|
||||
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
|
||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
|
||||
"//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library",
|
||||
|
@ -38,8 +38,9 @@ type PodMetricsInfo map[string]PodMetric
|
||||
// resource metrics as well as pod-level arbitrary metrics
|
||||
type MetricsClient interface {
|
||||
// GetResourceMetric gets the given resource metric (and an associated oldest timestamp)
|
||||
// for all pods matching the specified selector in the given namespace
|
||||
GetResourceMetric(resource v1.ResourceName, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error)
|
||||
// for the specified named container in all pods matching the specified selector in the given namespace and when
|
||||
// the container is an empty string it returns the sum of all the container metrics.
|
||||
GetResourceMetric(resource v1.ResourceName, namespace string, selector labels.Selector, container string) (PodMetricsInfo, time.Time, error)
|
||||
|
||||
// GetRawMetric gets the given metric (and an associated oldest timestamp)
|
||||
// for all pods matching the specified selector in the given namespace
|
||||
|
@ -63,7 +63,7 @@ func NewHeapsterMetricsClient(client clientset.Interface, namespace, scheme, ser
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HeapsterMetricsClient) GetResourceMetric(resource v1.ResourceName, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) {
|
||||
func (h *HeapsterMetricsClient) GetResourceMetric(resource v1.ResourceName, namespace string, selector labels.Selector, container string) (PodMetricsInfo, time.Time, error) {
|
||||
metricPath := fmt.Sprintf("/apis/metrics/v1alpha1/namespaces/%s/pods", namespace)
|
||||
params := map[string]string{"labelSelector": selector.String()}
|
||||
|
||||
@ -92,13 +92,15 @@ func (h *HeapsterMetricsClient) GetResourceMetric(resource v1.ResourceName, name
|
||||
podSum := int64(0)
|
||||
missing := len(m.Containers) == 0
|
||||
for _, c := range m.Containers {
|
||||
resValue, found := c.Usage[v1.ResourceName(resource)]
|
||||
if !found {
|
||||
missing = true
|
||||
klog.V(2).Infof("missing resource metric %v for container %s in pod %s/%s", resource, c.Name, namespace, m.Name)
|
||||
continue
|
||||
if container == "" || container == c.Name {
|
||||
resValue, found := c.Usage[v1.ResourceName(resource)]
|
||||
if !found {
|
||||
missing = true
|
||||
klog.V(2).Infof("missing resource metric %v for container %s in pod %s/%s", resource, c.Name, namespace, m.Name)
|
||||
continue
|
||||
}
|
||||
podSum += resValue.MilliValue()
|
||||
}
|
||||
podSum += resValue.MilliValue()
|
||||
}
|
||||
|
||||
if !missing {
|
||||
|
@ -222,7 +222,7 @@ func (tc *testCase) runTest(t *testing.T) {
|
||||
metricsClient := NewHeapsterMetricsClient(testClient, DefaultHeapsterNamespace, DefaultHeapsterScheme, DefaultHeapsterService, DefaultHeapsterPort)
|
||||
isResource := len(tc.resourceName) > 0
|
||||
if isResource {
|
||||
info, timestamp, err := metricsClient.GetResourceMetric(tc.resourceName, tc.namespace, tc.selector)
|
||||
info, timestamp, err := metricsClient.GetResourceMetric(tc.resourceName, tc.namespace, tc.selector, "")
|
||||
tc.verifyResults(t, info, timestamp, err)
|
||||
} else {
|
||||
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector, tc.metricSelector)
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
customapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
||||
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
|
||||
customclient "k8s.io/metrics/pkg/client/custom_metrics"
|
||||
externalclient "k8s.io/metrics/pkg/client/external_metrics"
|
||||
@ -63,7 +64,7 @@ type resourceMetricsClient struct {
|
||||
|
||||
// GetResourceMetric gets the given resource metric (and an associated oldest timestamp)
|
||||
// for all pods matching the specified selector in the given namespace
|
||||
func (c *resourceMetricsClient) GetResourceMetric(resource v1.ResourceName, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) {
|
||||
func (c *resourceMetricsClient) GetResourceMetric(resource v1.ResourceName, namespace string, selector labels.Selector, container string) (PodMetricsInfo, time.Time, error) {
|
||||
metrics, err := c.client.PodMetricses(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.String()})
|
||||
if err != nil {
|
||||
return nil, time.Time{}, fmt.Errorf("unable to fetch metrics from resource metrics API: %v", err)
|
||||
@ -72,34 +73,66 @@ func (c *resourceMetricsClient) GetResourceMetric(resource v1.ResourceName, name
|
||||
if len(metrics.Items) == 0 {
|
||||
return nil, time.Time{}, fmt.Errorf("no metrics returned from resource metrics API")
|
||||
}
|
||||
var res PodMetricsInfo
|
||||
if container != "" {
|
||||
res, err = getContainerMetrics(metrics.Items, resource, container)
|
||||
if err != nil {
|
||||
return nil, time.Time{}, fmt.Errorf("failed to get container metrics: %v", err)
|
||||
}
|
||||
} else {
|
||||
res = getPodMetrics(metrics.Items, resource)
|
||||
}
|
||||
timestamp := metrics.Items[0].Timestamp.Time
|
||||
return res, timestamp, nil
|
||||
}
|
||||
|
||||
res := make(PodMetricsInfo, len(metrics.Items))
|
||||
func getContainerMetrics(rawMetrics []metricsapi.PodMetrics, resource v1.ResourceName, container string) (PodMetricsInfo, error) {
|
||||
res := make(PodMetricsInfo, len(rawMetrics))
|
||||
for _, m := range rawMetrics {
|
||||
containerFound := false
|
||||
for _, c := range m.Containers {
|
||||
if c.Name == container {
|
||||
containerFound = true
|
||||
if val, resFound := c.Usage[resource]; resFound {
|
||||
res[m.Name] = PodMetric{
|
||||
Timestamp: m.Timestamp.Time,
|
||||
Window: m.Window.Duration,
|
||||
Value: val.MilliValue(),
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if !containerFound {
|
||||
return nil, fmt.Errorf("container %s not present in metrics for pod %s/%s", container, m.Namespace, m.Name)
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
for _, m := range metrics.Items {
|
||||
func getPodMetrics(rawMetrics []metricsapi.PodMetrics, resource v1.ResourceName) PodMetricsInfo {
|
||||
res := make(PodMetricsInfo, len(rawMetrics))
|
||||
for _, m := range rawMetrics {
|
||||
podSum := int64(0)
|
||||
missing := len(m.Containers) == 0
|
||||
for _, c := range m.Containers {
|
||||
resValue, found := c.Usage[v1.ResourceName(resource)]
|
||||
resValue, found := c.Usage[resource]
|
||||
if !found {
|
||||
missing = true
|
||||
klog.V(2).Infof("missing resource metric %v for container %s in pod %s/%s", resource, c.Name, namespace, m.Name)
|
||||
break // containers loop
|
||||
klog.V(2).Infof("missing resource metric %v for %s/%s", resource, m.Namespace, m.Name)
|
||||
break
|
||||
}
|
||||
podSum += resValue.MilliValue()
|
||||
}
|
||||
|
||||
if !missing {
|
||||
res[m.Name] = PodMetric{
|
||||
Timestamp: m.Timestamp.Time,
|
||||
Window: m.Window.Duration,
|
||||
Value: int64(podSum),
|
||||
Value: podSum,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timestamp := metrics.Items[0].Timestamp.Time
|
||||
|
||||
return res, timestamp, nil
|
||||
return res
|
||||
}
|
||||
|
||||
// customMetricsClient implements the custom-metrics-related parts of MetricsClient,
|
||||
|
@ -50,12 +50,13 @@ type restClientTestCase struct {
|
||||
targetTimestamp int
|
||||
window time.Duration
|
||||
reportedMetricPoints []metricPoint
|
||||
reportedPodMetrics [][]int64
|
||||
reportedPodMetrics []map[string]int64
|
||||
singleObject *autoscalingapi.CrossVersionObjectReference
|
||||
|
||||
namespace string
|
||||
selector labels.Selector
|
||||
resourceName v1.ResourceName
|
||||
container string
|
||||
metricName string
|
||||
metricSelector *metav1.LabelSelector
|
||||
metricLabelSelector labels.Selector
|
||||
@ -91,9 +92,9 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie
|
||||
Window: metav1.Duration{Duration: tc.window},
|
||||
Containers: []metricsapi.ContainerMetrics{},
|
||||
}
|
||||
for j, cpu := range containers {
|
||||
for containerName, cpu := range containers {
|
||||
cm := metricsapi.ContainerMetrics{
|
||||
Name: fmt.Sprintf("%s-%d-container-%d", podNamePrefix, i, j),
|
||||
Name: containerName,
|
||||
Usage: v1.ResourceList{
|
||||
v1.ResourceCPU: *resource.NewMilliQuantity(
|
||||
cpu,
|
||||
@ -230,7 +231,7 @@ func (tc *restClientTestCase) runTest(t *testing.T) {
|
||||
isResource := len(tc.resourceName) > 0
|
||||
isExternal := tc.metricSelector != nil
|
||||
if isResource {
|
||||
info, timestamp, err := metricsClient.GetResourceMetric(v1.ResourceName(tc.resourceName), tc.namespace, tc.selector)
|
||||
info, timestamp, err := metricsClient.GetResourceMetric(v1.ResourceName(tc.resourceName), tc.namespace, tc.selector, tc.container)
|
||||
tc.verifyResults(t, info, timestamp, err)
|
||||
} else if isExternal {
|
||||
tc.metricLabelSelector, err = metav1.LabelSelectorAsSelector(tc.metricSelector)
|
||||
@ -253,7 +254,7 @@ func (tc *restClientTestCase) runTest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTClientCPU(t *testing.T) {
|
||||
func TestRESTClientPodCPU(t *testing.T) {
|
||||
targetTimestamp := 1
|
||||
window := 30 * time.Second
|
||||
tc := restClientTestCase{
|
||||
@ -265,7 +266,25 @@ func TestRESTClientCPU(t *testing.T) {
|
||||
resourceName: v1.ResourceCPU,
|
||||
targetTimestamp: targetTimestamp,
|
||||
window: window,
|
||||
reportedPodMetrics: [][]int64{{5000}, {5000}, {5000}},
|
||||
reportedPodMetrics: []map[string]int64{{"test": 5000}, {"test": 5000}, {"test": 5000}},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestRESTClientContainerCPU(t *testing.T) {
|
||||
targetTimestamp := 1
|
||||
window := 30 * time.Second
|
||||
tc := restClientTestCase{
|
||||
desiredMetricValues: PodMetricsInfo{
|
||||
"test-pod-0": {Value: 5000, Timestamp: offsetTimestampBy(targetTimestamp), Window: window},
|
||||
"test-pod-1": {Value: 5000, Timestamp: offsetTimestampBy(targetTimestamp), Window: window},
|
||||
"test-pod-2": {Value: 5000, Timestamp: offsetTimestampBy(targetTimestamp), Window: window},
|
||||
},
|
||||
container: "test-1",
|
||||
resourceName: v1.ResourceCPU,
|
||||
targetTimestamp: targetTimestamp,
|
||||
window: window,
|
||||
reportedPodMetrics: []map[string]int64{{"test-1": 5000, "test-2": 500}, {"test-1": 5000, "test-2": 500}, {"test-1": 5000, "test-2": 500}},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
@ -362,17 +381,17 @@ func TestRESTClientExternalEmptyMetrics(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestRESTClientCPUEmptyMetrics(t *testing.T) {
|
||||
func TestRESTClientPodCPUEmptyMetrics(t *testing.T) {
|
||||
tc := restClientTestCase{
|
||||
resourceName: v1.ResourceCPU,
|
||||
desiredError: fmt.Errorf("no metrics returned from resource metrics API"),
|
||||
reportedMetricPoints: []metricPoint{},
|
||||
reportedPodMetrics: [][]int64{},
|
||||
reportedPodMetrics: []map[string]int64{},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestRESTClientCPUEmptyMetricsForOnePod(t *testing.T) {
|
||||
func TestRESTClientPodCPUEmptyMetricsForOnePod(t *testing.T) {
|
||||
targetTimestamp := 1
|
||||
window := 30 * time.Second
|
||||
tc := restClientTestCase{
|
||||
@ -383,7 +402,25 @@ func TestRESTClientCPUEmptyMetricsForOnePod(t *testing.T) {
|
||||
},
|
||||
targetTimestamp: targetTimestamp,
|
||||
window: window,
|
||||
reportedPodMetrics: [][]int64{{100}, {300, 400}, {}},
|
||||
reportedPodMetrics: []map[string]int64{{"test-1": 100}, {"test-1": 300, "test-2": 400}, {}},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestRESTClientContainerCPUEmptyMetricsForOnePod(t *testing.T) {
|
||||
targetTimestamp := 1
|
||||
window := 30 * time.Second
|
||||
tc := restClientTestCase{
|
||||
resourceName: v1.ResourceCPU,
|
||||
desiredMetricValues: PodMetricsInfo{
|
||||
"test-pod-0": {Value: 100, Timestamp: offsetTimestampBy(targetTimestamp), Window: window},
|
||||
"test-pod-1": {Value: 300, Timestamp: offsetTimestampBy(targetTimestamp), Window: window},
|
||||
},
|
||||
container: "test-1",
|
||||
targetTimestamp: targetTimestamp,
|
||||
window: window,
|
||||
desiredError: fmt.Errorf("failed to get container metrics"),
|
||||
reportedPodMetrics: []map[string]int64{{"test-1": 100}, {"test-1": 300, "test-2": 400}, {}},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ func NewReplicaCalculator(metricsClient metricsclient.MetricsClient, podLister c
|
||||
|
||||
// GetResourceReplicas calculates the desired replica count based on a target resource utilization percentage
|
||||
// of the given resource for pods matching the given selector in the given namespace, and the current replica count
|
||||
func (c *ReplicaCalculator) GetResourceReplicas(currentReplicas int32, targetUtilization int32, resource v1.ResourceName, namespace string, selector labels.Selector) (replicaCount int32, utilization int32, rawUtilization int64, timestamp time.Time, err error) {
|
||||
metrics, timestamp, err := c.metricsClient.GetResourceMetric(resource, namespace, selector)
|
||||
func (c *ReplicaCalculator) GetResourceReplicas(currentReplicas int32, targetUtilization int32, resource v1.ResourceName, namespace string, selector labels.Selector, container string) (replicaCount int32, utilization int32, rawUtilization int64, timestamp time.Time, err error) {
|
||||
metrics, timestamp, err := c.metricsClient.GetResourceMetric(resource, namespace, selector, container)
|
||||
if err != nil {
|
||||
return 0, 0, 0, time.Time{}, fmt.Errorf("unable to get metrics for resource %s: %v", resource, err)
|
||||
}
|
||||
@ -79,7 +79,7 @@ func (c *ReplicaCalculator) GetResourceReplicas(currentReplicas int32, targetUti
|
||||
readyPodCount, unreadyPods, missingPods, ignoredPods := groupPods(podList, metrics, resource, c.cpuInitializationPeriod, c.delayOfInitialReadinessStatus)
|
||||
removeMetricsForPods(metrics, ignoredPods)
|
||||
removeMetricsForPods(metrics, unreadyPods)
|
||||
requests, err := calculatePodRequests(podList, resource)
|
||||
requests, err := calculatePodRequests(podList, container, resource)
|
||||
if err != nil {
|
||||
return 0, 0, 0, time.Time{}, err
|
||||
}
|
||||
@ -150,8 +150,8 @@ func (c *ReplicaCalculator) GetResourceReplicas(currentReplicas int32, targetUti
|
||||
|
||||
// GetRawResourceReplicas calculates the desired replica count based on a target resource utilization (as a raw milli-value)
|
||||
// for pods matching the given selector in the given namespace, and the current replica count
|
||||
func (c *ReplicaCalculator) GetRawResourceReplicas(currentReplicas int32, targetUtilization int64, resource v1.ResourceName, namespace string, selector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
|
||||
metrics, timestamp, err := c.metricsClient.GetResourceMetric(resource, namespace, selector)
|
||||
func (c *ReplicaCalculator) GetRawResourceReplicas(currentReplicas int32, targetUtilization int64, resource v1.ResourceName, namespace string, selector labels.Selector, container string) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
|
||||
metrics, timestamp, err := c.metricsClient.GetResourceMetric(resource, namespace, selector, container)
|
||||
if err != nil {
|
||||
return 0, 0, time.Time{}, fmt.Errorf("unable to get metrics for resource %s: %v", resource, err)
|
||||
}
|
||||
@ -414,15 +414,17 @@ func groupPods(pods []*v1.Pod, metrics metricsclient.PodMetricsInfo, resource v1
|
||||
return
|
||||
}
|
||||
|
||||
func calculatePodRequests(pods []*v1.Pod, resource v1.ResourceName) (map[string]int64, error) {
|
||||
func calculatePodRequests(pods []*v1.Pod, container string, resource v1.ResourceName) (map[string]int64, error) {
|
||||
requests := make(map[string]int64, len(pods))
|
||||
for _, pod := range pods {
|
||||
podSum := int64(0)
|
||||
for _, container := range pod.Spec.Containers {
|
||||
if containerRequest, ok := container.Resources.Requests[resource]; ok {
|
||||
podSum += containerRequest.MilliValue()
|
||||
} else {
|
||||
return nil, fmt.Errorf("missing request for %s", resource)
|
||||
for _, c := range pod.Spec.Containers {
|
||||
if container == "" || container == c.Name {
|
||||
if containerRequest, ok := c.Resources.Requests[resource]; ok {
|
||||
podSum += containerRequest.MilliValue()
|
||||
} else {
|
||||
return nil, fmt.Errorf("missing request for %s", resource)
|
||||
}
|
||||
}
|
||||
}
|
||||
requests[pod.Name] = podSum
|
||||
|
@ -52,7 +52,7 @@ import (
|
||||
type resourceInfo struct {
|
||||
name v1.ResourceName
|
||||
requests []resource.Quantity
|
||||
levels []int64
|
||||
levels [][]int64
|
||||
// only applies to pod names returned from "heapster"
|
||||
podNames []string
|
||||
|
||||
@ -93,6 +93,7 @@ type replicaCalcTestCase struct {
|
||||
resource *resourceInfo
|
||||
metric *metricInfo
|
||||
metricLabelSelector labels.Selector
|
||||
container string
|
||||
|
||||
podReadiness []v1.ConditionStatus
|
||||
podStartTime []metav1.Time
|
||||
@ -152,7 +153,7 @@ func (tc *replicaCalcTestCase) prepareTestClientSet() *fake.Clientset {
|
||||
},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{{}, {}},
|
||||
Containers: []v1.Container{{Name: "container1"}, {Name: "container2"}},
|
||||
},
|
||||
}
|
||||
if podDeletionTimestamp {
|
||||
@ -202,13 +203,11 @@ func (tc *replicaCalcTestCase) prepareTestMetricsClient() *metricsfake.Clientset
|
||||
Containers: make([]metricsapi.ContainerMetrics, numContainersPerPod),
|
||||
}
|
||||
|
||||
for i := 0; i < numContainersPerPod; i++ {
|
||||
for i, m := range resValue {
|
||||
podMetric.Containers[i] = metricsapi.ContainerMetrics{
|
||||
Name: fmt.Sprintf("container%v", i),
|
||||
Name: fmt.Sprintf("container%v", i+1),
|
||||
Usage: v1.ResourceList{
|
||||
v1.ResourceName(tc.resource.name): *resource.NewMilliQuantity(
|
||||
int64(resValue),
|
||||
resource.DecimalSI),
|
||||
tc.resource.name: *resource.NewMilliQuantity(m, resource.DecimalSI),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -362,7 +361,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
|
||||
}
|
||||
|
||||
if tc.resource != nil {
|
||||
outReplicas, outUtilization, outRawValue, outTimestamp, err := replicaCalc.GetResourceReplicas(tc.currentReplicas, tc.resource.targetUtilization, tc.resource.name, testNamespace, selector)
|
||||
outReplicas, outUtilization, outRawValue, outTimestamp, err := replicaCalc.GetResourceReplicas(tc.currentReplicas, tc.resource.targetUtilization, tc.resource.name, testNamespace, selector, tc.container)
|
||||
|
||||
if tc.expectedError != nil {
|
||||
require.Error(t, err, "there should be an error calculating the replica count")
|
||||
@ -424,7 +423,16 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
|
||||
assert.Equal(t, tc.metric.expectedUtilization, outUtilization, "utilization should be as expected")
|
||||
assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected")
|
||||
}
|
||||
|
||||
func makePodMetricLevels(containerMetric ...int64) [][]int64 {
|
||||
metrics := make([][]int64, len(containerMetric))
|
||||
for i := 0; i < len(containerMetric); i++ {
|
||||
metrics[i] = make([]int64, numContainersPerPod)
|
||||
for j := 0; j < numContainersPerPod; j++ {
|
||||
metrics[i][j] = containerMetric[i]
|
||||
}
|
||||
}
|
||||
return metrics
|
||||
}
|
||||
func TestReplicaCalcDisjointResourcesMetrics(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 1,
|
||||
@ -432,7 +440,7 @@ func TestReplicaCalcDisjointResourcesMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0")},
|
||||
levels: []int64{100},
|
||||
levels: makePodMetricLevels(100),
|
||||
podNames: []string{"an-older-pod-name"},
|
||||
|
||||
targetUtilization: 100,
|
||||
@ -441,6 +449,20 @@ func TestReplicaCalcDisjointResourcesMetrics(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcMissingContainerMetricError(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 1,
|
||||
expectedError: fmt.Errorf("container container2 not present in metrics for pod test-namespace/test-pod-0"),
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0")},
|
||||
levels: [][]int64{{0}},
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUp(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 3,
|
||||
@ -448,7 +470,7 @@ func TestReplicaCalcScaleUp(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{300, 500, 700},
|
||||
levels: makePodMetricLevels(300, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 50,
|
||||
@ -458,6 +480,24 @@ func TestReplicaCalcScaleUp(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcContainerScaleUp(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 3,
|
||||
expectedReplicas: 5,
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 300}, {1000, 500}, {1000, 700}},
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 50,
|
||||
expectedValue: 500,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpUnreadyLessScale(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 3,
|
||||
@ -466,7 +506,7 @@ func TestReplicaCalcScaleUpUnreadyLessScale(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{300, 500, 700},
|
||||
levels: makePodMetricLevels(300, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
@ -476,6 +516,25 @@ func TestReplicaCalcScaleUpUnreadyLessScale(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpContainerHotCpuLessScale(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 3,
|
||||
expectedReplicas: 4,
|
||||
podStartTime: []metav1.Time{hotCPUCreationTime(), coolCPUCreationTime(), coolCPUCreationTime()},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{0, 300}, {0, 500}, {0, 700}},
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
expectedValue: 600,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpHotCpuLessScale(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 3,
|
||||
@ -484,7 +543,7 @@ func TestReplicaCalcScaleUpHotCpuLessScale(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{300, 500, 700},
|
||||
levels: makePodMetricLevels(300, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
@ -502,7 +561,7 @@ func TestReplicaCalcScaleUpUnreadyNoScale(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{400, 500, 700},
|
||||
levels: makePodMetricLevels(400, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 40,
|
||||
@ -521,7 +580,7 @@ func TestReplicaCalcScaleHotCpuNoScale(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{400, 500, 700},
|
||||
levels: makePodMetricLevels(400, 500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 40,
|
||||
@ -540,7 +599,7 @@ func TestReplicaCalcScaleUpIgnoresFailedPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{500, 700},
|
||||
levels: makePodMetricLevels(500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
@ -550,6 +609,26 @@ func TestReplicaCalcScaleUpIgnoresFailedPods(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpContainerIgnoresFailedPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 2,
|
||||
expectedReplicas: 4,
|
||||
podReadiness: []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionTrue, v1.ConditionFalse, v1.ConditionFalse},
|
||||
podPhase: []v1.PodPhase{v1.PodRunning, v1.PodRunning, v1.PodFailed, v1.PodFailed},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 500}, {9000, 700}},
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
expectedValue: 600,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpIgnoresDeletionPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 2,
|
||||
@ -560,7 +639,7 @@ func TestReplicaCalcScaleUpIgnoresDeletionPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{500, 700},
|
||||
levels: makePodMetricLevels(500, 700),
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
@ -570,6 +649,27 @@ func TestReplicaCalcScaleUpIgnoresDeletionPods(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpContainerIgnoresDeletionPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 2,
|
||||
expectedReplicas: 4,
|
||||
podReadiness: []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionTrue, v1.ConditionFalse, v1.ConditionFalse},
|
||||
podPhase: []v1.PodPhase{v1.PodRunning, v1.PodRunning, v1.PodRunning, v1.PodRunning},
|
||||
podDeletionTimestamp: []bool{false, false, true, true},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: makePodMetricLevels(500, 700), // TODO: This test is broken and works only because of missing metrics
|
||||
|
||||
targetUtilization: 30,
|
||||
expectedUtilization: 60,
|
||||
expectedValue: 600,
|
||||
},
|
||||
container: "container1",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleUpCM(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 3,
|
||||
@ -749,7 +849,7 @@ func TestReplicaCalcScaleDown(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
@ -759,6 +859,24 @@ func TestReplicaCalcScaleDown(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcContainerScaleDown(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
expectedReplicas: 3,
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 100}, {1000, 300}, {1000, 500}, {1000, 250}, {1000, 250}},
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
expectedValue: 280,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownCM(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
@ -845,7 +963,7 @@ func TestReplicaCalcScaleDownPerPodCMExternal(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownIncludeUnreadyPods(t *testing.T) {
|
||||
func TestReplicaCalcScaleDownExcludeUnreadyPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
expectedReplicas: 2,
|
||||
@ -853,7 +971,7 @@ func TestReplicaCalcScaleDownIncludeUnreadyPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 30,
|
||||
@ -863,6 +981,25 @@ func TestReplicaCalcScaleDownIncludeUnreadyPods(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownContainerExcludeUnreadyPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
expectedReplicas: 2,
|
||||
podReadiness: []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionTrue, v1.ConditionTrue, v1.ConditionFalse, v1.ConditionFalse},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 100}, {1000, 300}, {1000, 500}, {1000, 250}, {1000, 250}},
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 30,
|
||||
expectedValue: 300,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownExcludeUnscheduledPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
@ -872,7 +1009,7 @@ func TestReplicaCalcScaleDownExcludeUnscheduledPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100},
|
||||
levels: makePodMetricLevels(100),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 10,
|
||||
@ -882,6 +1019,26 @@ func TestReplicaCalcScaleDownExcludeUnscheduledPods(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownContainerExcludeUnscheduledPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
expectedReplicas: 1,
|
||||
podReadiness: []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionFalse, v1.ConditionFalse, v1.ConditionFalse, v1.ConditionFalse},
|
||||
podPhase: []v1.PodPhase{v1.PodRunning, v1.PodPending, v1.PodPending, v1.PodPending, v1.PodPending},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 100}, {1000, 300}, {1000, 500}, {1000, 250}, {1000, 250}},
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 10,
|
||||
expectedValue: 100,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownIgnoreHotCpuPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
@ -890,7 +1047,7 @@ func TestReplicaCalcScaleDownIgnoreHotCpuPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 30,
|
||||
@ -900,6 +1057,25 @@ func TestReplicaCalcScaleDownIgnoreHotCpuPods(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownContainerIgnoreHotCpuPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
expectedReplicas: 2,
|
||||
podStartTime: []metav1.Time{coolCPUCreationTime(), coolCPUCreationTime(), coolCPUCreationTime(), hotCPUCreationTime(), hotCPUCreationTime()},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 100}, {1000, 300}, {1000, 500}, {1000, 1000}, {1000, 1000}},
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 30,
|
||||
expectedValue: 300,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownIgnoresFailedPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
@ -909,7 +1085,7 @@ func TestReplicaCalcScaleDownIgnoresFailedPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
@ -919,6 +1095,26 @@ func TestReplicaCalcScaleDownIgnoresFailedPods(t *testing.T) {
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownContainerIgnoresFailedPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
expectedReplicas: 3,
|
||||
podReadiness: []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionTrue, v1.ConditionTrue, v1.ConditionTrue, v1.ConditionTrue, v1.ConditionFalse, v1.ConditionFalse},
|
||||
podPhase: []v1.PodPhase{v1.PodRunning, v1.PodRunning, v1.PodRunning, v1.PodRunning, v1.PodRunning, v1.PodFailed, v1.PodFailed},
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: [][]int64{{1000, 100}, {1000, 300}, {1000, 500}, {1000, 250}, {1000, 250}}, //TODO: Test is broken
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
expectedValue: 280,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestReplicaCalcScaleDownIgnoresDeletionPods(t *testing.T) {
|
||||
tc := replicaCalcTestCase{
|
||||
currentReplicas: 5,
|
||||
@ -929,7 +1125,7 @@ func TestReplicaCalcScaleDownIgnoresDeletionPods(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250},
|
||||
levels: makePodMetricLevels(100, 300, 500, 250, 250),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
@ -950,12 +1146,13 @@ func TestReplicaCalcScaleDownIgnoresDeletionPods_StillRunning(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 300, 500, 250, 250, 0, 0},
|
||||
levels: [][]int64{{1000, 100}, {1000, 300}, {1000, 500}, {1000, 250}, {1000, 250}},
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 28,
|
||||
expectedValue: numContainersPerPod * 280,
|
||||
expectedValue: 280,
|
||||
},
|
||||
container: "container2",
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
@ -967,7 +1164,7 @@ func TestReplicaCalcTolerance(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("0.9"), resource.MustParse("1.0"), resource.MustParse("1.1")},
|
||||
levels: []int64{1010, 1030, 1020},
|
||||
levels: makePodMetricLevels(1010, 1030, 1020),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 102,
|
||||
@ -1070,7 +1267,7 @@ func TestReplicaCalcSuperfluousMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{4000, 9500, 3000, 7000, 3200, 2000},
|
||||
levels: makePodMetricLevels(4000, 9500, 3000, 7000, 3200, 2000),
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 587,
|
||||
expectedValue: numContainersPerPod * 5875,
|
||||
@ -1086,7 +1283,7 @@ func TestReplicaCalcMissingMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{400, 95},
|
||||
levels: makePodMetricLevels(400, 95),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 24,
|
||||
@ -1103,7 +1300,7 @@ func TestReplicaCalcEmptyMetrics(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{},
|
||||
levels: makePodMetricLevels(),
|
||||
|
||||
targetUtilization: 100,
|
||||
},
|
||||
@ -1118,7 +1315,7 @@ func TestReplicaCalcEmptyCPURequest(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{},
|
||||
levels: []int64{200},
|
||||
levels: makePodMetricLevels(200),
|
||||
|
||||
targetUtilization: 100,
|
||||
},
|
||||
@ -1133,7 +1330,7 @@ func TestReplicaCalcMissingMetricsNoChangeEq(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{1000},
|
||||
levels: makePodMetricLevels(1000),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 100,
|
||||
@ -1150,7 +1347,7 @@ func TestReplicaCalcMissingMetricsNoChangeGt(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{1900},
|
||||
levels: makePodMetricLevels(1900),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 190,
|
||||
@ -1167,7 +1364,7 @@ func TestReplicaCalcMissingMetricsNoChangeLt(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{600},
|
||||
levels: makePodMetricLevels(600),
|
||||
|
||||
targetUtilization: 100,
|
||||
expectedUtilization: 60,
|
||||
@ -1185,7 +1382,7 @@ func TestReplicaCalcMissingMetricsUnreadyChange(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 450},
|
||||
levels: makePodMetricLevels(100, 450),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 45,
|
||||
@ -1203,7 +1400,7 @@ func TestReplicaCalcMissingMetricsHotCpuNoChange(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 450},
|
||||
levels: makePodMetricLevels(100, 450),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 45,
|
||||
@ -1221,7 +1418,7 @@ func TestReplicaCalcMissingMetricsUnreadyScaleUp(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 2000},
|
||||
levels: makePodMetricLevels(100, 2000),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 200,
|
||||
@ -1240,7 +1437,7 @@ func TestReplicaCalcMissingMetricsHotCpuScaleUp(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 2000},
|
||||
levels: makePodMetricLevels(100, 2000),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 200,
|
||||
@ -1258,7 +1455,7 @@ func TestReplicaCalcMissingMetricsUnreadyScaleDown(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 100, 100},
|
||||
levels: makePodMetricLevels(100, 100, 100),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 10,
|
||||
@ -1276,7 +1473,7 @@ func TestReplicaCalcDuringRollingUpdateWithMaxSurge(t *testing.T) {
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
requests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
levels: []int64{100, 100},
|
||||
levels: makePodMetricLevels(100, 100),
|
||||
|
||||
targetUtilization: 50,
|
||||
expectedUtilization: 10,
|
||||
@ -1315,18 +1512,18 @@ func TestReplicaCalcComputedToleranceAlgImplementation(t *testing.T) {
|
||||
expectedReplicas: finalPods,
|
||||
resource: &resourceInfo{
|
||||
name: v1.ResourceCPU,
|
||||
levels: []int64{
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
totalUsedCPUOfAllPods / 10,
|
||||
},
|
||||
levels: makePodMetricLevels(
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
totalUsedCPUOfAllPods/10,
|
||||
),
|
||||
requests: []resource.Quantity{
|
||||
resource.MustParse(fmt.Sprint(perPodRequested+100) + "m"),
|
||||
resource.MustParse(fmt.Sprint(perPodRequested-100) + "m"),
|
||||
|
@ -642,6 +642,13 @@ const (
|
||||
//
|
||||
// Disables Accelerator Metrics Collected by Kubelet
|
||||
DisableAcceleratorUsageMetrics featuregate.Feature = "DisableAcceleratorUsageMetrics"
|
||||
|
||||
// owner: @arjunrn @mwielgus @josephburnett
|
||||
// alpha: v1.20
|
||||
//
|
||||
// Add support for the HPA to scale based on metrics from individual containers
|
||||
// in target pods
|
||||
HPAContainerMetrics featuregate.Feature = "HPAContainerMetrics"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -739,6 +746,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
WinOverlay: {Default: true, PreRelease: featuregate.Beta},
|
||||
WinDSR: {Default: false, PreRelease: featuregate.Alpha},
|
||||
DisableAcceleratorUsageMetrics: {Default: true, PreRelease: featuregate.Beta},
|
||||
HPAContainerMetrics: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
|
||||
// unintentionally on either side:
|
||||
|
@ -2042,6 +2042,25 @@ func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.Met
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s/%s", current, target))
|
||||
}
|
||||
case autoscaling.ContainerResourceMetricSourceType:
|
||||
if spec.ContainerResource.Target.AverageValue != nil {
|
||||
current := "<unknown>"
|
||||
if len(statuses) > i && statuses[i].ContainerResource != nil {
|
||||
current = statuses[i].ContainerResource.Current.AverageValue.String()
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s/%s", current, spec.ContainerResource.Target.AverageValue.String()))
|
||||
} else {
|
||||
current := "<unknown>"
|
||||
if len(statuses) > i && statuses[i].ContainerResource != nil && statuses[i].ContainerResource.Current.AverageUtilization != nil {
|
||||
current = fmt.Sprintf("%d%%", *statuses[i].ContainerResource.Current.AverageUtilization)
|
||||
}
|
||||
|
||||
target := "<auto>"
|
||||
if spec.ContainerResource.Target.AverageUtilization != nil {
|
||||
target = fmt.Sprintf("%d%%", *spec.ContainerResource.Target.AverageUtilization)
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s/%s", current, target))
|
||||
}
|
||||
default:
|
||||
list = append(list, "<unknown type>")
|
||||
}
|
||||
|
@ -2813,6 +2813,161 @@ func TestPrintHPA(t *testing.T) {
|
||||
// Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
|
||||
expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50%/80%", "2", int64(10), int64(4), "<unknown>"}}},
|
||||
},
|
||||
// container resource source type, targetVal (no current)
|
||||
{
|
||||
hpa: 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.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.AverageValueMetricType,
|
||||
AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
// Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
|
||||
expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/100m", "2", int64(10), int64(4), "<unknown>"}}},
|
||||
},
|
||||
// container resource source type, targetVal
|
||||
{
|
||||
hpa: 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.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.AverageValueMetricType,
|
||||
AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "application",
|
||||
Current: autoscaling.MetricValueStatus{
|
||||
AverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
|
||||
expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50m/100m", "2", int64(10), int64(4), "<unknown>"}}},
|
||||
},
|
||||
// container resource source type, targetUtil (no current)
|
||||
{
|
||||
hpa: 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.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "application",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
// Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
|
||||
expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "<unknown>/80%", "2", int64(10), int64(4), "<unknown>"}}},
|
||||
},
|
||||
// container resource source type, targetUtil
|
||||
{
|
||||
hpa: 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.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
Container: "application",
|
||||
Current: autoscaling.MetricValueStatus{
|
||||
AverageUtilization: ¤tUtilizationVal,
|
||||
AverageValue: resource.NewMilliQuantity(40, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Columns: Name, Reference, Targets, MinPods, MaxPods, Replicas, Age
|
||||
expected: []metav1.TableRow{{Cells: []interface{}{"some-hpa", "ReplicationController/some-rc", "50%/80%", "2", int64(10), int64(4), "<unknown>"}}},
|
||||
},
|
||||
// multiple specs
|
||||
{
|
||||
hpa: autoscaling.HorizontalPodAutoscaler{
|
||||
|
@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"])
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
@ -16,9 +17,11 @@ go_library(
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/autoscaling/validation:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -37,3 +40,17 @@ filegroup(
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["strategy_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -22,9 +22,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// autoscalerStrategy implements behavior for HorizontalPodAutoscalers
|
||||
@ -48,6 +50,10 @@ func (autoscalerStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obje
|
||||
|
||||
// create cannot set status
|
||||
newHPA.Status = autoscaling.HorizontalPodAutoscalerStatus{}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.HPAContainerMetrics) {
|
||||
dropContainerMetricSources(newHPA.Spec.Metrics)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates a new autoscaler.
|
||||
@ -69,10 +75,30 @@ func (autoscalerStrategy) AllowCreateOnUpdate() bool {
|
||||
func (autoscalerStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
newHPA := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
oldHPA := old.(*autoscaling.HorizontalPodAutoscaler)
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.HPAContainerMetrics) && !hasContainerMetricSources(oldHPA) {
|
||||
dropContainerMetricSources(newHPA.Spec.Metrics)
|
||||
}
|
||||
// Update is not allowed to set status
|
||||
newHPA.Status = oldHPA.Status
|
||||
}
|
||||
|
||||
// dropContainerMetricSources ensures all container resource metric sources are nil
|
||||
func dropContainerMetricSources(metrics []autoscaling.MetricSpec) {
|
||||
for i := range metrics {
|
||||
metrics[i].ContainerResource = nil
|
||||
}
|
||||
}
|
||||
|
||||
// hasContainerMetricSources returns true if the hpa has any container resource metric sources
|
||||
func hasContainerMetricSources(hpa *autoscaling.HorizontalPodAutoscaler) bool {
|
||||
for i := range hpa.Spec.Metrics {
|
||||
if hpa.Spec.Metrics[i].ContainerResource != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (autoscalerStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return validation.ValidateHorizontalPodAutoscalerUpdate(obj.(*autoscaling.HorizontalPodAutoscaler), old.(*autoscaling.HorizontalPodAutoscaler))
|
||||
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package horizontalpodautoscaler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func makeTestContainerMetricsHPA(hasContainerMetric bool) *autoscaling.HorizontalPodAutoscaler {
|
||||
testHPA := &autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
Metrics: []autoscaling.MetricSpec{},
|
||||
},
|
||||
}
|
||||
if hasContainerMetric {
|
||||
testHPA.Spec.Metrics = append(testHPA.Spec.Metrics, autoscaling.MetricSpec{
|
||||
Type: autoscaling.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscaling.ContainerResourceMetricSource{
|
||||
Name: core.ResourceCPU,
|
||||
Container: "test-container",
|
||||
Target: autoscaling.MetricTarget{
|
||||
Type: autoscaling.UtilizationMetricType,
|
||||
AverageUtilization: pointer.Int32Ptr(30),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
return testHPA
|
||||
}
|
||||
|
||||
func TestCreateWithFeatureEnabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HPAContainerMetrics, true)()
|
||||
testHPA := makeTestContainerMetricsHPA(true)
|
||||
Strategy.PrepareForCreate(context.Background(), testHPA)
|
||||
if testHPA.Spec.Metrics[0].ContainerResource == nil {
|
||||
t.Errorf("container metrics was set to nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateWithFeatureDisabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HPAContainerMetrics, false)()
|
||||
testHPA := makeTestContainerMetricsHPA(true)
|
||||
Strategy.PrepareForCreate(context.Background(), testHPA)
|
||||
if testHPA.Spec.Metrics[0].ContainerResource != nil {
|
||||
t.Errorf("container metrics is not nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoscalerStatusStrategy_PrepareForUpdate(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
featureEnabled bool
|
||||
old bool
|
||||
expectedNew bool
|
||||
}{
|
||||
{
|
||||
name: "feature disabled with existing container metrics",
|
||||
featureEnabled: false,
|
||||
old: true,
|
||||
expectedNew: true,
|
||||
},
|
||||
{
|
||||
name: "feature enabled with no container metrics",
|
||||
featureEnabled: true,
|
||||
old: false,
|
||||
expectedNew: true,
|
||||
},
|
||||
{
|
||||
name: "feature enabled with existing container metrics",
|
||||
featureEnabled: true,
|
||||
old: true,
|
||||
expectedNew: true,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HPAContainerMetrics, tc.featureEnabled)()
|
||||
oldHPA := makeTestContainerMetricsHPA(tc.old)
|
||||
newHPA := makeTestContainerMetricsHPA(true)
|
||||
Strategy.PrepareForUpdate(context.Background(), newHPA, oldHPA)
|
||||
if tc.expectedNew && newHPA.Spec.Metrics[0].ContainerResource == nil {
|
||||
t.Errorf("container metric source is nil")
|
||||
}
|
||||
if !tc.expectedNew && newHPA.Spec.Metrics[0].ContainerResource != nil {
|
||||
t.Errorf("container metric source is not nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
905
staging/src/k8s.io/api/autoscaling/v1/generated.pb.go
generated
905
staging/src/k8s.io/api/autoscaling/v1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,60 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "v1";
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in the requests and limits, describing a single container in
|
||||
// each of the pods of the current scale target(e.g. CPU or memory). The values will be
|
||||
// averaged together before being compared to the target. Such metrics are built into
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
message ContainerResourceMetricSource {
|
||||
// name is the name of the resource in question.
|
||||
optional string name = 1;
|
||||
|
||||
// targetAverageUtilization is the target value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods.
|
||||
// +optional
|
||||
optional int32 targetAverageUtilization = 2;
|
||||
|
||||
// targetAverageValue is the target value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 3;
|
||||
|
||||
// container is the name of the container in the pods of the scaling target.
|
||||
optional string container = 5;
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
message ContainerResourceMetricStatus {
|
||||
// name is the name of the resource in question.
|
||||
optional string name = 1;
|
||||
|
||||
// currentAverageUtilization is the current value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods. It will only be
|
||||
// present if `targetAverageValue` was set in the corresponding metric
|
||||
// specification.
|
||||
// +optional
|
||||
optional int32 currentAverageUtilization = 2;
|
||||
|
||||
// currentAverageValue is the current value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// It will always be set, regardless of the corresponding metric specification.
|
||||
optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 3;
|
||||
|
||||
// container is the name of the container in the pods of the scaling taget
|
||||
optional string container = 4;
|
||||
}
|
||||
|
||||
// CrossVersionObjectReference contains enough information to let you identify the referred resource.
|
||||
message CrossVersionObjectReference {
|
||||
// Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"
|
||||
@ -184,8 +238,10 @@ message HorizontalPodAutoscalerStatus {
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
message MetricSpec {
|
||||
// type is the type of metric source. It should be one of "Object",
|
||||
// "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// type is the type of metric source. It should be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
optional string type = 1;
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -207,6 +263,15 @@ message MetricSpec {
|
||||
// +optional
|
||||
optional ResourceMetricSource resource = 4;
|
||||
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod of the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.
|
||||
// +optional
|
||||
optional ContainerResourceMetricSource containerResource = 7;
|
||||
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -218,8 +283,10 @@ message MetricSpec {
|
||||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
message MetricStatus {
|
||||
// type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// type is the type of metric source. It will be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
optional string type = 1;
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -241,6 +308,14 @@ message MetricStatus {
|
||||
// +optional
|
||||
optional ResourceMetricStatus resource = 4;
|
||||
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
optional ContainerResourceMetricStatus containerResource = 7;
|
||||
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
|
@ -165,6 +165,12 @@ const (
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ResourceMetricSourceType MetricSourceType = "Resource"
|
||||
// ContainerResourceMetricSourceType is a resource metric known to Kubernetes, as
|
||||
// specified in requests and limits, describing a single container in each pod in the current
|
||||
// scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ContainerResourceMetricSourceType MetricSourceType = "ContainerResource"
|
||||
// ExternalMetricSourceType is a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -176,8 +182,10 @@ const (
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
type MetricSpec struct {
|
||||
// type is the type of metric source. It should be one of "Object",
|
||||
// "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// type is the type of metric source. It should be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
Type MetricSourceType `json:"type" protobuf:"bytes,1,name=type"`
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -196,6 +204,14 @@ type MetricSpec struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricSource `json:"resource,omitempty" protobuf:"bytes,4,opt,name=resource"`
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod of the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricSource `json:"containerResource,omitempty" protobuf:"bytes,7,opt,name=containerResource"`
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -267,6 +283,30 @@ type ResourceMetricSource struct {
|
||||
TargetAverageValue *resource.Quantity `json:"targetAverageValue,omitempty" protobuf:"bytes,3,opt,name=targetAverageValue"`
|
||||
}
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in the requests and limits, describing a single container in
|
||||
// each of the pods of the current scale target(e.g. CPU or memory). The values will be
|
||||
// averaged together before being compared to the target. Such metrics are built into
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
type ContainerResourceMetricSource struct {
|
||||
// name is the name of the resource in question.
|
||||
Name v1.ResourceName `json:"name" protobuf:"bytes,1,name=name"`
|
||||
// targetAverageUtilization is the target value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods.
|
||||
// +optional
|
||||
TargetAverageUtilization *int32 `json:"targetAverageUtilization,omitempty" protobuf:"varint,2,opt,name=targetAverageUtilization"`
|
||||
// targetAverageValue is the target value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// +optional
|
||||
TargetAverageValue *resource.Quantity `json:"targetAverageValue,omitempty" protobuf:"bytes,3,opt,name=targetAverageValue"`
|
||||
// container is the name of the container in the pods of the scaling target.
|
||||
Container string `json:"container" protobuf:"bytes,5,opt,name=container"`
|
||||
}
|
||||
|
||||
// ExternalMetricSource indicates how to scale on a metric not associated with
|
||||
// any Kubernetes object (for example length of queue in cloud
|
||||
// messaging service, or QPS from loadbalancer running outside of cluster).
|
||||
@ -289,8 +329,10 @@ type ExternalMetricSource struct {
|
||||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
type MetricStatus struct {
|
||||
// type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// type is the type of metric source. It will be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
Type MetricSourceType `json:"type" protobuf:"bytes,1,name=type"`
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -309,6 +351,13 @@ type MetricStatus struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricStatus `json:"resource,omitempty" protobuf:"bytes,4,opt,name=resource"`
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricStatus `json:"containerResource,omitempty" protobuf:"bytes,7,opt,name=containerResource"`
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -414,6 +463,30 @@ type ResourceMetricStatus struct {
|
||||
CurrentAverageValue resource.Quantity `json:"currentAverageValue" protobuf:"bytes,3,name=currentAverageValue"`
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
type ContainerResourceMetricStatus struct {
|
||||
// name is the name of the resource in question.
|
||||
Name v1.ResourceName `json:"name" protobuf:"bytes,1,name=name"`
|
||||
// currentAverageUtilization is the current value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods. It will only be
|
||||
// present if `targetAverageValue` was set in the corresponding metric
|
||||
// specification.
|
||||
// +optional
|
||||
CurrentAverageUtilization *int32 `json:"currentAverageUtilization,omitempty" protobuf:"bytes,2,opt,name=currentAverageUtilization"`
|
||||
// currentAverageValue is the current value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// It will always be set, regardless of the corresponding metric specification.
|
||||
CurrentAverageValue resource.Quantity `json:"currentAverageValue" protobuf:"bytes,3,name=currentAverageValue"`
|
||||
// container is the name of the container in the pods of the scaling taget
|
||||
Container string `json:"container" protobuf:"bytes,4,opt,name=container"`
|
||||
}
|
||||
|
||||
// ExternalMetricStatus indicates the current value of a global metric
|
||||
// not associated with any Kubernetes object.
|
||||
type ExternalMetricStatus struct {
|
||||
|
@ -27,6 +27,30 @@ package v1
|
||||
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT.
|
||||
var map_ContainerResourceMetricSource = map[string]string{
|
||||
"": "ContainerResourceMetricSource indicates how to scale on a resource metric known to Kubernetes, as specified in the requests and limits, describing a single container in each of the pods of the current scale target(e.g. CPU or memory). The values will be averaged together before being compared to the target. Such metrics are built into Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. Only one \"target\" type should be set.",
|
||||
"name": "name is the name of the resource in question.",
|
||||
"targetAverageUtilization": "targetAverageUtilization is the target value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods.",
|
||||
"targetAverageValue": "targetAverageValue is the target value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type.",
|
||||
"container": "container is the name of the container in the pods of the scaling target.",
|
||||
}
|
||||
|
||||
func (ContainerResourceMetricSource) SwaggerDoc() map[string]string {
|
||||
return map_ContainerResourceMetricSource
|
||||
}
|
||||
|
||||
var map_ContainerResourceMetricStatus = map[string]string{
|
||||
"": "ContainerResourceMetricStatus indicates the current value of a resource metric known to Kubernetes, as specified in requests and limits, describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"name": "name is the name of the resource in question.",
|
||||
"currentAverageUtilization": "currentAverageUtilization is the current value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods. It will only be present if `targetAverageValue` was set in the corresponding metric specification.",
|
||||
"currentAverageValue": "currentAverageValue is the current value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type. It will always be set, regardless of the corresponding metric specification.",
|
||||
"container": "container is the name of the container in the pods of the scaling taget",
|
||||
}
|
||||
|
||||
func (ContainerResourceMetricStatus) SwaggerDoc() map[string]string {
|
||||
return map_ContainerResourceMetricStatus
|
||||
}
|
||||
|
||||
var map_CrossVersionObjectReference = map[string]string{
|
||||
"": "CrossVersionObjectReference contains enough information to let you identify the referred resource.",
|
||||
"kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\"",
|
||||
@ -122,12 +146,13 @@ func (HorizontalPodAutoscalerStatus) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_MetricSpec = map[string]string{
|
||||
"": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"type": "type is the type of metric source. It should be one of \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object.",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
"": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"type": "type is the type of metric source. It should be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"containerResource": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod of the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
}
|
||||
|
||||
func (MetricSpec) SwaggerDoc() map[string]string {
|
||||
@ -135,12 +160,13 @@ func (MetricSpec) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_MetricStatus = map[string]string{
|
||||
"": "MetricStatus describes the last-read state of a single metric.",
|
||||
"type": "type is the type of metric source. It will be one of \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object.",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
"": "MetricStatus describes the last-read state of a single metric.",
|
||||
"type": "type is the type of metric source. It will be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"containerResource": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
}
|
||||
|
||||
func (MetricStatus) SwaggerDoc() map[string]string {
|
||||
|
@ -25,6 +25,54 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricSource) DeepCopyInto(out *ContainerResourceMetricSource) {
|
||||
*out = *in
|
||||
if in.TargetAverageUtilization != nil {
|
||||
in, out := &in.TargetAverageUtilization, &out.TargetAverageUtilization
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.TargetAverageValue != nil {
|
||||
in, out := &in.TargetAverageValue, &out.TargetAverageValue
|
||||
x := (*in).DeepCopy()
|
||||
*out = &x
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricSource.
|
||||
func (in *ContainerResourceMetricSource) DeepCopy() *ContainerResourceMetricSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopyInto(out *ContainerResourceMetricStatus) {
|
||||
*out = *in
|
||||
if in.CurrentAverageUtilization != nil {
|
||||
in, out := &in.CurrentAverageUtilization, &out.CurrentAverageUtilization
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
out.CurrentAverageValue = in.CurrentAverageValue.DeepCopy()
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricStatus.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopy() *ContainerResourceMetricStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CrossVersionObjectReference) DeepCopyInto(out *CrossVersionObjectReference) {
|
||||
*out = *in
|
||||
@ -252,6 +300,11 @@ func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
|
||||
*out = new(ResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricSource)
|
||||
@ -288,6 +341,11 @@ func (in *MetricStatus) DeepCopyInto(out *MetricStatus) {
|
||||
*out = new(ResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricStatus)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,60 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "v2beta1";
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing each pod in the
|
||||
// current scale target (e.g. CPU or memory). The values will be averaged
|
||||
// together before being compared to the target. Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
message ContainerResourceMetricSource {
|
||||
// name is the name of the resource in question.
|
||||
optional string name = 1;
|
||||
|
||||
// targetAverageUtilization is the target value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods.
|
||||
// +optional
|
||||
optional int32 targetAverageUtilization = 2;
|
||||
|
||||
// targetAverageValue is the target value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 3;
|
||||
|
||||
// container is the name of the container in the pods of the scaling target
|
||||
optional string container = 4;
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
message ContainerResourceMetricStatus {
|
||||
// name is the name of the resource in question.
|
||||
optional string name = 1;
|
||||
|
||||
// currentAverageUtilization is the current value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods. It will only be
|
||||
// present if `targetAverageValue` was set in the corresponding metric
|
||||
// specification.
|
||||
// +optional
|
||||
optional int32 currentAverageUtilization = 2;
|
||||
|
||||
// currentAverageValue is the current value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// It will always be set, regardless of the corresponding metric specification.
|
||||
optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 3;
|
||||
|
||||
// container is the name of the container in the pods of the scaling target
|
||||
optional string container = 4;
|
||||
}
|
||||
|
||||
// CrossVersionObjectReference contains enough information to let you identify the referred resource.
|
||||
message CrossVersionObjectReference {
|
||||
// Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"
|
||||
@ -200,8 +254,10 @@ message HorizontalPodAutoscalerStatus {
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
message MetricSpec {
|
||||
// type is the type of metric source. It should be one of "Object",
|
||||
// "Pods", "Resource" or "External", each mapping to a matching field in the object.
|
||||
// type is the type of metric source. It should be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
optional string type = 1;
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -223,6 +279,15 @@ message MetricSpec {
|
||||
// +optional
|
||||
optional ResourceMetricSource resource = 4;
|
||||
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in
|
||||
// each pod of the current scale target (e.g. CPU or memory). Such metrics are
|
||||
// built in to Kubernetes, and have special scaling options on top of those
|
||||
// available to normal per-pod metrics using the "pods" source.
|
||||
// This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.
|
||||
// +optional
|
||||
optional ContainerResourceMetricSource containerResource = 7;
|
||||
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -234,8 +299,10 @@ message MetricSpec {
|
||||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
message MetricStatus {
|
||||
// type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// type is the type of metric source. It will be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
optional string type = 1;
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -257,6 +324,14 @@ message MetricStatus {
|
||||
// +optional
|
||||
optional ResourceMetricStatus resource = 4;
|
||||
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
optional ContainerResourceMetricStatus containerResource = 7;
|
||||
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
|
@ -76,6 +76,12 @@ const (
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ResourceMetricSourceType MetricSourceType = "Resource"
|
||||
// ContainerResourceMetricSourceType is a resource metric known to Kubernetes, as
|
||||
// specified in requests and limits, describing a single container in each pod in the current
|
||||
// scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ContainerResourceMetricSourceType MetricSourceType = "ContainerResource"
|
||||
// ExternalMetricSourceType is a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -87,8 +93,10 @@ const (
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
type MetricSpec struct {
|
||||
// type is the type of metric source. It should be one of "Object",
|
||||
// "Pods", "Resource" or "External", each mapping to a matching field in the object.
|
||||
// type is the type of metric source. It should be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
Type MetricSourceType `json:"type" protobuf:"bytes,1,name=type"`
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -107,6 +115,14 @@ type MetricSpec struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricSource `json:"resource,omitempty" protobuf:"bytes,4,opt,name=resource"`
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in
|
||||
// each pod of the current scale target (e.g. CPU or memory). Such metrics are
|
||||
// built in to Kubernetes, and have special scaling options on top of those
|
||||
// available to normal per-pod metrics using the "pods" source.
|
||||
// This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricSource `json:"containerResource,omitempty" protobuf:"bytes,7,opt,name=containerResource"`
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -178,6 +194,30 @@ type ResourceMetricSource struct {
|
||||
TargetAverageValue *resource.Quantity `json:"targetAverageValue,omitempty" protobuf:"bytes,3,opt,name=targetAverageValue"`
|
||||
}
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing each pod in the
|
||||
// current scale target (e.g. CPU or memory). The values will be averaged
|
||||
// together before being compared to the target. Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
type ContainerResourceMetricSource struct {
|
||||
// name is the name of the resource in question.
|
||||
Name v1.ResourceName `json:"name" protobuf:"bytes,1,name=name"`
|
||||
// targetAverageUtilization is the target value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods.
|
||||
// +optional
|
||||
TargetAverageUtilization *int32 `json:"targetAverageUtilization,omitempty" protobuf:"varint,2,opt,name=targetAverageUtilization"`
|
||||
// targetAverageValue is the target value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// +optional
|
||||
TargetAverageValue *resource.Quantity `json:"targetAverageValue,omitempty" protobuf:"bytes,3,opt,name=targetAverageValue"`
|
||||
// container is the name of the container in the pods of the scaling target
|
||||
Container string `json:"container" protobuf:"bytes,4,opt,name=container"`
|
||||
}
|
||||
|
||||
// ExternalMetricSource indicates how to scale on a metric not associated with
|
||||
// any Kubernetes object (for example length of queue in cloud
|
||||
// messaging service, or QPS from loadbalancer running outside of cluster).
|
||||
@ -265,8 +305,10 @@ type HorizontalPodAutoscalerCondition struct {
|
||||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
type MetricStatus struct {
|
||||
// type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// type is the type of metric source. It will be one of "ContainerResource",
|
||||
// "External", "Object", "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
Type MetricSourceType `json:"type" protobuf:"bytes,1,name=type"`
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -285,6 +327,13 @@ type MetricStatus struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricStatus `json:"resource,omitempty" protobuf:"bytes,4,opt,name=resource"`
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricStatus `json:"containerResource,omitempty" protobuf:"bytes,7,opt,name=containerResource"`
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -354,6 +403,30 @@ type ResourceMetricStatus struct {
|
||||
CurrentAverageValue resource.Quantity `json:"currentAverageValue" protobuf:"bytes,3,name=currentAverageValue"`
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
type ContainerResourceMetricStatus struct {
|
||||
// name is the name of the resource in question.
|
||||
Name v1.ResourceName `json:"name" protobuf:"bytes,1,name=name"`
|
||||
// currentAverageUtilization is the current value of the average of the
|
||||
// resource metric across all relevant pods, represented as a percentage of
|
||||
// the requested value of the resource for the pods. It will only be
|
||||
// present if `targetAverageValue` was set in the corresponding metric
|
||||
// specification.
|
||||
// +optional
|
||||
CurrentAverageUtilization *int32 `json:"currentAverageUtilization,omitempty" protobuf:"bytes,2,opt,name=currentAverageUtilization"`
|
||||
// currentAverageValue is the current value of the average of the
|
||||
// resource metric across all relevant pods, as a raw value (instead of as
|
||||
// a percentage of the request), similar to the "pods" metric source type.
|
||||
// It will always be set, regardless of the corresponding metric specification.
|
||||
CurrentAverageValue resource.Quantity `json:"currentAverageValue" protobuf:"bytes,3,name=currentAverageValue"`
|
||||
// container is the name of the container in the pods of the scaling target
|
||||
Container string `json:"container" protobuf:"bytes,4,opt,name=container"`
|
||||
}
|
||||
|
||||
// ExternalMetricStatus indicates the current value of a global metric
|
||||
// not associated with any Kubernetes object.
|
||||
type ExternalMetricStatus struct {
|
||||
|
@ -27,6 +27,30 @@ package v2beta1
|
||||
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT.
|
||||
var map_ContainerResourceMetricSource = map[string]string{
|
||||
"": "ContainerResourceMetricSource indicates how to scale on a resource metric known to Kubernetes, as specified in requests and limits, describing each pod in the current scale target (e.g. CPU or memory). The values will be averaged together before being compared to the target. Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. Only one \"target\" type should be set.",
|
||||
"name": "name is the name of the resource in question.",
|
||||
"targetAverageUtilization": "targetAverageUtilization is the target value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods.",
|
||||
"targetAverageValue": "targetAverageValue is the target value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type.",
|
||||
"container": "container is the name of the container in the pods of the scaling target",
|
||||
}
|
||||
|
||||
func (ContainerResourceMetricSource) SwaggerDoc() map[string]string {
|
||||
return map_ContainerResourceMetricSource
|
||||
}
|
||||
|
||||
var map_ContainerResourceMetricStatus = map[string]string{
|
||||
"": "ContainerResourceMetricStatus indicates the current value of a resource metric known to Kubernetes, as specified in requests and limits, describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"name": "name is the name of the resource in question.",
|
||||
"currentAverageUtilization": "currentAverageUtilization is the current value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods. It will only be present if `targetAverageValue` was set in the corresponding metric specification.",
|
||||
"currentAverageValue": "currentAverageValue is the current value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type. It will always be set, regardless of the corresponding metric specification.",
|
||||
"container": "container is the name of the container in the pods of the scaling target",
|
||||
}
|
||||
|
||||
func (ContainerResourceMetricStatus) SwaggerDoc() map[string]string {
|
||||
return map_ContainerResourceMetricStatus
|
||||
}
|
||||
|
||||
var map_CrossVersionObjectReference = map[string]string{
|
||||
"": "CrossVersionObjectReference contains enough information to let you identify the referred resource.",
|
||||
"kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\"",
|
||||
@ -123,12 +147,13 @@ func (HorizontalPodAutoscalerStatus) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_MetricSpec = map[string]string{
|
||||
"": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"type": "type is the type of metric source. It should be one of \"Object\", \"Pods\", \"Resource\" or \"External\", each mapping to a matching field in the object.",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
"": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"type": "type is the type of metric source. It should be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"containerResource": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod of the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
}
|
||||
|
||||
func (MetricSpec) SwaggerDoc() map[string]string {
|
||||
@ -136,12 +161,13 @@ func (MetricSpec) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_MetricStatus = map[string]string{
|
||||
"": "MetricStatus describes the last-read state of a single metric.",
|
||||
"type": "type is the type of metric source. It will be one of \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object.",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
"": "MetricStatus describes the last-read state of a single metric.",
|
||||
"type": "type is the type of metric source. It will be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"containerResource": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
}
|
||||
|
||||
func (MetricStatus) SwaggerDoc() map[string]string {
|
||||
|
@ -25,6 +25,54 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricSource) DeepCopyInto(out *ContainerResourceMetricSource) {
|
||||
*out = *in
|
||||
if in.TargetAverageUtilization != nil {
|
||||
in, out := &in.TargetAverageUtilization, &out.TargetAverageUtilization
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.TargetAverageValue != nil {
|
||||
in, out := &in.TargetAverageValue, &out.TargetAverageValue
|
||||
x := (*in).DeepCopy()
|
||||
*out = &x
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricSource.
|
||||
func (in *ContainerResourceMetricSource) DeepCopy() *ContainerResourceMetricSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopyInto(out *ContainerResourceMetricStatus) {
|
||||
*out = *in
|
||||
if in.CurrentAverageUtilization != nil {
|
||||
in, out := &in.CurrentAverageUtilization, &out.CurrentAverageUtilization
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
out.CurrentAverageValue = in.CurrentAverageValue.DeepCopy()
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricStatus.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopy() *ContainerResourceMetricStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CrossVersionObjectReference) DeepCopyInto(out *CrossVersionObjectReference) {
|
||||
*out = *in
|
||||
@ -263,6 +311,11 @@ func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
|
||||
*out = new(ResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricSource)
|
||||
@ -299,6 +352,11 @@ func (in *MetricStatus) DeepCopyInto(out *MetricStatus) {
|
||||
*out = new(ResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricStatus)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,40 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "v2beta2";
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing each pod in the
|
||||
// current scale target (e.g. CPU or memory). The values will be averaged
|
||||
// together before being compared to the target. Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
message ContainerResourceMetricSource {
|
||||
// name is the name of the resource in question.
|
||||
optional string name = 1;
|
||||
|
||||
// target specifies the target value for the given metric
|
||||
optional MetricTarget target = 2;
|
||||
|
||||
// container is the name of the container in the pods of the scaling target
|
||||
optional string container = 3;
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
message ContainerResourceMetricStatus {
|
||||
// Name is the name of the resource in question.
|
||||
optional string name = 1;
|
||||
|
||||
// current contains the current value for the given metric
|
||||
optional MetricValueStatus current = 2;
|
||||
|
||||
// Container is the name of the container in the pods of the scaling target
|
||||
optional string container = 3;
|
||||
}
|
||||
|
||||
// CrossVersionObjectReference contains enough information to let you identify the referred resource.
|
||||
message CrossVersionObjectReference {
|
||||
// Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"
|
||||
@ -256,8 +290,10 @@ message MetricIdentifier {
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
message MetricSpec {
|
||||
// type is the type of metric source. It should be one of "Object",
|
||||
// "Pods", "Resource" or "External", each mapping to a matching field in the object.
|
||||
// type is the type of metric source. It should be one of "ContainerResource", "External",
|
||||
// "Object", "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
optional string type = 1;
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -279,6 +315,15 @@ message MetricSpec {
|
||||
// +optional
|
||||
optional ResourceMetricSource resource = 4;
|
||||
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in
|
||||
// each pod of the current scale target (e.g. CPU or memory). Such metrics are
|
||||
// built in to Kubernetes, and have special scaling options on top of those
|
||||
// available to normal per-pod metrics using the "pods" source.
|
||||
// This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.
|
||||
// +optional
|
||||
optional ContainerResourceMetricSource containerResource = 7;
|
||||
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -290,8 +335,10 @@ message MetricSpec {
|
||||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
message MetricStatus {
|
||||
// type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// type is the type of metric source. It will be one of "ContainerResource", "External",
|
||||
// "Object", "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
optional string type = 1;
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -313,6 +360,14 @@ message MetricStatus {
|
||||
// +optional
|
||||
optional ResourceMetricStatus resource = 4;
|
||||
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
optional ContainerResourceMetricStatus containerResource = 7;
|
||||
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
|
@ -96,8 +96,10 @@ type CrossVersionObjectReference struct {
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
type MetricSpec struct {
|
||||
// type is the type of metric source. It should be one of "Object",
|
||||
// "Pods", "Resource" or "External", each mapping to a matching field in the object.
|
||||
// type is the type of metric source. It should be one of "ContainerResource", "External",
|
||||
// "Object", "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
Type MetricSourceType `json:"type" protobuf:"bytes,1,name=type"`
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -116,6 +118,14 @@ type MetricSpec struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricSource `json:"resource,omitempty" protobuf:"bytes,4,opt,name=resource"`
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in
|
||||
// each pod of the current scale target (e.g. CPU or memory). Such metrics are
|
||||
// built in to Kubernetes, and have special scaling options on top of those
|
||||
// available to normal per-pod metrics using the "pods" source.
|
||||
// This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricSource `json:"containerResource,omitempty" protobuf:"bytes,7,opt,name=containerResource"`
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -220,6 +230,12 @@ const (
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ResourceMetricSourceType MetricSourceType = "Resource"
|
||||
// ContainerResourceMetricSourceType is a resource metric known to Kubernetes, as
|
||||
// specified in requests and limits, describing a single container in each pod in the current
|
||||
// scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ContainerResourceMetricSourceType MetricSourceType = "ContainerResource"
|
||||
// ExternalMetricSourceType is a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -263,6 +279,22 @@ type ResourceMetricSource struct {
|
||||
Target MetricTarget `json:"target" protobuf:"bytes,2,name=target"`
|
||||
}
|
||||
|
||||
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing each pod in the
|
||||
// current scale target (e.g. CPU or memory). The values will be averaged
|
||||
// together before being compared to the target. Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source. Only one "target" type
|
||||
// should be set.
|
||||
type ContainerResourceMetricSource struct {
|
||||
// name is the name of the resource in question.
|
||||
Name v1.ResourceName `json:"name" protobuf:"bytes,1,name=name"`
|
||||
// target specifies the target value for the given metric
|
||||
Target MetricTarget `json:"target" protobuf:"bytes,2,name=target"`
|
||||
// container is the name of the container in the pods of the scaling target
|
||||
Container string `json:"container" protobuf:"bytes,3,opt,name=container"`
|
||||
}
|
||||
|
||||
// ExternalMetricSource indicates how to scale on a metric not associated with
|
||||
// any Kubernetes object (for example length of queue in cloud
|
||||
// messaging service, or QPS from loadbalancer running outside of cluster).
|
||||
@ -382,8 +414,10 @@ type HorizontalPodAutoscalerCondition struct {
|
||||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
type MetricStatus struct {
|
||||
// type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// type is the type of metric source. It will be one of "ContainerResource", "External",
|
||||
// "Object", "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
// Note: "ContainerResource" type is available on when the feature-gate
|
||||
// HPAContainerMetrics is enabled
|
||||
Type MetricSourceType `json:"type" protobuf:"bytes,1,name=type"`
|
||||
|
||||
// object refers to a metric describing a single kubernetes object
|
||||
@ -402,6 +436,13 @@ type MetricStatus struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricStatus `json:"resource,omitempty" protobuf:"bytes,4,opt,name=resource"`
|
||||
// container resource refers to a resource metric (such as those specified in
|
||||
// requests and limits) known to Kubernetes describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
ContainerResource *ContainerResourceMetricStatus `json:"containerResource,omitempty" protobuf:"bytes,7,opt,name=containerResource"`
|
||||
// external refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
@ -443,6 +484,20 @@ type ResourceMetricStatus struct {
|
||||
Current MetricValueStatus `json:"current" protobuf:"bytes,2,name=current"`
|
||||
}
|
||||
|
||||
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
|
||||
// Kubernetes, as specified in requests and limits, describing a single container in each pod in the
|
||||
// current scale target (e.g. CPU or memory). Such metrics are built in to
|
||||
// Kubernetes, and have special scaling options on top of those available to
|
||||
// normal per-pod metrics using the "pods" source.
|
||||
type ContainerResourceMetricStatus struct {
|
||||
// Name is the name of the resource in question.
|
||||
Name v1.ResourceName `json:"name" protobuf:"bytes,1,name=name"`
|
||||
// current contains the current value for the given metric
|
||||
Current MetricValueStatus `json:"current" protobuf:"bytes,2,name=current"`
|
||||
// Container is the name of the container in the pods of the scaling target
|
||||
Container string `json:"container" protobuf:"bytes,3,opt,name=container"`
|
||||
}
|
||||
|
||||
// ExternalMetricStatus indicates the current value of a global metric
|
||||
// not associated with any Kubernetes object.
|
||||
type ExternalMetricStatus struct {
|
||||
|
@ -27,6 +27,28 @@ package v2beta2
|
||||
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT.
|
||||
var map_ContainerResourceMetricSource = map[string]string{
|
||||
"": "ContainerResourceMetricSource indicates how to scale on a resource metric known to Kubernetes, as specified in requests and limits, describing each pod in the current scale target (e.g. CPU or memory). The values will be averaged together before being compared to the target. Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. Only one \"target\" type should be set.",
|
||||
"name": "name is the name of the resource in question.",
|
||||
"target": "target specifies the target value for the given metric",
|
||||
"container": "container is the name of the container in the pods of the scaling target",
|
||||
}
|
||||
|
||||
func (ContainerResourceMetricSource) SwaggerDoc() map[string]string {
|
||||
return map_ContainerResourceMetricSource
|
||||
}
|
||||
|
||||
var map_ContainerResourceMetricStatus = map[string]string{
|
||||
"": "ContainerResourceMetricStatus indicates the current value of a resource metric known to Kubernetes, as specified in requests and limits, describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"name": "Name is the name of the resource in question.",
|
||||
"current": "current contains the current value for the given metric",
|
||||
"container": "Container is the name of the container in the pods of the scaling target",
|
||||
}
|
||||
|
||||
func (ContainerResourceMetricStatus) SwaggerDoc() map[string]string {
|
||||
return map_ContainerResourceMetricStatus
|
||||
}
|
||||
|
||||
var map_CrossVersionObjectReference = map[string]string{
|
||||
"": "CrossVersionObjectReference contains enough information to let you identify the referred resource.",
|
||||
"kind": "Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\"",
|
||||
@ -162,12 +184,13 @@ func (MetricIdentifier) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_MetricSpec = map[string]string{
|
||||
"": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"type": "type is the type of metric source. It should be one of \"Object\", \"Pods\", \"Resource\" or \"External\", each mapping to a matching field in the object.",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
"": "MetricSpec specifies how to scale based on a single metric (only `type` and one other matching field should be set at once).",
|
||||
"type": "type is the type of metric source. It should be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"containerResource": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod of the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
}
|
||||
|
||||
func (MetricSpec) SwaggerDoc() map[string]string {
|
||||
@ -175,12 +198,13 @@ func (MetricSpec) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_MetricStatus = map[string]string{
|
||||
"": "MetricStatus describes the last-read state of a single metric.",
|
||||
"type": "type is the type of metric source. It will be one of \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object.",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
"": "MetricStatus describes the last-read state of a single metric.",
|
||||
"type": "type is the type of metric source. It will be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
"object": "object refers to a metric describing a single kubernetes object (for example, hits-per-second on an Ingress object).",
|
||||
"pods": "pods refers to a metric describing each pod in the current scale target (for example, transactions-processed-per-second). The values will be averaged together before being compared to the target value.",
|
||||
"resource": "resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"containerResource": "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
"external": "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
}
|
||||
|
||||
func (MetricStatus) SwaggerDoc() map[string]string {
|
||||
|
@ -25,6 +25,40 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricSource) DeepCopyInto(out *ContainerResourceMetricSource) {
|
||||
*out = *in
|
||||
in.Target.DeepCopyInto(&out.Target)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricSource.
|
||||
func (in *ContainerResourceMetricSource) DeepCopy() *ContainerResourceMetricSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopyInto(out *ContainerResourceMetricStatus) {
|
||||
*out = *in
|
||||
in.Current.DeepCopyInto(&out.Current)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricStatus.
|
||||
func (in *ContainerResourceMetricStatus) DeepCopy() *ContainerResourceMetricStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerResourceMetricStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CrossVersionObjectReference) DeepCopyInto(out *CrossVersionObjectReference) {
|
||||
*out = *in
|
||||
@ -340,6 +374,11 @@ func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
|
||||
*out = new(ResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricSource)
|
||||
@ -376,6 +415,11 @@ func (in *MetricStatus) DeepCopyInto(out *MetricStatus) {
|
||||
*out = new(ResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ContainerResource != nil {
|
||||
in, out := &in.ContainerResource, &out.ContainerResource
|
||||
*out = new(ContainerResourceMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
*out = new(ExternalMetricStatus)
|
||||
|
@ -98,98 +98,122 @@
|
||||
"targetAverageUtilization": 1253093074,
|
||||
"targetAverageValue": "8"
|
||||
},
|
||||
"containerResource": {
|
||||
"name": "w垁鷌辪虽U珝Żwʮ馜üNșƶ4ĩ",
|
||||
"targetAverageUtilization": 1463207240,
|
||||
"targetAverageValue": "84",
|
||||
"container": "39"
|
||||
},
|
||||
"external": {
|
||||
"metricName": "39",
|
||||
"metricName": "40",
|
||||
"metricSelector": {
|
||||
"matchLabels": {
|
||||
"4kh6oqu-or---40--87-1wpl6-2-310e5hz/B._z": "G6t-2.-_-8w6"
|
||||
"bigm-h8-3q768km-0--03-t-0-035--5b95w------4-n4f-h/u-5.-Z3P__D__6t-2.-_-8wE._._3.-.83_iq_-1": "1-_Y33--.8U.-.5--_zm-.-_RJt2pX_2_28.-.7_8B.HF-U-_ik_--DSX0"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "1295at-o7qff7-x--r7v66bm71u-n4f9wk-3--652x01--p--n4-4-t--2gk-0/d.83_iq_-y.-25C.A-j..9dfn3Y8d_0_.---M_4FpF_W-1._-vL_i.-_-a--GI",
|
||||
"operator": "DoesNotExist"
|
||||
"key": "680---z-6-t2z-w-fg98-r--v53nyx5u-o-k-md--381d-7.3di292f--90-17-hg1-o-p665--4-j8---t6-r7r/Y-H-Mqpt._.-_..05c.---qy-_5_S.d5a37",
|
||||
"operator": "NotIn",
|
||||
"values": [
|
||||
"dY_um-_8r--684._-_18_...E.-2o_-.5"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"targetValue": "570",
|
||||
"targetAverageValue": "829"
|
||||
"targetValue": "865",
|
||||
"targetAverageValue": "379"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"observedGeneration": -7224326297454280417,
|
||||
"currentReplicas": 596942561,
|
||||
"desiredReplicas": -1880980172,
|
||||
"observedGeneration": 61436896663269868,
|
||||
"currentReplicas": -1462219068,
|
||||
"desiredReplicas": -370386363,
|
||||
"currentMetrics": [
|
||||
{
|
||||
"type": " ïì«丯Ƙ枛牐ɺ皚|懥",
|
||||
"type": "",
|
||||
"object": {
|
||||
"target": {
|
||||
"kind": "46",
|
||||
"name": "47",
|
||||
"apiVersion": "48"
|
||||
"kind": "47",
|
||||
"name": "48",
|
||||
"apiVersion": "49"
|
||||
},
|
||||
"metricName": "49",
|
||||
"currentValue": "55",
|
||||
"metricName": "50",
|
||||
"currentValue": "856",
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"8._Wxpe..J7rs6.0_OHz_.B-.-_w_--.8_r_N-.3n-xu": "o_-Nm-_X8"
|
||||
"vL7": "L_0N_N.O30-_u._-2hT.-z-._7-5lL..-_--.VEa-_gn.8-c.C3_F._oX-FT"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "665--4-j8---t6-r7--9.9dy/XvSA..1",
|
||||
"operator": "Exists"
|
||||
"key": "4_.-N_g-.._5",
|
||||
"operator": "In",
|
||||
"values": [
|
||||
"2qz.W..4....-h._.GgT7_7B_D-..-.k4u-zA_--_.-.6GA26C-s.Nj-d-4_t"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"averageValue": "14"
|
||||
"averageValue": "817"
|
||||
},
|
||||
"pods": {
|
||||
"metricName": "56",
|
||||
"currentAverageValue": "878",
|
||||
"metricName": "57",
|
||||
"currentAverageValue": "400",
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"6fv--m-8--72-bca4m56au3f-j/0-_1-F.h-__k_K5._..O_.J_-G_--V-42E_--o90G_A4..-L..-__0N_N.O3i": "r_gn.8-c.C3_F._oX-F9_.v"
|
||||
"mj_9.M.134-5-.q6H_.--_---.M.U_-m.-P.yP9S--858LI__.8U": "KrO-S-P_-...0c.-.p_3_J_SA995IKCR.s--f.-f.-zv._._.5-HT"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "g-..__._____K_g1cXfr.4_.B",
|
||||
"operator": "DoesNotExist"
|
||||
"key": "26-k8-c2---2etfh41ca-z-5g2wco280.ka-6-31g--z-o-3bz6-8-0-1-z--271s-p9-8--m-cbck561-7n/VC..7o_x3..-.8J",
|
||||
"operator": "NotIn",
|
||||
"values": [
|
||||
"8._Q.6.I--2_9.v.--_.--4QQ.-s.H.Hf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"resource": {
|
||||
"name": "šeSvEȤƏ埮pɵ{WOŭW灬pȭ",
|
||||
"currentAverageUtilization": -1607821167,
|
||||
"currentAverageValue": "832"
|
||||
"name": "ƻ遲njlȘ鹾KƂʼnç",
|
||||
"currentAverageUtilization": 769521729,
|
||||
"currentAverageValue": "727"
|
||||
},
|
||||
"containerResource": {
|
||||
"name": "!@@)Zq=",
|
||||
"currentAverageUtilization": -861915578,
|
||||
"currentAverageValue": "111",
|
||||
"container": "64"
|
||||
},
|
||||
"external": {
|
||||
"metricName": "63",
|
||||
"metricName": "65",
|
||||
"metricSelector": {
|
||||
"matchLabels": {
|
||||
"4_4--.-_Z4.LA3HVG93_._.I3.__-.0-z_z0sn_.hx_-a__0-8-.M-.-.-8vJ": "zET_..3dCv3j._.-_pP__up.2L_s-o779._-k-5___-Qq4"
|
||||
"2y3-4-3/AO": "r..6W.V0"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "FC-rtSY.g._2F7.-_e..OP",
|
||||
"operator": "Exists"
|
||||
"key": "v55039780bdw0-1-47rrw8-7/U_--56-.7D.3_KPg___Kp",
|
||||
"operator": "In",
|
||||
"values": [
|
||||
"N7_-Zp_._w"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"currentValue": "229",
|
||||
"currentAverageValue": "606"
|
||||
"currentValue": "200",
|
||||
"currentAverageValue": "288"
|
||||
}
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"type": "鯶縆",
|
||||
"status": "aTGÒ鵌Ē3",
|
||||
"lastTransitionTime": "2416-12-01T11:47:49Z",
|
||||
"reason": "70",
|
||||
"message": "71"
|
||||
"type": "",
|
||||
"status": "",
|
||||
"lastTransitionTime": "1995-10-31T09:59:43Z",
|
||||
"reason": "72",
|
||||
"message": "73"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Binary file not shown.
@ -32,16 +32,23 @@ metadata:
|
||||
spec:
|
||||
maxReplicas: -1971381490
|
||||
metrics:
|
||||
- external:
|
||||
metricName: "39"
|
||||
- containerResource:
|
||||
container: "39"
|
||||
name: w垁鷌辪虽U珝Żwʮ馜üNșƶ4ĩ
|
||||
targetAverageUtilization: 1463207240
|
||||
targetAverageValue: "84"
|
||||
external:
|
||||
metricName: "40"
|
||||
metricSelector:
|
||||
matchExpressions:
|
||||
- key: 1295at-o7qff7-x--r7v66bm71u-n4f9wk-3--652x01--p--n4-4-t--2gk-0/d.83_iq_-y.-25C.A-j..9dfn3Y8d_0_.---M_4FpF_W-1._-vL_i.-_-a--GI
|
||||
operator: DoesNotExist
|
||||
- key: 680---z-6-t2z-w-fg98-r--v53nyx5u-o-k-md--381d-7.3di292f--90-17-hg1-o-p665--4-j8---t6-r7r/Y-H-Mqpt._.-_..05c.---qy-_5_S.d5a37
|
||||
operator: NotIn
|
||||
values:
|
||||
- dY_um-_8r--684._-_18_...E.-2o_-.5
|
||||
matchLabels:
|
||||
4kh6oqu-or---40--87-1wpl6-2-310e5hz/B._z: G6t-2.-_-8w6
|
||||
targetAverageValue: "829"
|
||||
targetValue: "570"
|
||||
bigm-h8-3q768km-0--03-t-0-035--5b95w------4-n4f-h/u-5.-Z3P__D__6t-2.-_-8wE._._3.-.83_iq_-1: 1-_Y33--.8U.-.5--_zm-.-_RJt2pX_2_28.-.7_8B.HF-U-_ik_--DSX0
|
||||
targetAverageValue: "379"
|
||||
targetValue: "865"
|
||||
object:
|
||||
averageValue: "954"
|
||||
metricName: "25"
|
||||
@ -82,50 +89,61 @@ spec:
|
||||
name: "20"
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2416-12-01T11:47:49Z"
|
||||
message: "71"
|
||||
reason: "70"
|
||||
status: aTGÒ鵌Ē3
|
||||
type: 鯶縆
|
||||
- lastTransitionTime: "1995-10-31T09:59:43Z"
|
||||
message: "73"
|
||||
reason: "72"
|
||||
status: ""
|
||||
type: ""
|
||||
currentMetrics:
|
||||
- external:
|
||||
currentAverageValue: "606"
|
||||
currentValue: "229"
|
||||
metricName: "63"
|
||||
- containerResource:
|
||||
container: "64"
|
||||
currentAverageUtilization: -861915578
|
||||
currentAverageValue: "111"
|
||||
name: '!@@)Zq='
|
||||
external:
|
||||
currentAverageValue: "288"
|
||||
currentValue: "200"
|
||||
metricName: "65"
|
||||
metricSelector:
|
||||
matchExpressions:
|
||||
- key: FC-rtSY.g._2F7.-_e..OP
|
||||
operator: Exists
|
||||
- key: v55039780bdw0-1-47rrw8-7/U_--56-.7D.3_KPg___Kp
|
||||
operator: In
|
||||
values:
|
||||
- N7_-Zp_._w
|
||||
matchLabels:
|
||||
4_4--.-_Z4.LA3HVG93_._.I3.__-.0-z_z0sn_.hx_-a__0-8-.M-.-.-8vJ: zET_..3dCv3j._.-_pP__up.2L_s-o779._-k-5___-Qq4
|
||||
2y3-4-3/AO: r..6W.V0
|
||||
object:
|
||||
averageValue: "14"
|
||||
currentValue: "55"
|
||||
metricName: "49"
|
||||
averageValue: "817"
|
||||
currentValue: "856"
|
||||
metricName: "50"
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: 665--4-j8---t6-r7--9.9dy/XvSA..1
|
||||
operator: Exists
|
||||
- key: 4_.-N_g-.._5
|
||||
operator: In
|
||||
values:
|
||||
- 2qz.W..4....-h._.GgT7_7B_D-..-.k4u-zA_--_.-.6GA26C-s.Nj-d-4_t
|
||||
matchLabels:
|
||||
8._Wxpe..J7rs6.0_OHz_.B-.-_w_--.8_r_N-.3n-xu: o_-Nm-_X8
|
||||
vL7: L_0N_N.O30-_u._-2hT.-z-._7-5lL..-_--.VEa-_gn.8-c.C3_F._oX-FT
|
||||
target:
|
||||
apiVersion: "48"
|
||||
kind: "46"
|
||||
name: "47"
|
||||
apiVersion: "49"
|
||||
kind: "47"
|
||||
name: "48"
|
||||
pods:
|
||||
currentAverageValue: "878"
|
||||
metricName: "56"
|
||||
currentAverageValue: "400"
|
||||
metricName: "57"
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: g-..__._____K_g1cXfr.4_.B
|
||||
operator: DoesNotExist
|
||||
- key: 26-k8-c2---2etfh41ca-z-5g2wco280.ka-6-31g--z-o-3bz6-8-0-1-z--271s-p9-8--m-cbck561-7n/VC..7o_x3..-.8J
|
||||
operator: NotIn
|
||||
values:
|
||||
- 8._Q.6.I--2_9.v.--_.--4QQ.-s.H.Hf
|
||||
matchLabels:
|
||||
6fv--m-8--72-bca4m56au3f-j/0-_1-F.h-__k_K5._..O_.J_-G_--V-42E_--o90G_A4..-L..-__0N_N.O3i: r_gn.8-c.C3_F._oX-F9_.v
|
||||
mj_9.M.134-5-.q6H_.--_---.M.U_-m.-P.yP9S--858LI__.8U: KrO-S-P_-...0c.-.p_3_J_SA995IKCR.s--f.-f.-zv._._.5-HT
|
||||
resource:
|
||||
currentAverageUtilization: -1607821167
|
||||
currentAverageValue: "832"
|
||||
name: šeSvEȤƏ埮pɵ{WOŭW灬pȭ
|
||||
type: ' ïì«丯Ƙ枛牐ɺ皚|懥'
|
||||
currentReplicas: 596942561
|
||||
desiredReplicas: -1880980172
|
||||
observedGeneration: -7224326297454280417
|
||||
currentAverageUtilization: 769521729
|
||||
currentAverageValue: "727"
|
||||
name: ƻ遲njlȘ鹾KƂʼnç
|
||||
type: ""
|
||||
currentReplicas: -1462219068
|
||||
desiredReplicas: -370386363
|
||||
observedGeneration: 61436896663269868
|
||||
|
@ -112,159 +112,169 @@
|
||||
"averageUtilization": 580681683
|
||||
}
|
||||
},
|
||||
"containerResource": {
|
||||
"name": "Ɋł/擇ɦĽ胚O醔ɍ厶耈 ",
|
||||
"target": {
|
||||
"type": "禒Ƙá腿ħ缶.蒅",
|
||||
"value": "999",
|
||||
"averageValue": "151",
|
||||
"averageUtilization": -1105572246
|
||||
},
|
||||
"container": "39"
|
||||
},
|
||||
"external": {
|
||||
"metric": {
|
||||
"name": "39",
|
||||
"name": "40",
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"9s-m---vl80.5-6y-07b-3---g-jdi/z_-tY-R6S17_.8CnK_O.d-._NwcGnP-w-Sf5_Or.i1_7z.WH-.._d": "1_57__JR.N-1zL-4--6o--Bo-F__..XR.7_1-l"
|
||||
"wcGnP-w-Sf5_O1": "1_70"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "n3-8d-0-5qty--4-p---u16-wv-i.84-n4f--139-295at-o7qff7-x--r7v66bm71u-n4f0/2_31.-.-yz-0-_p4mz--.I_f6kjsz-7lwY-Y93-x6bigm_-._q",
|
||||
"operator": "In",
|
||||
"values": [
|
||||
"Q3_Y.5.-..P_pDZ-._._t__2k"
|
||||
]
|
||||
"key": "1-1-x1z-j4kh6oqu-or---40--87-1wp6.759s-3------6tv27r-m8w-6-9-35d383-iq-ay1z25-3-vj73d/Y.t--_0..--_6yV07-_.___gO-d.iUaCw",
|
||||
"operator": "DoesNotExist"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"type": "3.v-鿧悮坮Ȣ",
|
||||
"value": "82",
|
||||
"averageValue": "301",
|
||||
"averageUtilization": -521487971
|
||||
"type": "ʣy豎@ɀ羭,铻OŤ",
|
||||
"value": "830",
|
||||
"averageValue": "799",
|
||||
"averageUtilization": 747521320
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"behavior": {
|
||||
"scaleUp": {
|
||||
"stabilizationWindowSeconds": 1761963371,
|
||||
"selectPolicy": "0矀Kʝ瘴I\\p[ħsĨɆâĺɗŹ倗S",
|
||||
"stabilizationWindowSeconds": -648954478,
|
||||
"selectPolicy": "Ƿ裚瓶釆Ɗ+j忊",
|
||||
"policies": [
|
||||
{
|
||||
"type": "嶗U",
|
||||
"value": -1285424066,
|
||||
"periodSeconds": -686523310
|
||||
"type": "ȫ焗捏ĨFħ籘Àǒɿʒ刽",
|
||||
"value": 427196286,
|
||||
"periodSeconds": 1048864116
|
||||
}
|
||||
]
|
||||
},
|
||||
"scaleDown": {
|
||||
"stabilizationWindowSeconds": 1206365825,
|
||||
"selectPolicy": "/ɸɎ R§耶FfBls3!",
|
||||
"stabilizationWindowSeconds": -342705708,
|
||||
"selectPolicy": "褎weLJèux",
|
||||
"policies": [
|
||||
{
|
||||
"type": "ɾģ毋Ó6dz娝嘚",
|
||||
"value": 627713162,
|
||||
"periodSeconds": 1255312175
|
||||
"type": "VƋZ1Ůđ眊ľǎɳ,ǿ飏",
|
||||
"value": 2040455355,
|
||||
"periodSeconds": 1505972335
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"observedGeneration": -7477362499801752548,
|
||||
"currentReplicas": 267768240,
|
||||
"desiredReplicas": -127849333,
|
||||
"observedGeneration": -115578794491385044,
|
||||
"currentReplicas": 474119379,
|
||||
"desiredReplicas": 1923334396,
|
||||
"currentMetrics": [
|
||||
{
|
||||
"type": "Ǖɳɷ9Ì崟¿瘦ɖ緕",
|
||||
"type": "0Ƹ[Ęİ榌U",
|
||||
"object": {
|
||||
"metric": {
|
||||
"name": "46",
|
||||
"name": "47",
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"29.-_Z.0_1._hg._o_p665O_4Gj._BXt.O-7___-Y_um-_8r--684._V": "8_...E.-o"
|
||||
"hA9..9__Y-H-Mqpt._.-_..05c.---qy-_5_S.d5a3Jb": "46g_4....1..jtFe8b_A_..P1s-V.9.4..9..c_uo3Pa__n-Di"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "6-d42--clo90---461v-07r--0---8-30i-uo/9DF",
|
||||
"operator": "In",
|
||||
"key": "Dp665O_4Gj._BXt.O-7___-Y_um-_8r--684._-_188",
|
||||
"operator": "NotIn",
|
||||
"values": [
|
||||
"2hT.-z-._7-5lL..-_--.VEa-_gn.8-c.C3_F._oX-F9_.5vN5.25aWx.a"
|
||||
"XK5._..O_.J_-G_--V-42E_--o90G_A4..-L..-__0N_N.O30-_u._-2T"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"current": {
|
||||
"value": "526",
|
||||
"averageValue": "860",
|
||||
"averageUtilization": -126958936
|
||||
"value": "124",
|
||||
"averageValue": "472",
|
||||
"averageUtilization": -1666319281
|
||||
},
|
||||
"describedObject": {
|
||||
"kind": "53",
|
||||
"name": "54",
|
||||
"apiVersion": "55"
|
||||
"kind": "54",
|
||||
"name": "55",
|
||||
"apiVersion": "56"
|
||||
}
|
||||
},
|
||||
"pods": {
|
||||
"metric": {
|
||||
"name": "56",
|
||||
"name": "57",
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"d5-g-7-7---g88w2k4usz--mj-8o26--26-hs5-jeds4-4tz9x-4.i-l11q5--uk5mj-94-8134i5k6q6--5tu-tie4-7--gm4p-8y-99/N_g-..__._____K_g1cXfr4": "ET_..3dCv3j._.-_pP__up.2L_s-o779._-k-N"
|
||||
"5.-_--.VEa-_gn.8-c.3": "F._oX-F9_.5vN5.25aWx.2aM214_.-C"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "382m88w-pz9d4i-m7---k8235--8--c83-4b-9-1k.1f-53-x1y-8---3----p-pdn--j2---2--82--cj-1-s--op3w/3--Z1Tvw39F_C-rtSY.g._2F7.-_e..Or_-.3OHgt.U",
|
||||
"operator": "In",
|
||||
"values": [
|
||||
"y.8_8"
|
||||
]
|
||||
"key": "4ds4-4tz9x--j.1l11q5--uk5mj-94-8134i5k6q6--5tu-tie4-7--gm4p-8y-9-te5/H._____K_g1cXfr.4_.-_-_-...1py_8-3..s._.x.2K_2qu_0S-CqWD",
|
||||
"operator": "Exists"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"current": {
|
||||
"value": "671",
|
||||
"averageValue": "683",
|
||||
"averageUtilization": 1008425444
|
||||
"value": "378",
|
||||
"averageValue": "328",
|
||||
"averageUtilization": -1050824692
|
||||
}
|
||||
},
|
||||
"resource": {
|
||||
"name": "Ƈè*鑏='ʨ|ǓÓ敆OɈÏ 瞍髃",
|
||||
"name": "反-n覦灲閈誹ʅ蕉ɼ搳ǭ濑箨ʨ",
|
||||
"current": {
|
||||
"value": "93",
|
||||
"averageValue": "183",
|
||||
"averageUtilization": -392406530
|
||||
"value": "113",
|
||||
"averageValue": "653",
|
||||
"averageUtilization": 1190831814
|
||||
}
|
||||
},
|
||||
"containerResource": {
|
||||
"name": "腂ǂǚŜEuEy",
|
||||
"current": {
|
||||
"value": "77",
|
||||
"averageValue": "394",
|
||||
"averageUtilization": -1945921250
|
||||
},
|
||||
"container": "64"
|
||||
},
|
||||
"external": {
|
||||
"metric": {
|
||||
"name": "63",
|
||||
"name": "65",
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"627-23---g-----p8-d5-8-m8i--k0j5-gr-y7nlp97v-0-1y7/2....3_t_-l..-.DG7r-3.----._4__XOnf_ZN.-_--r.E__-8": "K.-miJ4x-_0_5-_7"
|
||||
"Tvw39F_C-rtSY.g._2F7.-_e..Or_-.3OHgt._U.-x_rC9..__-6_k.N-2B_Ve": "fh4.caTz_.g.w-o.8_WT-M.3_-1y_8E"
|
||||
},
|
||||
"matchExpressions": [
|
||||
{
|
||||
"key": "c-.F5_x.KNC0-.-m_0-m-6Sp_N-S..o",
|
||||
"operator": "In",
|
||||
"values": [
|
||||
"g-_4Q__-v_t_u_.__I_-_-3-3--5X1rh-K5y_AzOBW.9oE9_6.--v7"
|
||||
]
|
||||
"key": "n_H-.___._D8.TS-jJ.Ys_Mop34_-2",
|
||||
"operator": "DoesNotExist"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"current": {
|
||||
"value": "287",
|
||||
"averageValue": "759",
|
||||
"averageUtilization": -1175595426
|
||||
"value": "444",
|
||||
"averageValue": "797",
|
||||
"averageUtilization": 1928526133
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"type": "`翾'ųŎ群E牬庘颮6(|ǖû",
|
||||
"status": "龢ÄƤUǷ坒ŕF5o儎ĄÇ稕E",
|
||||
"lastTransitionTime": "2682-06-14T06:09:58Z",
|
||||
"reason": "70",
|
||||
"message": "71"
|
||||
"type": "44矕",
|
||||
"status": "ƱÁR»淹揀",
|
||||
"lastTransitionTime": "2026-05-26T09:35:23Z",
|
||||
"reason": "72",
|
||||
"message": "73"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Binary file not shown.
@ -33,36 +33,42 @@ spec:
|
||||
behavior:
|
||||
scaleDown:
|
||||
policies:
|
||||
- periodSeconds: 1255312175
|
||||
type: ɾģ毋Ó6dz娝嘚
|
||||
value: 627713162
|
||||
selectPolicy: /ɸɎ R§耶FfBls3!
|
||||
stabilizationWindowSeconds: 1206365825
|
||||
- periodSeconds: 1505972335
|
||||
type: VƋZ1Ůđ眊ľǎɳ,ǿ飏
|
||||
value: 2040455355
|
||||
selectPolicy: 褎weLJèux
|
||||
stabilizationWindowSeconds: -342705708
|
||||
scaleUp:
|
||||
policies:
|
||||
- periodSeconds: -686523310
|
||||
type: 嶗U
|
||||
value: -1285424066
|
||||
selectPolicy: 0矀Kʝ瘴I\p[ħsĨɆâĺɗŹ倗S
|
||||
stabilizationWindowSeconds: 1761963371
|
||||
- periodSeconds: 1048864116
|
||||
type: ȫ焗捏ĨFħ籘Àǒɿʒ刽
|
||||
value: 427196286
|
||||
selectPolicy: Ƿ裚瓶釆Ɗ+j忊
|
||||
stabilizationWindowSeconds: -648954478
|
||||
maxReplicas: -1971381490
|
||||
metrics:
|
||||
- external:
|
||||
- containerResource:
|
||||
container: "39"
|
||||
name: Ɋł/擇ɦĽ胚O醔ɍ厶耈
|
||||
target:
|
||||
averageUtilization: -1105572246
|
||||
averageValue: "151"
|
||||
type: 禒Ƙá腿ħ缶.蒅
|
||||
value: "999"
|
||||
external:
|
||||
metric:
|
||||
name: "39"
|
||||
name: "40"
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: n3-8d-0-5qty--4-p---u16-wv-i.84-n4f--139-295at-o7qff7-x--r7v66bm71u-n4f0/2_31.-.-yz-0-_p4mz--.I_f6kjsz-7lwY-Y93-x6bigm_-._q
|
||||
operator: In
|
||||
values:
|
||||
- Q3_Y.5.-..P_pDZ-._._t__2k
|
||||
- key: 1-1-x1z-j4kh6oqu-or---40--87-1wp6.759s-3------6tv27r-m8w-6-9-35d383-iq-ay1z25-3-vj73d/Y.t--_0..--_6yV07-_.___gO-d.iUaCw
|
||||
operator: DoesNotExist
|
||||
matchLabels:
|
||||
9s-m---vl80.5-6y-07b-3---g-jdi/z_-tY-R6S17_.8CnK_O.d-._NwcGnP-w-Sf5_Or.i1_7z.WH-.._d: 1_57__JR.N-1zL-4--6o--Bo-F__..XR.7_1-l
|
||||
wcGnP-w-Sf5_O1: "1_70"
|
||||
target:
|
||||
averageUtilization: -521487971
|
||||
averageValue: "301"
|
||||
type: 3.v-鿧悮坮Ȣ
|
||||
value: "82"
|
||||
averageUtilization: 747521320
|
||||
averageValue: "799"
|
||||
type: ʣy豎@ɀ羭,铻OŤ
|
||||
value: "830"
|
||||
object:
|
||||
describedObject:
|
||||
apiVersion: "24"
|
||||
@ -112,69 +118,71 @@ spec:
|
||||
name: "20"
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2682-06-14T06:09:58Z"
|
||||
message: "71"
|
||||
reason: "70"
|
||||
status: 龢ÄƤUǷ坒ŕF5o儎ĄÇ稕E
|
||||
type: '`翾''ųŎ群E牬庘颮6(|ǖû'
|
||||
- lastTransitionTime: "2026-05-26T09:35:23Z"
|
||||
message: "73"
|
||||
reason: "72"
|
||||
status: ƱÁR»淹揀
|
||||
type: 44矕
|
||||
currentMetrics:
|
||||
- external:
|
||||
- containerResource:
|
||||
container: "64"
|
||||
current:
|
||||
averageUtilization: -1175595426
|
||||
averageValue: "759"
|
||||
value: "287"
|
||||
averageUtilization: -1945921250
|
||||
averageValue: "394"
|
||||
value: "77"
|
||||
name: 腂ǂǚŜEuEy
|
||||
external:
|
||||
current:
|
||||
averageUtilization: 1928526133
|
||||
averageValue: "797"
|
||||
value: "444"
|
||||
metric:
|
||||
name: "63"
|
||||
name: "65"
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: c-.F5_x.KNC0-.-m_0-m-6Sp_N-S..o
|
||||
operator: In
|
||||
values:
|
||||
- g-_4Q__-v_t_u_.__I_-_-3-3--5X1rh-K5y_AzOBW.9oE9_6.--v7
|
||||
- key: n_H-.___._D8.TS-jJ.Ys_Mop34_-2
|
||||
operator: DoesNotExist
|
||||
matchLabels:
|
||||
627-23---g-----p8-d5-8-m8i--k0j5-gr-y7nlp97v-0-1y7/2....3_t_-l..-.DG7r-3.----._4__XOnf_ZN.-_--r.E__-8: K.-miJ4x-_0_5-_7
|
||||
Tvw39F_C-rtSY.g._2F7.-_e..Or_-.3OHgt._U.-x_rC9..__-6_k.N-2B_Ve: fh4.caTz_.g.w-o.8_WT-M.3_-1y_8E
|
||||
object:
|
||||
current:
|
||||
averageUtilization: -126958936
|
||||
averageValue: "860"
|
||||
value: "526"
|
||||
averageUtilization: -1666319281
|
||||
averageValue: "472"
|
||||
value: "124"
|
||||
describedObject:
|
||||
apiVersion: "55"
|
||||
kind: "53"
|
||||
name: "54"
|
||||
apiVersion: "56"
|
||||
kind: "54"
|
||||
name: "55"
|
||||
metric:
|
||||
name: "46"
|
||||
name: "47"
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: 6-d42--clo90---461v-07r--0---8-30i-uo/9DF
|
||||
operator: In
|
||||
- key: Dp665O_4Gj._BXt.O-7___-Y_um-_8r--684._-_188
|
||||
operator: NotIn
|
||||
values:
|
||||
- 2hT.-z-._7-5lL..-_--.VEa-_gn.8-c.C3_F._oX-F9_.5vN5.25aWx.a
|
||||
- XK5._..O_.J_-G_--V-42E_--o90G_A4..-L..-__0N_N.O30-_u._-2T
|
||||
matchLabels:
|
||||
29.-_Z.0_1._hg._o_p665O_4Gj._BXt.O-7___-Y_um-_8r--684._V: 8_...E.-o
|
||||
hA9..9__Y-H-Mqpt._.-_..05c.---qy-_5_S.d5a3Jb: 46g_4....1..jtFe8b_A_..P1s-V.9.4..9..c_uo3Pa__n-Di
|
||||
pods:
|
||||
current:
|
||||
averageUtilization: 1008425444
|
||||
averageValue: "683"
|
||||
value: "671"
|
||||
averageUtilization: -1050824692
|
||||
averageValue: "328"
|
||||
value: "378"
|
||||
metric:
|
||||
name: "56"
|
||||
name: "57"
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: 382m88w-pz9d4i-m7---k8235--8--c83-4b-9-1k.1f-53-x1y-8---3----p-pdn--j2---2--82--cj-1-s--op3w/3--Z1Tvw39F_C-rtSY.g._2F7.-_e..Or_-.3OHgt.U
|
||||
operator: In
|
||||
values:
|
||||
- y.8_8
|
||||
- key: 4ds4-4tz9x--j.1l11q5--uk5mj-94-8134i5k6q6--5tu-tie4-7--gm4p-8y-9-te5/H._____K_g1cXfr.4_.-_-_-...1py_8-3..s._.x.2K_2qu_0S-CqWD
|
||||
operator: Exists
|
||||
matchLabels:
|
||||
? d5-g-7-7---g88w2k4usz--mj-8o26--26-hs5-jeds4-4tz9x-4.i-l11q5--uk5mj-94-8134i5k6q6--5tu-tie4-7--gm4p-8y-99/N_g-..__._____K_g1cXfr4
|
||||
: ET_..3dCv3j._.-_pP__up.2L_s-o779._-k-N
|
||||
5.-_--.VEa-_gn.8-c.3: F._oX-F9_.5vN5.25aWx.2aM214_.-C
|
||||
resource:
|
||||
current:
|
||||
averageUtilization: -392406530
|
||||
averageValue: "183"
|
||||
value: "93"
|
||||
name: Ƈè*鑏='ʨ|ǓÓ敆OɈÏ 瞍髃
|
||||
type: Ǖɳɷ9Ì崟¿瘦ɖ緕
|
||||
currentReplicas: 267768240
|
||||
desiredReplicas: -127849333
|
||||
observedGeneration: -7477362499801752548
|
||||
averageUtilization: 1190831814
|
||||
averageValue: "653"
|
||||
value: "113"
|
||||
name: 反-n覦灲閈誹ʅ蕉ɼ搳ǭ濑箨ʨ
|
||||
type: 0Ƹ[Ęİ榌U
|
||||
currentReplicas: 474119379
|
||||
desiredReplicas: 1923334396
|
||||
observedGeneration: -115578794491385044
|
||||
|
@ -30,6 +30,8 @@ import (
|
||||
|
||||
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
|
||||
return map[string]common.OpenAPIDefinition{
|
||||
"k8s.io/api/autoscaling/v1.ContainerResourceMetricSource": schema_k8sio_api_autoscaling_v1_ContainerResourceMetricSource(ref),
|
||||
"k8s.io/api/autoscaling/v1.ContainerResourceMetricStatus": schema_k8sio_api_autoscaling_v1_ContainerResourceMetricStatus(ref),
|
||||
"k8s.io/api/autoscaling/v1.CrossVersionObjectReference": schema_k8sio_api_autoscaling_v1_CrossVersionObjectReference(ref),
|
||||
"k8s.io/api/autoscaling/v1.ExternalMetricSource": schema_k8sio_api_autoscaling_v1_ExternalMetricSource(ref),
|
||||
"k8s.io/api/autoscaling/v1.ExternalMetricStatus": schema_k8sio_api_autoscaling_v1_ExternalMetricStatus(ref),
|
||||
@ -104,6 +106,92 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_api_autoscaling_v1_ContainerResourceMetricSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ContainerResourceMetricSource indicates how to scale on a resource metric known to Kubernetes, as specified in the requests and limits, describing a single container in each of the pods of the current scale target(e.g. CPU or memory). The values will be averaged together before being compared to the target. Such metrics are built into Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. Only one \"target\" type should be set.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "name is the name of the resource in question.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"targetAverageUtilization": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "targetAverageUtilization is the target value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods.",
|
||||
Type: []string{"integer"},
|
||||
Format: "int32",
|
||||
},
|
||||
},
|
||||
"targetAverageValue": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "targetAverageValue is the target value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"),
|
||||
},
|
||||
},
|
||||
"container": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "container is the name of the container in the pods of the scaling target.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"name", "container"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/api/resource.Quantity"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_api_autoscaling_v1_ContainerResourceMetricStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ContainerResourceMetricStatus indicates the current value of a resource metric known to Kubernetes, as specified in requests and limits, describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "name is the name of the resource in question.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"currentAverageUtilization": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "currentAverageUtilization is the current value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods. It will only be present if `targetAverageValue` was set in the corresponding metric specification.",
|
||||
Type: []string{"integer"},
|
||||
Format: "int32",
|
||||
},
|
||||
},
|
||||
"currentAverageValue": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "currentAverageValue is the current value of the average of the resource metric across all relevant pods, as a raw value (instead of as a percentage of the request), similar to the \"pods\" metric source type. It will always be set, regardless of the corresponding metric specification.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/api/resource.Quantity"),
|
||||
},
|
||||
},
|
||||
"container": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "container is the name of the container in the pods of the scaling taget",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"name", "currentAverageValue", "container"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/api/resource.Quantity"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_api_autoscaling_v1_CrossVersionObjectReference(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
@ -469,7 +557,7 @@ func schema_k8sio_api_autoscaling_v1_MetricSpec(ref common.ReferenceCallback) co
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "type is the type of metric source. It should be one of \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object.",
|
||||
Description: "type is the type of metric source. It should be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each mapping to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
@ -492,6 +580,12 @@ func schema_k8sio_api_autoscaling_v1_MetricSpec(ref common.ReferenceCallback) co
|
||||
Ref: ref("k8s.io/api/autoscaling/v1.ResourceMetricSource"),
|
||||
},
|
||||
},
|
||||
"containerResource": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod of the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source. This is an alpha feature and can be enabled by the HPAContainerMetrics feature flag.",
|
||||
Ref: ref("k8s.io/api/autoscaling/v1.ContainerResourceMetricSource"),
|
||||
},
|
||||
},
|
||||
"external": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
@ -503,7 +597,7 @@ func schema_k8sio_api_autoscaling_v1_MetricSpec(ref common.ReferenceCallback) co
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/api/autoscaling/v1.ExternalMetricSource", "k8s.io/api/autoscaling/v1.ObjectMetricSource", "k8s.io/api/autoscaling/v1.PodsMetricSource", "k8s.io/api/autoscaling/v1.ResourceMetricSource"},
|
||||
"k8s.io/api/autoscaling/v1.ContainerResourceMetricSource", "k8s.io/api/autoscaling/v1.ExternalMetricSource", "k8s.io/api/autoscaling/v1.ObjectMetricSource", "k8s.io/api/autoscaling/v1.PodsMetricSource", "k8s.io/api/autoscaling/v1.ResourceMetricSource"},
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,7 +610,7 @@ func schema_k8sio_api_autoscaling_v1_MetricStatus(ref common.ReferenceCallback)
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "type is the type of metric source. It will be one of \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object.",
|
||||
Description: "type is the type of metric source. It will be one of \"ContainerResource\", \"External\", \"Object\", \"Pods\" or \"Resource\", each corresponds to a matching field in the object. Note: \"ContainerResource\" type is available on when the feature-gate HPAContainerMetrics is enabled",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
@ -539,6 +633,12 @@ func schema_k8sio_api_autoscaling_v1_MetricStatus(ref common.ReferenceCallback)
|
||||
Ref: ref("k8s.io/api/autoscaling/v1.ResourceMetricStatus"),
|
||||
},
|
||||
},
|
||||
"containerResource": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "container resource refers to a resource metric (such as those specified in requests and limits) known to Kubernetes describing a single container in each pod in the current scale target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and have special scaling options on top of those available to normal per-pod metrics using the \"pods\" source.",
|
||||
Ref: ref("k8s.io/api/autoscaling/v1.ContainerResourceMetricStatus"),
|
||||
},
|
||||
},
|
||||
"external": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "external refers to a global metric that is not associated with any Kubernetes object. It allows autoscaling based on information coming from components running outside of cluster (for example length of queue in cloud messaging service, or QPS from loadbalancer running outside of cluster).",
|
||||
@ -550,7 +650,7 @@ func schema_k8sio_api_autoscaling_v1_MetricStatus(ref common.ReferenceCallback)
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/api/autoscaling/v1.ExternalMetricStatus", "k8s.io/api/autoscaling/v1.ObjectMetricStatus", "k8s.io/api/autoscaling/v1.PodsMetricStatus", "k8s.io/api/autoscaling/v1.ResourceMetricStatus"},
|
||||
"k8s.io/api/autoscaling/v1.ContainerResourceMetricStatus", "k8s.io/api/autoscaling/v1.ExternalMetricStatus", "k8s.io/api/autoscaling/v1.ObjectMetricStatus", "k8s.io/api/autoscaling/v1.PodsMetricStatus", "k8s.io/api/autoscaling/v1.ResourceMetricStatus"},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3653,6 +3653,26 @@ func describeHorizontalPodAutoscalerV2beta2(hpa *autoscalingv2beta2.HorizontalPo
|
||||
}
|
||||
w.Write(LEVEL_1, "(as a percentage of request):\t%s / %s\n", current, target)
|
||||
}
|
||||
case autoscalingv2beta2.ContainerResourceMetricSourceType:
|
||||
w.Write(LEVEL_1, "resource %s of container \"%s\" on pods", string(metric.ContainerResource.Name), metric.ContainerResource.Container)
|
||||
if metric.ContainerResource.Target.AverageValue != nil {
|
||||
current := "<unknown>"
|
||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].ContainerResource != nil {
|
||||
current = hpa.Status.CurrentMetrics[i].ContainerResource.Current.AverageValue.String()
|
||||
}
|
||||
w.Write(LEVEL_0, ":\t%s / %s\n", current, metric.ContainerResource.Target.AverageValue.String())
|
||||
} else {
|
||||
current := "<unknown>"
|
||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].ContainerResource != nil && hpa.Status.CurrentMetrics[i].ContainerResource.Current.AverageUtilization != nil {
|
||||
current = fmt.Sprintf("%d%% (%s)", *hpa.Status.CurrentMetrics[i].ContainerResource.Current.AverageUtilization, hpa.Status.CurrentMetrics[i].ContainerResource.Current.AverageValue.String())
|
||||
}
|
||||
|
||||
target := "<auto>"
|
||||
if metric.ContainerResource.Target.AverageUtilization != nil {
|
||||
target = fmt.Sprintf("%d%%", *metric.ContainerResource.Target.AverageUtilization)
|
||||
}
|
||||
w.Write(LEVEL_1, "(as a percentage of request):\t%s / %s\n", current, target)
|
||||
}
|
||||
default:
|
||||
w.Write(LEVEL_1, "<unknown metric type %q>\n", string(metric.Type))
|
||||
}
|
||||
|
@ -2711,6 +2711,152 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"container resource source type, target average value (no current)",
|
||||
autoscalingv2beta2.HorizontalPodAutoscaler{
|
||||
Spec: autoscalingv2beta2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscalingv2beta2.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscalingv2beta2.MetricSpec{
|
||||
{
|
||||
Type: autoscalingv2beta2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2beta2.ContainerResourceMetricSource{
|
||||
Name: corev1.ResourceCPU,
|
||||
Container: "application",
|
||||
Target: autoscalingv2beta2.MetricTarget{
|
||||
Type: autoscalingv2beta2.AverageValueMetricType,
|
||||
AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscalingv2beta2.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"container resource source type, target average value (with current)",
|
||||
autoscalingv2beta2.HorizontalPodAutoscaler{
|
||||
Spec: autoscalingv2beta2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscalingv2beta2.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscalingv2beta2.MetricSpec{
|
||||
{
|
||||
Type: autoscalingv2beta2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2beta2.ContainerResourceMetricSource{
|
||||
Name: corev1.ResourceCPU,
|
||||
Container: "application",
|
||||
Target: autoscalingv2beta2.MetricTarget{
|
||||
Type: autoscalingv2beta2.AverageValueMetricType,
|
||||
AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscalingv2beta2.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscalingv2beta2.MetricStatus{
|
||||
{
|
||||
Type: autoscalingv2beta2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2beta2.ContainerResourceMetricStatus{
|
||||
Name: corev1.ResourceCPU,
|
||||
Container: "application",
|
||||
Current: autoscalingv2beta2.MetricValueStatus{
|
||||
AverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"container resource source type, target utilization (no current)",
|
||||
autoscalingv2beta2.HorizontalPodAutoscaler{
|
||||
Spec: autoscalingv2beta2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscalingv2beta2.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscalingv2beta2.MetricSpec{
|
||||
{
|
||||
Type: autoscalingv2beta2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2beta2.ContainerResourceMetricSource{
|
||||
Name: corev1.ResourceCPU,
|
||||
Container: "application",
|
||||
Target: autoscalingv2beta2.MetricTarget{
|
||||
Type: autoscalingv2beta2.UtilizationMetricType,
|
||||
AverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscalingv2beta2.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"container resource source type, target utilization (with current)",
|
||||
autoscalingv2beta2.HorizontalPodAutoscaler{
|
||||
Spec: autoscalingv2beta2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscalingv2beta2.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscalingv2beta2.MetricSpec{
|
||||
{
|
||||
Type: autoscalingv2beta2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2beta2.ContainerResourceMetricSource{
|
||||
Name: corev1.ResourceCPU,
|
||||
Container: "application",
|
||||
Target: autoscalingv2beta2.MetricTarget{
|
||||
Type: autoscalingv2beta2.UtilizationMetricType,
|
||||
AverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscalingv2beta2.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscalingv2beta2.MetricStatus{
|
||||
{
|
||||
Type: autoscalingv2beta2.ContainerResourceMetricSourceType,
|
||||
ContainerResource: &autoscalingv2beta2.ContainerResourceMetricStatus{
|
||||
Name: corev1.ResourceCPU,
|
||||
Container: "application",
|
||||
Current: autoscalingv2beta2.MetricValueStatus{
|
||||
AverageUtilization: ¤tUtilizationVal,
|
||||
AverageValue: resource.NewMilliQuantity(40, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"multiple metrics",
|
||||
autoscalingv2beta2.HorizontalPodAutoscaler{
|
||||
|
Loading…
Reference in New Issue
Block a user