mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Better choices of what pods to kill
This commit is contained in:
		@@ -34,6 +34,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/labels"
 | 
						"k8s.io/kubernetes/pkg/labels"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/runtime"
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util"
 | 
						"k8s.io/kubernetes/pkg/util"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/util/integer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const CreatedByAnnotation = "kubernetes.io/created-by"
 | 
					const CreatedByAnnotation = "kubernetes.io/created-by"
 | 
				
			||||||
@@ -409,22 +410,59 @@ func (s ActivePods) Len() int      { return len(s) }
 | 
				
			|||||||
func (s ActivePods) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
 | 
					func (s ActivePods) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s ActivePods) Less(i, j int) bool {
 | 
					func (s ActivePods) Less(i, j int) bool {
 | 
				
			||||||
	// Unassigned < assigned
 | 
						// 1. Unassigned < assigned
 | 
				
			||||||
	if s[i].Spec.NodeName == "" && s[j].Spec.NodeName != "" {
 | 
						// If only one of the pods is unassigned, the unassigned one is smaller
 | 
				
			||||||
		return true
 | 
						if s[i].Spec.NodeName != s[j].Spec.NodeName && (len(s[i].Spec.NodeName) == 0 || len(s[j].Spec.NodeName) == 0) {
 | 
				
			||||||
 | 
							return len(s[i].Spec.NodeName) == 0
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// PodPending < PodUnknown < PodRunning
 | 
						// 2. PodPending < PodUnknown < PodRunning
 | 
				
			||||||
	m := map[api.PodPhase]int{api.PodPending: 0, api.PodUnknown: 1, api.PodRunning: 2}
 | 
						m := map[api.PodPhase]int{api.PodPending: 0, api.PodUnknown: 1, api.PodRunning: 2}
 | 
				
			||||||
	if m[s[i].Status.Phase] != m[s[j].Status.Phase] {
 | 
						if m[s[i].Status.Phase] != m[s[j].Status.Phase] {
 | 
				
			||||||
		return m[s[i].Status.Phase] < m[s[j].Status.Phase]
 | 
							return m[s[i].Status.Phase] < m[s[j].Status.Phase]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Not ready < ready
 | 
						// 3. Not ready < ready
 | 
				
			||||||
	if !api.IsPodReady(s[i]) && api.IsPodReady(s[j]) {
 | 
						// If only one of the pods is not ready, the not ready one is smaller
 | 
				
			||||||
		return true
 | 
						if api.IsPodReady(s[i]) != api.IsPodReady(s[j]) {
 | 
				
			||||||
 | 
							return !api.IsPodReady(s[i])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: take availability into account when we push minReadySeconds information from deployment into pods,
 | 
				
			||||||
 | 
						//       see https://github.com/kubernetes/kubernetes/issues/22065
 | 
				
			||||||
 | 
						// 4. Been ready for less time < more time
 | 
				
			||||||
 | 
						// If both pods are ready, the latest ready one is smaller
 | 
				
			||||||
 | 
						if api.IsPodReady(s[i]) && api.IsPodReady(s[j]) && !podReadyTime(s[i]).Equal(podReadyTime(s[j])) {
 | 
				
			||||||
 | 
							return podReadyTime(s[i]).After(podReadyTime(s[j]).Time)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 5. Pods with containers with higher restart counts < lower restart counts
 | 
				
			||||||
 | 
						if maxContainerRestarts(s[i]) != maxContainerRestarts(s[j]) {
 | 
				
			||||||
 | 
							return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 6. Newer pods < older pods
 | 
				
			||||||
 | 
						if !s[i].CreationTimestamp.Equal(s[j].CreationTimestamp) {
 | 
				
			||||||
 | 
							return s[i].CreationTimestamp.After(s[j].CreationTimestamp.Time)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func podReadyTime(pod *api.Pod) unversioned.Time {
 | 
				
			||||||
 | 
						if api.IsPodReady(pod) {
 | 
				
			||||||
 | 
							for _, c := range pod.Status.Conditions {
 | 
				
			||||||
 | 
								// we only care about pod ready conditions
 | 
				
			||||||
 | 
								if c.Type == api.PodReady && c.Status == api.ConditionTrue {
 | 
				
			||||||
 | 
									return c.LastTransitionTime
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return unversioned.Time{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func maxContainerRestarts(pod *api.Pod) int {
 | 
				
			||||||
 | 
						maxRestarts := 0
 | 
				
			||||||
 | 
						for _, c := range pod.Status.ContainerStatuses {
 | 
				
			||||||
 | 
							maxRestarts = integer.IntMax(maxRestarts, c.RestartCount)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return maxRestarts
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FilterActivePods returns pods that have not terminated.
 | 
					// FilterActivePods returns pods that have not terminated.
 | 
				
			||||||
func FilterActivePods(pods []api.Pod) []*api.Pod {
 | 
					func FilterActivePods(pods []api.Pod) []*api.Pod {
 | 
				
			||||||
	var result []*api.Pod
 | 
						var result []*api.Pod
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -245,7 +245,7 @@ func TestActivePodFiltering(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSortingActivePods(t *testing.T) {
 | 
					func TestSortingActivePods(t *testing.T) {
 | 
				
			||||||
	numPods := 5
 | 
						numPods := 8
 | 
				
			||||||
	// This rc is not needed by the test, only the newPodList to give the pods labels/a namespace.
 | 
						// This rc is not needed by the test, only the newPodList to give the pods labels/a namespace.
 | 
				
			||||||
	rc := newReplicationController(0)
 | 
						rc := newReplicationController(0)
 | 
				
			||||||
	podList := newPodList(nil, numPods, api.PodRunning, rc)
 | 
						podList := newPodList(nil, numPods, api.PodRunning, rc)
 | 
				
			||||||
@@ -267,9 +267,29 @@ func TestSortingActivePods(t *testing.T) {
 | 
				
			|||||||
	pods[3].Spec.NodeName = "foo"
 | 
						pods[3].Spec.NodeName = "foo"
 | 
				
			||||||
	pods[3].Status.Phase = api.PodRunning
 | 
						pods[3].Status.Phase = api.PodRunning
 | 
				
			||||||
	// pods[4] is running and ready.
 | 
						// pods[4] is running and ready.
 | 
				
			||||||
 | 
						now := unversioned.Now()
 | 
				
			||||||
	pods[4].Spec.NodeName = "foo"
 | 
						pods[4].Spec.NodeName = "foo"
 | 
				
			||||||
	pods[4].Status.Phase = api.PodRunning
 | 
						pods[4].Status.Phase = api.PodRunning
 | 
				
			||||||
	pods[4].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue}}
 | 
						pods[4].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: now}}
 | 
				
			||||||
 | 
						pods[4].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}
 | 
				
			||||||
 | 
						// pods[5] is running ready for a longer time than pods[4].
 | 
				
			||||||
 | 
						then := unversioned.Time{Time: now.AddDate(0, -1, 0)}
 | 
				
			||||||
 | 
						pods[5].Spec.NodeName = "foo"
 | 
				
			||||||
 | 
						pods[5].Status.Phase = api.PodRunning
 | 
				
			||||||
 | 
						pods[5].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: then}}
 | 
				
			||||||
 | 
						pods[5].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}
 | 
				
			||||||
 | 
						// pods[6] has lower container restart count than pods[5].
 | 
				
			||||||
 | 
						pods[6].Spec.NodeName = "foo"
 | 
				
			||||||
 | 
						pods[6].Status.Phase = api.PodRunning
 | 
				
			||||||
 | 
						pods[6].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: then}}
 | 
				
			||||||
 | 
						pods[6].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}}
 | 
				
			||||||
 | 
						pods[6].CreationTimestamp = now
 | 
				
			||||||
 | 
						// pods[7] is older than pods[6].
 | 
				
			||||||
 | 
						pods[7].Spec.NodeName = "foo"
 | 
				
			||||||
 | 
						pods[7].Status.Phase = api.PodRunning
 | 
				
			||||||
 | 
						pods[7].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: then}}
 | 
				
			||||||
 | 
						pods[7].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}}
 | 
				
			||||||
 | 
						pods[7].CreationTimestamp = then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	getOrder := func(pods []*api.Pod) []string {
 | 
						getOrder := func(pods []*api.Pod) []string {
 | 
				
			||||||
		names := make([]string, len(pods))
 | 
							names := make([]string, len(pods))
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user