mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
Promote LogarithmicScaleDown to beta
This promotes the LogarithmicScaleDown feature gate to Beta, enabling it by default. It also introduces a new metric, `sorting_deletion_age_ratio`, intended to measure the efficacy of this new replica set scaledown behavior.
This commit is contained in:
parent
a445eb2b7f
commit
4b9230ed27
44
pkg/controller/replicaset/metrics/metrics.go
Normal file
44
pkg/controller/replicaset/metrics/metrics.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/component-base/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ReplicaSetControllerSubsystem = "replicaset_controller"
|
||||||
|
|
||||||
|
var SortingDeletionAgeRatio = metrics.NewHistogram(
|
||||||
|
&metrics.HistogramOpts{
|
||||||
|
Subsystem: ReplicaSetControllerSubsystem,
|
||||||
|
Name: "sorting_deletion_age_ratio",
|
||||||
|
Help: "The ratio of chosen deleted pod's ages to the current youngest pod's age (at the time). Should be <2." +
|
||||||
|
"The intent of this metric is to measure the rough efficacy of the LogarithmicScaleDown feature gate's effect on" +
|
||||||
|
"the sorting (and deletion) of pods when a replicaset scales down. This only considers Ready pods when calculating and reporting.",
|
||||||
|
Buckets: metrics.ExponentialBuckets(0.25, 2, 6),
|
||||||
|
StabilityLevel: metrics.ALPHA,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register registers ReplicaSet controller metrics.
|
||||||
|
func Register(registrationFunc func(metrics.Registerable) error) error {
|
||||||
|
err := registrationFunc(SortingDeletionAgeRatio)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -55,10 +55,12 @@ import (
|
|||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
"k8s.io/component-base/metrics/legacyregistry"
|
||||||
"k8s.io/component-base/metrics/prometheus/ratelimiter"
|
"k8s.io/component-base/metrics/prometheus/ratelimiter"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
|
"k8s.io/kubernetes/pkg/controller/replicaset/metrics"
|
||||||
"k8s.io/utils/integer"
|
"k8s.io/utils/integer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -112,6 +114,9 @@ func NewReplicaSetController(rsInformer appsinformers.ReplicaSetInformer, podInf
|
|||||||
eventBroadcaster := record.NewBroadcaster()
|
eventBroadcaster := record.NewBroadcaster()
|
||||||
eventBroadcaster.StartStructuredLogging(0)
|
eventBroadcaster.StartStructuredLogging(0)
|
||||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
|
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
|
||||||
|
if err := metrics.Register(legacyregistry.Register); err != nil {
|
||||||
|
klog.ErrorS(err, "unable to register metrics")
|
||||||
|
}
|
||||||
return NewBaseController(rsInformer, podInformer, kubeClient, burstReplicas,
|
return NewBaseController(rsInformer, podInformer, kubeClient, burstReplicas,
|
||||||
apps.SchemeGroupVersion.WithKind("ReplicaSet"),
|
apps.SchemeGroupVersion.WithKind("ReplicaSet"),
|
||||||
"replicaset_controller",
|
"replicaset_controller",
|
||||||
@ -802,10 +807,31 @@ func getPodsToDelete(filteredPods, relatedPods []*v1.Pod, diff int) []*v1.Pod {
|
|||||||
if diff < len(filteredPods) {
|
if diff < len(filteredPods) {
|
||||||
podsWithRanks := getPodsRankedByRelatedPodsOnSameNode(filteredPods, relatedPods)
|
podsWithRanks := getPodsRankedByRelatedPodsOnSameNode(filteredPods, relatedPods)
|
||||||
sort.Sort(podsWithRanks)
|
sort.Sort(podsWithRanks)
|
||||||
|
reportSortingDeletionAgeRatioMetric(filteredPods, diff)
|
||||||
}
|
}
|
||||||
return filteredPods[:diff]
|
return filteredPods[:diff]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reportSortingDeletionAgeRatioMetric(filteredPods []*v1.Pod, diff int) {
|
||||||
|
now := time.Now()
|
||||||
|
youngestTime := time.Time{}
|
||||||
|
// first we need to check all of the ready pods to get the youngest, as they may not necessarily be sorted by timestamp alone
|
||||||
|
for _, pod := range filteredPods {
|
||||||
|
if pod.CreationTimestamp.Time.After(youngestTime) && podutil.IsPodReady(pod) {
|
||||||
|
youngestTime = pod.CreationTimestamp.Time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each pod chosen for deletion, report the ratio of its age to the youngest pod's age
|
||||||
|
for _, pod := range filteredPods[:diff] {
|
||||||
|
if !podutil.IsPodReady(pod) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ratio := float64(now.Sub(pod.CreationTimestamp.Time).Milliseconds() / now.Sub(youngestTime).Milliseconds())
|
||||||
|
metrics.SortingDeletionAgeRatio.Observe(ratio)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// getPodsRankedByRelatedPodsOnSameNode returns an ActivePodsWithRanks value
|
// getPodsRankedByRelatedPodsOnSameNode returns an ActivePodsWithRanks value
|
||||||
// that wraps podsToRank and assigns each pod a rank equal to the number of
|
// that wraps podsToRank and assigns each pod a rank equal to the number of
|
||||||
// active pods in relatedPods that are colocated on the same node with the pod.
|
// active pods in relatedPods that are colocated on the same node with the pod.
|
||||||
|
@ -658,7 +658,8 @@ const (
|
|||||||
ServiceLoadBalancerClass featuregate.Feature = "ServiceLoadBalancerClass"
|
ServiceLoadBalancerClass featuregate.Feature = "ServiceLoadBalancerClass"
|
||||||
|
|
||||||
// owner: @damemi
|
// owner: @damemi
|
||||||
// aplpha: v1.21
|
// alpha: v1.21
|
||||||
|
// beta: v1.22
|
||||||
//
|
//
|
||||||
// Enables scaling down replicas via logarithmic comparison of creation/ready timestamps
|
// Enables scaling down replicas via logarithmic comparison of creation/ready timestamps
|
||||||
LogarithmicScaleDown featuregate.Feature = "LogarithmicScaleDown"
|
LogarithmicScaleDown featuregate.Feature = "LogarithmicScaleDown"
|
||||||
@ -844,9 +845,9 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
TopologyAwareHints: {Default: false, PreRelease: featuregate.Alpha},
|
TopologyAwareHints: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
PodAffinityNamespaceSelector: {Default: true, PreRelease: featuregate.Beta},
|
PodAffinityNamespaceSelector: {Default: true, PreRelease: featuregate.Beta},
|
||||||
ServiceLoadBalancerClass: {Default: true, PreRelease: featuregate.Beta},
|
ServiceLoadBalancerClass: {Default: true, PreRelease: featuregate.Beta},
|
||||||
LogarithmicScaleDown: {Default: false, PreRelease: featuregate.Alpha},
|
|
||||||
IngressClassNamespacedParams: {Default: true, PreRelease: featuregate.Beta},
|
IngressClassNamespacedParams: {Default: true, PreRelease: featuregate.Beta},
|
||||||
ServiceInternalTrafficPolicy: {Default: true, PreRelease: featuregate.Beta},
|
ServiceInternalTrafficPolicy: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
LogarithmicScaleDown: {Default: true, PreRelease: featuregate.Beta},
|
||||||
SuspendJob: {Default: true, PreRelease: featuregate.Beta},
|
SuspendJob: {Default: true, PreRelease: featuregate.Beta},
|
||||||
KubeletPodResourcesGetAllocatable: {Default: false, PreRelease: featuregate.Alpha},
|
KubeletPodResourcesGetAllocatable: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
NamespaceDefaultLabelName: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.24
|
NamespaceDefaultLabelName: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.24
|
||||||
|
Loading…
Reference in New Issue
Block a user