in vertical-pod-autoscaler/pkg/updater/logic/updater.go [109:233]
func (u *updater) RunOnce(ctx context.Context) {
timer := metrics_updater.NewExecutionTimer()
defer timer.ObserveTotal()
if u.useAdmissionControllerStatus {
isValid, err := u.statusValidator.IsStatusValid(status.AdmissionControllerStatusTimeout)
if err != nil {
klog.Errorf("Error getting Admission Controller status: %v. Skipping eviction loop", err)
return
}
if !isValid {
klog.Warningf("Admission Controller status has been refreshed more than %v ago. Skipping eviction loop",
status.AdmissionControllerStatusTimeout)
return
}
}
vpaList, err := u.vpaLister.List(labels.Everything())
if err != nil {
klog.Fatalf("failed get VPA list: %v", err)
}
timer.ObserveStep("ListVPAs")
vpas := make([]*vpa_api_util.VpaWithSelector, 0)
for _, vpa := range vpaList {
if vpa_api_util.GetUpdateMode(vpa) != vpa_types.UpdateModeRecreate &&
vpa_api_util.GetUpdateMode(vpa) != vpa_types.UpdateModeAuto {
klog.V(3).Infof("skipping VPA object %v because its mode is not \"Recreate\" or \"Auto\"", vpa.Name)
continue
}
selector, err := u.selectorFetcher.Fetch(vpa)
if err != nil {
klog.V(3).Infof("skipping VPA object %v because we cannot fetch selector", vpa.Name)
continue
}
vpas = append(vpas, &vpa_api_util.VpaWithSelector{
Vpa: vpa,
Selector: selector,
})
}
if len(vpas) == 0 {
klog.Warningf("no VPA objects to process")
if u.evictionAdmission != nil {
u.evictionAdmission.CleanUp()
}
return
}
podsList, err := u.podLister.List(labels.Everything())
if err != nil {
klog.Errorf("failed to get pods list: %v", err)
return
}
timer.ObserveStep("ListPods")
allLivePods := filterDeletedPods(podsList)
controlledPods := make(map[*vpa_types.VerticalPodAutoscaler][]*apiv1.Pod)
for _, pod := range allLivePods {
controllingVPA := vpa_api_util.GetControllingVPAForPod(pod, vpas)
if controllingVPA != nil {
controlledPods[controllingVPA.Vpa] = append(controlledPods[controllingVPA.Vpa], pod)
}
}
timer.ObserveStep("FilterPods")
if u.evictionAdmission != nil {
u.evictionAdmission.LoopInit(allLivePods, controlledPods)
}
timer.ObserveStep("AdmissionInit")
// wrappers for metrics which are computed every loop run
controlledPodsCounter := metrics_updater.NewControlledPodsCounter()
evictablePodsCounter := metrics_updater.NewEvictablePodsCounter()
vpasWithEvictablePodsCounter := metrics_updater.NewVpasWithEvictablePodsCounter()
vpasWithEvictedPodsCounter := metrics_updater.NewVpasWithEvictedPodsCounter()
// using defer to protect against 'return' after evictionRateLimiter.Wait
defer controlledPodsCounter.Observe()
defer evictablePodsCounter.Observe()
defer vpasWithEvictablePodsCounter.Observe()
defer vpasWithEvictedPodsCounter.Observe()
// NOTE: this loop assumes that controlledPods are filtered
// to contain only Pods controlled by a VPA in auto or recreate mode
for vpa, livePods := range controlledPods {
vpaSize := len(livePods)
controlledPodsCounter.Add(vpaSize, vpaSize)
evictionLimiter := u.evictionFactory.NewPodsEvictionRestriction(livePods, vpa)
podsForUpdate := u.getPodsUpdateOrder(filterNonEvictablePods(livePods, evictionLimiter), vpa)
evictablePodsCounter.Add(vpaSize, len(podsForUpdate))
withEvictable := false
withEvicted := false
for _, pod := range podsForUpdate {
withEvictable = true
if !evictionLimiter.CanEvict(pod) {
continue
}
err := u.evictionRateLimiter.Wait(ctx)
if err != nil {
klog.Warningf("evicting pod %v failed: %v", pod.Name, err)
return
}
klog.V(2).Infof("evicting pod %v", pod.Name)
evictErr := evictionLimiter.Evict(pod, u.eventRecorder)
if evictErr != nil {
klog.Warningf("evicting pod %v failed: %v", pod.Name, evictErr)
} else {
withEvicted = true
metrics_updater.AddEvictedPod(vpaSize)
}
}
if withEvictable {
vpasWithEvictablePodsCounter.Add(vpaSize, 1)
}
if withEvicted {
vpasWithEvictedPodsCounter.Add(vpaSize, 1)
}
}
timer.ObserveStep("EvictPods")
}