@@ -26,6 +26,7 @@ import (
26
26
27
27
v1 "k8s.io/api/core/v1"
28
28
policy "k8s.io/api/policy/v1beta1"
29
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
29
30
"k8s.io/apimachinery/pkg/api/resource"
30
31
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31
32
"k8s.io/apimachinery/pkg/runtime"
@@ -1023,6 +1024,93 @@ func TestNominatedNodeCleanUp(t *testing.T) {
1023
1024
}
1024
1025
}
1025
1026
1027
+ func TestNominatedNodeCleanUpUponNodeDeletion (t * testing.T ) {
1028
+ // Initialize scheduler.
1029
+ testCtx := initTest (t , "preemption" )
1030
+ defer testutils .CleanupTest (t , testCtx )
1031
+
1032
+ cs := testCtx .ClientSet
1033
+ defer cleanupPodsInNamespace (cs , t , testCtx .NS .Name )
1034
+
1035
+ // Create a node with some resources and a label.
1036
+ nodeRes := & v1.ResourceList {
1037
+ v1 .ResourcePods : * resource .NewQuantity (32 , resource .DecimalSI ),
1038
+ v1 .ResourceCPU : * resource .NewMilliQuantity (100 , resource .DecimalSI ),
1039
+ v1 .ResourceMemory : * resource .NewQuantity (100 , resource .DecimalSI ),
1040
+ }
1041
+ nodeNames := []string {"node1" , "node2" }
1042
+ for _ , nodeName := range nodeNames {
1043
+ _ , err := createNode (testCtx .ClientSet , nodeName , nodeRes )
1044
+ if err != nil {
1045
+ t .Fatalf ("Error creating nodes: %v" , err )
1046
+ }
1047
+ }
1048
+
1049
+ // Fill the cluster with one high-priority and one low-priority Pod.
1050
+ highPriPod , err := createPausePod (cs , mkPriorityPodWithGrace (testCtx , "high-pod" , highPriority , 60 ))
1051
+ if err != nil {
1052
+ t .Fatalf ("Error creating high-priority pod: %v" , err )
1053
+ }
1054
+ // Make sure the pod is scheduled.
1055
+ if err := testutils .WaitForPodToSchedule (cs , highPriPod ); err != nil {
1056
+ t .Fatalf ("Pod %v/%v didn't get scheduled: %v" , highPriPod .Namespace , highPriPod .Name , err )
1057
+ }
1058
+
1059
+ lowPriPod , err := createPausePod (cs , mkPriorityPodWithGrace (testCtx , "low-pod" , lowPriority , 60 ))
1060
+ if err != nil {
1061
+ t .Fatalf ("Error creating low-priority pod: %v" , err )
1062
+ }
1063
+ // Make sure the pod is scheduled.
1064
+ if err := testutils .WaitForPodToSchedule (cs , lowPriPod ); err != nil {
1065
+ t .Fatalf ("Pod %v/%v didn't get scheduled: %v" , lowPriPod .Namespace , lowPriPod .Name , err )
1066
+ }
1067
+
1068
+ // Create a medium-priority Pod.
1069
+ medPriPod , err := createPausePod (cs , mkPriorityPodWithGrace (testCtx , "med-pod" , mediumPriority , 60 ))
1070
+ if err != nil {
1071
+ t .Fatalf ("Error creating med-priority pod: %v" , err )
1072
+ }
1073
+ // Check its nominatedNodeName field is set properly.
1074
+ if err := waitForNominatedNodeName (cs , medPriPod ); err != nil {
1075
+ t .Fatalf ("NominatedNodeName was not set for pod %v/%v: %v" , medPriPod .Namespace , medPriPod .Name , err )
1076
+ }
1077
+
1078
+ // Get the live version of low and med pods.
1079
+ lowPriPod , _ = getPod (cs , lowPriPod .Name , lowPriPod .Namespace )
1080
+ medPriPod , _ = getPod (cs , medPriPod .Name , medPriPod .Namespace )
1081
+
1082
+ want , got := lowPriPod .Spec .NodeName , medPriPod .Status .NominatedNodeName
1083
+ if want != got {
1084
+ t .Fatalf ("Expect med-priority's nominatedNodeName to be %v, but got %v." , want , got )
1085
+ }
1086
+
1087
+ // Delete the node where med-priority pod is nominated to.
1088
+ cs .CoreV1 ().Nodes ().Delete (context .TODO (), got , metav1.DeleteOptions {})
1089
+ if err := wait .Poll (200 * time .Millisecond , wait .ForeverTestTimeout , func () (bool , error ) {
1090
+ _ , err := cs .CoreV1 ().Nodes ().Get (context .TODO (), got , metav1.GetOptions {})
1091
+ if apierrors .IsNotFound (err ) {
1092
+ return true , nil
1093
+ }
1094
+ return false , err
1095
+ }); err != nil {
1096
+ t .Fatalf ("Node %v cannot be deleted: %v." , got , err )
1097
+ }
1098
+
1099
+ // Finally verify if med-priority pod's nominatedNodeName gets cleared.
1100
+ if err := wait .Poll (200 * time .Millisecond , wait .ForeverTestTimeout , func () (bool , error ) {
1101
+ pod , err := cs .CoreV1 ().Pods (medPriPod .Namespace ).Get (context .TODO (), medPriPod .Name , metav1.GetOptions {})
1102
+ if err != nil {
1103
+ t .Errorf ("Error getting the medium priority pod info: %v" , err )
1104
+ }
1105
+ if len (pod .Status .NominatedNodeName ) == 0 {
1106
+ return true , nil
1107
+ }
1108
+ return false , err
1109
+ }); err != nil {
1110
+ t .Errorf ("The nominated node name of the medium priority pod was not cleared: %v" , err )
1111
+ }
1112
+ }
1113
+
1026
1114
func mkMinAvailablePDB (name , namespace string , uid types.UID , minAvailable int , matchLabels map [string ]string ) * policy.PodDisruptionBudget {
1027
1115
intMinAvailable := intstr .FromInt (minAvailable )
1028
1116
return & policy.PodDisruptionBudget {
0 commit comments