mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 05:14:13 +01:00
PodLifeTime: update support pods with container status and pods reason (#1330)
* update support podlifetime status Signed-off-by: dongjiang1989 <dongjiang1989@126.com> * update verify gen Signed-off-by: dongjiang1989 <dongjiang1989@126.com> --------- Signed-off-by: dongjiang1989 <dongjiang1989@126.com>
This commit is contained in:
@@ -637,8 +637,9 @@ profiles:
|
|||||||
This strategy evicts pods that are older than `maxPodLifeTimeSeconds`.
|
This strategy evicts pods that are older than `maxPodLifeTimeSeconds`.
|
||||||
|
|
||||||
You can also specify `states` parameter to **only** evict pods matching the following conditions:
|
You can also specify `states` parameter to **only** evict pods matching the following conditions:
|
||||||
- [Pod Phase](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase) status of: `Running`, `Pending`
|
- [Pod Phase](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase) status of: `Running`, `Pending`, `Unknown`
|
||||||
- [Container State Waiting](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-state-waiting) condition of: `PodInitializing`, `ContainerCreating`, `ImagePullBackOff`
|
- [Pod Reason](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions) reasons of: `NodeAffinity`, `NodeLost`, `Shutdown`, `UnexpectedAdmissionError`
|
||||||
|
- [Container State Waiting](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-state-waiting) condition of: `PodInitializing`, `ContainerCreating`, `ImagePullBackOff`, `CrashLoopBackOff`, `CreateContainerConfigError`, `ErrImagePull`, `ImagePullBackOff`, `CreateContainerError`, `InvalidImageName`
|
||||||
|
|
||||||
If a value for `states` or `podStatusPhases` is not specified,
|
If a value for `states` or `podStatusPhases` is not specified,
|
||||||
Pods in any state (even `Running`) are considered for eviction.
|
Pods in any state (even `Running`) are considered for eviction.
|
||||||
|
|||||||
@@ -75,10 +75,17 @@ func New(args runtime.Object, handle frameworktypes.Handle) (frameworktypes.Plug
|
|||||||
if len(podLifeTimeArgs.States) > 0 {
|
if len(podLifeTimeArgs.States) > 0 {
|
||||||
states := sets.New(podLifeTimeArgs.States...)
|
states := sets.New(podLifeTimeArgs.States...)
|
||||||
podFilter = podutil.WrapFilterFuncs(podFilter, func(pod *v1.Pod) bool {
|
podFilter = podutil.WrapFilterFuncs(podFilter, func(pod *v1.Pod) bool {
|
||||||
|
// Pod Status Phase
|
||||||
if states.Has(string(pod.Status.Phase)) {
|
if states.Has(string(pod.Status.Phase)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pod Status Reason
|
||||||
|
if states.Has(pod.Status.Reason) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container Status Reason
|
||||||
for _, containerStatus := range pod.Status.ContainerStatuses {
|
for _, containerStatus := range pod.Status.ContainerStatuses {
|
||||||
if containerStatus.State.Waiting != nil && states.Has(containerStatus.State.Waiting.Reason) {
|
if containerStatus.State.Waiting != nil && states.Has(containerStatus.State.Waiting.Reason) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -141,6 +141,12 @@ func TestPodLifeTime(t *testing.T) {
|
|||||||
p14.DeletionTimestamp = &metav1.Time{}
|
p14.DeletionTimestamp = &metav1.Time{}
|
||||||
p15.DeletionTimestamp = &metav1.Time{}
|
p15.DeletionTimestamp = &metav1.Time{}
|
||||||
|
|
||||||
|
p16 := test.BuildTestPod("p16", 100, 0, node1.Name, nil)
|
||||||
|
p16.Namespace = "dev"
|
||||||
|
p16.ObjectMeta.CreationTimestamp = olderPodCreationTime
|
||||||
|
p16.Status.Phase = v1.PodUnknown
|
||||||
|
p16.ObjectMeta.OwnerReferences = ownerRef1
|
||||||
|
|
||||||
var maxLifeTime uint = 600
|
var maxLifeTime uint = 600
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
description string
|
description string
|
||||||
@@ -338,6 +344,166 @@ func TestPodLifeTime(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with container status CrashLoopBackOff should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"CrashLoopBackOff"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.ContainerStatuses = []v1.ContainerStatus{
|
||||||
|
{
|
||||||
|
State: v1.ContainerState{
|
||||||
|
Waiting: &v1.ContainerStateWaiting{Reason: "CrashLoopBackOff"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with container status CreateContainerConfigError should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"CreateContainerConfigError"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.ContainerStatuses = []v1.ContainerStatus{
|
||||||
|
{
|
||||||
|
State: v1.ContainerState{
|
||||||
|
Waiting: &v1.ContainerStateWaiting{Reason: "CreateContainerConfigError"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with container status ErrImagePull should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"ErrImagePull"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.ContainerStatuses = []v1.ContainerStatus{
|
||||||
|
{
|
||||||
|
State: v1.ContainerState{
|
||||||
|
Waiting: &v1.ContainerStateWaiting{Reason: "ErrImagePull"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with container status CreateContainerError should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"CreateContainerError"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.ContainerStatuses = []v1.ContainerStatus{
|
||||||
|
{
|
||||||
|
State: v1.ContainerState{
|
||||||
|
Waiting: &v1.ContainerStateWaiting{Reason: "CreateContainerError"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with container status InvalidImageName should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"InvalidImageName"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.ContainerStatuses = []v1.ContainerStatus{
|
||||||
|
{
|
||||||
|
State: v1.ContainerState{
|
||||||
|
Waiting: &v1.ContainerStateWaiting{Reason: "InvalidImageName"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with pod status reason NodeLost should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"NodeLost"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.Reason = "NodeLost"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with pod status reason NodeAffinity should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"NodeAffinity"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.Reason = "NodeAffinity"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with pod status reason Shutdown should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"Shutdown"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.Reason = "Shutdown"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with pod status reason UnexpectedAdmissionError should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{"UnexpectedAdmissionError"},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p9},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.Reason = "UnexpectedAdmissionError"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "1 pod with pod status phase v1.PodUnknown should be evicted",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||||
|
States: []string{string(v1.PodUnknown)},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{p16},
|
||||||
|
nodes: []*v1.Node{node1},
|
||||||
|
expectedEvictedPodCount: 1,
|
||||||
|
applyPodsFunc: func(pods []*v1.Pod) {
|
||||||
|
pods[0].Status.Phase = v1.PodUnknown
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "1 pod without ImagePullBackOff States should be ignored",
|
description: "1 pod without ImagePullBackOff States should be ignored",
|
||||||
args: &PodLifeTimeArgs{
|
args: &PodLifeTimeArgs{
|
||||||
|
|||||||
@@ -44,15 +44,29 @@ func ValidatePodLifeTimeArgs(obj runtime.Object) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
podLifeTimeAllowedStates := sets.New(
|
podLifeTimeAllowedStates := sets.New(
|
||||||
|
// Pod Status Phase
|
||||||
string(v1.PodRunning),
|
string(v1.PodRunning),
|
||||||
string(v1.PodPending),
|
string(v1.PodPending),
|
||||||
|
string(v1.PodUnknown),
|
||||||
|
|
||||||
|
// Pod Status Reasons
|
||||||
|
"NodeAffinity",
|
||||||
|
"NodeLost",
|
||||||
|
"Shutdown",
|
||||||
|
"UnexpectedAdmissionError",
|
||||||
|
|
||||||
|
// Container Status Reasons
|
||||||
// Container state reasons: https://github.com/kubernetes/kubernetes/blob/release-1.24/pkg/kubelet/kubelet_pods.go#L76-L79
|
// Container state reasons: https://github.com/kubernetes/kubernetes/blob/release-1.24/pkg/kubelet/kubelet_pods.go#L76-L79
|
||||||
"PodInitializing",
|
"PodInitializing",
|
||||||
"ContainerCreating",
|
"ContainerCreating",
|
||||||
|
|
||||||
// containerStatuses[*].state.waiting.reason: ImagePullBackOff
|
// containerStatuses[*].state.waiting.reason: ImagePullBackOff, etc.
|
||||||
"ImagePullBackOff",
|
"ImagePullBackOff",
|
||||||
|
"CrashLoopBackOff",
|
||||||
|
"CreateContainerConfigError",
|
||||||
|
"ErrImagePull",
|
||||||
|
"CreateContainerError",
|
||||||
|
"InvalidImageName",
|
||||||
)
|
)
|
||||||
|
|
||||||
if !podLifeTimeAllowedStates.HasAll(args.States...) {
|
if !podLifeTimeAllowedStates.HasAll(args.States...) {
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ func TestValidateRemovePodLifeTimeArgs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectError: false,
|
expectError: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "Pod Status Reasons CrashLoopBackOff ",
|
||||||
|
args: &PodLifeTimeArgs{
|
||||||
|
MaxPodLifeTimeSeconds: func(i uint) *uint { return &i }(1),
|
||||||
|
States: []string{"CrashLoopBackOff"},
|
||||||
|
},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "nil MaxPodLifeTimeSeconds arg, expects errors",
|
description: "nil MaxPodLifeTimeSeconds arg, expects errors",
|
||||||
args: &PodLifeTimeArgs{
|
args: &PodLifeTimeArgs{
|
||||||
|
|||||||
Reference in New Issue
Block a user