feat: add annotation to ignore local storage volume during scale down
- this is so that scale down is not blocked on local storage volume - for pods where it is okay to ignore local storage volume Signed-off-by: vadasambar <surajrbanakar@gmail.com> fix: tests failing - there was a problem in the logic Signed-off-by: vadasambar <surajrbanakar@gmail.com> test: add unit test for `IgnoreLocalStorageVolumeKey` Signed-off-by: vadasambar <surajrbanakar@gmail.com> refactor: use `IgnoreLocalStorageVolumeKey` in tests instead of hardcoding the annotation Signed-off-by: vadasambar <surajrbanakar@gmail.com> fix: wording for test name - `pod with EmptyDir but IgnoreLocalStorageVolumeKey annotation` -> `pod with EmptyDir and IgnoreLocalStorageVolumeKey annotation` Signed-off-by: vadasambar <surajrbanakar@gmail.com> fix: simulator drain tests failing - set local storage vol name (required) Signed-off-by: vadasambar <surajrbanakar@gmail.com> refactor: add support for multiple vals in `safe-to-evict-local-volume` annotation - add more unit tests Signed-off-by: vadasambar <surajrbanakar@gmail.com> refactor: rename ignore local vol key `safe-to-evict-local-volume` -> `safe-to-evict-local-volumes` - abtract code to process annotation into a separate fn - shorten name for test cases Signed-off-by: vadasambar <surajrbanakar@gmail.com> docs: update FAQ with info about `safe-to-evict-local-volumes` annotation Signed-off-by: vadasambar <surajrbanakar@gmail.com> docs: add the FAQ for `safe-to-evict-local-volumes` annotation Signed-off-by: vadasambar <surajrbanakar@gmail.com> docs: fix formatting for `safe-to-evict-local-volumes` in FAQ Signed-off-by: vadasambar <surajrbanakar@gmail.com> docs: format the `safe-to-evict-local-volumes` as a bullet Signed-off-by: vadasambar <surajrbanakar@gmail.com> docs: fix `Unless` -> `unless` to make it consistent with other lines Signed-off-by: vadasambar <surajrbanakar@gmail.com> test: add an extra test for mismatching local vol value in annotation Signed-off-by: vadasambar <surajrbanakar@gmail.com> docs: make the wording clearer - for `safe-to-evict-local-volumes` annotation Signed-off-by: vadasambar <surajrbanakar@gmail.com>
This commit is contained in:
parent
63b334f81a
commit
b663f138a4
|
|
@ -89,6 +89,11 @@ Cluster Autoscaler decreases the size of the cluster when some nodes are consist
|
||||||
* don't have a [pod disruption budget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#how-disruption-budgets-work) set or their PDB is too restrictive (since CA 0.6).
|
* don't have a [pod disruption budget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#how-disruption-budgets-work) set or their PDB is too restrictive (since CA 0.6).
|
||||||
* Pods that are not backed by a controller object (so not created by deployment, replica set, job, stateful set etc). *
|
* Pods that are not backed by a controller object (so not created by deployment, replica set, job, stateful set etc). *
|
||||||
* Pods with local storage. *
|
* Pods with local storage. *
|
||||||
|
- unless the pod has the following annotation set:
|
||||||
|
```
|
||||||
|
"cluster-autoscaler.kubernetes.io/safe-to-evict-local-volumes": "volume-1,volume-2,.."
|
||||||
|
```
|
||||||
|
and all of the pod's local volumes are listed in the annotation value.
|
||||||
* Pods that cannot be moved elsewhere due to various constraints (lack of resources, non-matching node selectors or affinity,
|
* Pods that cannot be moved elsewhere due to various constraints (lack of resources, non-matching node selectors or affinity,
|
||||||
matching anti-affinity, etc)
|
matching anti-affinity, etc)
|
||||||
* Pods that have the following annotation set:
|
* Pods that have the following annotation set:
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ func TestGetPodsToMove(t *testing.T) {
|
||||||
Spec: apiv1.PodSpec{
|
Spec: apiv1.PodSpec{
|
||||||
Volumes: []apiv1.Volume{
|
Volumes: []apiv1.Volume{
|
||||||
{
|
{
|
||||||
|
Name: "empty-vol",
|
||||||
VolumeSource: apiv1.VolumeSource{
|
VolumeSource: apiv1.VolumeSource{
|
||||||
EmptyDir: &apiv1.EmptyDirVolumeSource{},
|
EmptyDir: &apiv1.EmptyDirVolumeSource{},
|
||||||
},
|
},
|
||||||
|
|
@ -136,6 +137,7 @@ func TestGetPodsToMove(t *testing.T) {
|
||||||
Spec: apiv1.PodSpec{
|
Spec: apiv1.PodSpec{
|
||||||
Volumes: []apiv1.Volume{
|
Volumes: []apiv1.Volume{
|
||||||
{
|
{
|
||||||
|
Name: "my-repo",
|
||||||
VolumeSource: apiv1.VolumeSource{
|
VolumeSource: apiv1.VolumeSource{
|
||||||
GitRepo: &apiv1.GitRepoVolumeSource{
|
GitRepo: &apiv1.GitRepoVolumeSource{
|
||||||
Repository: "my-repo",
|
Repository: "my-repo",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package drain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
|
@ -38,6 +39,8 @@ const (
|
||||||
// PodSafeToEvictKey - annotation that ignores constraints to evict a pod like not being replicated, being on
|
// PodSafeToEvictKey - annotation that ignores constraints to evict a pod like not being replicated, being on
|
||||||
// kube-system namespace or having a local storage.
|
// kube-system namespace or having a local storage.
|
||||||
PodSafeToEvictKey = "cluster-autoscaler.kubernetes.io/safe-to-evict"
|
PodSafeToEvictKey = "cluster-autoscaler.kubernetes.io/safe-to-evict"
|
||||||
|
// SafeToEvictLocalVolumesKey - annotation that ignores (doesn't block on) a local storage volume during node scale down
|
||||||
|
SafeToEvictLocalVolumesKey = "cluster-autoscaler.kubernetes.io/safe-to-evict-local-volumes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockingPod represents a pod which is blocking the scale down of a node.
|
// BlockingPod represents a pod which is blocking the scale down of a node.
|
||||||
|
|
@ -219,7 +222,7 @@ func GetPodsForDeletionOnNodeDrain(
|
||||||
return []*apiv1.Pod{}, []*apiv1.Pod{}, &BlockingPod{Pod: pod, Reason: UnmovableKubeSystemPod}, fmt.Errorf("non-daemonset, non-mirrored, non-pdb-assigned kube-system pod present: %s", pod.Name)
|
return []*apiv1.Pod{}, []*apiv1.Pod{}, &BlockingPod{Pod: pod, Reason: UnmovableKubeSystemPod}, fmt.Errorf("non-daemonset, non-mirrored, non-pdb-assigned kube-system pod present: %s", pod.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if HasLocalStorage(pod) && skipNodesWithLocalStorage {
|
if HasBlockingLocalStorage(pod) && skipNodesWithLocalStorage {
|
||||||
return []*apiv1.Pod{}, []*apiv1.Pod{}, &BlockingPod{Pod: pod, Reason: LocalStorageRequested}, fmt.Errorf("pod with local storage present: %s", pod.Name)
|
return []*apiv1.Pod{}, []*apiv1.Pod{}, &BlockingPod{Pod: pod, Reason: LocalStorageRequested}, fmt.Errorf("pod with local storage present: %s", pod.Name)
|
||||||
}
|
}
|
||||||
if hasNotSafeToEvictAnnotation(pod) {
|
if hasNotSafeToEvictAnnotation(pod) {
|
||||||
|
|
@ -250,16 +253,30 @@ func isPodTerminal(pod *apiv1.Pod) bool {
|
||||||
return pod.Status.Phase == apiv1.PodFailed
|
return pod.Status.Phase == apiv1.PodFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasLocalStorage returns true if pod has any local storage.
|
// HasBlockingLocalStorage returns true if pod has any local storage
|
||||||
func HasLocalStorage(pod *apiv1.Pod) bool {
|
// without pod annotation `<SafeToEvictLocalVolumeKey>: <volume-name-1>,<volume-name-2>...`
|
||||||
|
func HasBlockingLocalStorage(pod *apiv1.Pod) bool {
|
||||||
|
isNonBlocking := getNonBlockingVolumes(pod)
|
||||||
for _, volume := range pod.Spec.Volumes {
|
for _, volume := range pod.Spec.Volumes {
|
||||||
if isLocalVolume(&volume) {
|
if isLocalVolume(&volume) && !isNonBlocking[volume.Name] {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNonBlockingVolumes(pod *apiv1.Pod) map[string]bool {
|
||||||
|
isNonBlocking := map[string]bool{}
|
||||||
|
annotationVal := pod.GetAnnotations()[SafeToEvictLocalVolumesKey]
|
||||||
|
if annotationVal != "" {
|
||||||
|
vols := strings.Split(annotationVal, ",")
|
||||||
|
for _, v := range vols {
|
||||||
|
isNonBlocking[v] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isNonBlocking
|
||||||
|
}
|
||||||
|
|
||||||
func isLocalVolume(volume *apiv1.Volume) bool {
|
func isLocalVolume(volume *apiv1.Volume) bool {
|
||||||
return volume.HostPath != nil || volume.EmptyDir != nil
|
return volume.HostPath != nil || volume.EmptyDir != nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,178 @@ func TestDrain(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictVolumeSingleVal := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: "scratch",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictLocalVolumeSingleValEmpty := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictLocalVolumeSingleValNonMatching := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: "scratch-2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch-1",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictLocalVolumeMultiValAllMatching := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: "scratch-1,scratch-2,scratch-3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch-1",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-2",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-3",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictLocalVolumeMultiValNonMatching := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: "scratch-1,scratch-2,scratch-5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch-1",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-2",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-3",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictLocalVolumeMultiValSomeMatchingVals := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: "scratch-1,scratch-2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch-1",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-2",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-3",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyDirSafeToEvictLocalVolumeMultiValEmpty := &apiv1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
OwnerReferences: GenerateOwnerReferences(rc.Name, "ReplicationController", "core/v1", ""),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
SafeToEvictLocalVolumesKey: ",",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apiv1.PodSpec{
|
||||||
|
NodeName: "node",
|
||||||
|
Volumes: []apiv1.Volume{
|
||||||
|
{
|
||||||
|
Name: "scratch-1",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-2",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "scratch-3",
|
||||||
|
VolumeSource: apiv1.VolumeSource{EmptyDir: &apiv1.EmptyDirVolumeSource{Medium: ""}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
terminalPod := &apiv1.Pod{
|
terminalPod := &apiv1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
|
|
@ -489,6 +661,76 @@ func TestDrain(t *testing.T) {
|
||||||
expectBlockingPod: &BlockingPod{Pod: emptydirPod, Reason: LocalStorageRequested},
|
expectBlockingPod: &BlockingPod{Pod: emptydirPod, Reason: LocalStorageRequested},
|
||||||
expectDaemonSetPods: []*apiv1.Pod{},
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and SafeToEvictLocalVolumesKey annotation",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictVolumeSingleVal},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: false,
|
||||||
|
expectPods: []*apiv1.Pod{emptyDirSafeToEvictVolumeSingleVal},
|
||||||
|
expectBlockingPod: &BlockingPod{},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and empty value for SafeToEvictLocalVolumesKey annotation",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeSingleValEmpty},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: true,
|
||||||
|
expectPods: []*apiv1.Pod{},
|
||||||
|
expectBlockingPod: &BlockingPod{Pod: emptyDirSafeToEvictLocalVolumeSingleValEmpty, Reason: LocalStorageRequested},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and non-matching value for SafeToEvictLocalVolumesKey annotation",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeSingleValNonMatching},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: true,
|
||||||
|
expectPods: []*apiv1.Pod{},
|
||||||
|
expectBlockingPod: &BlockingPod{Pod: emptyDirSafeToEvictLocalVolumeSingleValNonMatching, Reason: LocalStorageRequested},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and SafeToEvictLocalVolumesKey annotation with matching values",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeMultiValAllMatching},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: false,
|
||||||
|
expectPods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeMultiValAllMatching},
|
||||||
|
expectBlockingPod: &BlockingPod{},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and SafeToEvictLocalVolumesKey annotation with non-matching values",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeMultiValNonMatching},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: true,
|
||||||
|
expectPods: []*apiv1.Pod{},
|
||||||
|
expectBlockingPod: &BlockingPod{Pod: emptyDirSafeToEvictLocalVolumeMultiValNonMatching, Reason: LocalStorageRequested},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and SafeToEvictLocalVolumesKey annotation with some matching values",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeMultiValSomeMatchingVals},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: true,
|
||||||
|
expectPods: []*apiv1.Pod{},
|
||||||
|
expectBlockingPod: &BlockingPod{Pod: emptyDirSafeToEvictLocalVolumeMultiValSomeMatchingVals, Reason: LocalStorageRequested},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "pod with EmptyDir and SafeToEvictLocalVolumesKey annotation empty values",
|
||||||
|
pods: []*apiv1.Pod{emptyDirSafeToEvictLocalVolumeMultiValEmpty},
|
||||||
|
pdbs: []*policyv1.PodDisruptionBudget{},
|
||||||
|
rcs: []*apiv1.ReplicationController{&rc},
|
||||||
|
expectFatal: true,
|
||||||
|
expectPods: []*apiv1.Pod{},
|
||||||
|
expectBlockingPod: &BlockingPod{Pod: emptyDirSafeToEvictLocalVolumeMultiValEmpty, Reason: LocalStorageRequested},
|
||||||
|
expectDaemonSetPods: []*apiv1.Pod{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "failed pod",
|
description: "failed pod",
|
||||||
pods: []*apiv1.Pod{failedPod},
|
pods: []*apiv1.Pod{failedPod},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue