@@ -39,6 +39,7 @@ import (
39
39
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
40
40
e2eruntimeclass "k8s.io/kubernetes/test/e2e/framework/node/runtimeclass"
41
41
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
42
+ e2epv "k8s.io/kubernetes/test/e2e/framework/pv"
42
43
e2erc "k8s.io/kubernetes/test/e2e/framework/rc"
43
44
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
44
45
testutils "k8s.io/kubernetes/test/utils"
@@ -857,6 +858,78 @@ var _ = SIGDescribe("SchedulerPredicates", framework.WithSerial(), func() {
857
858
ginkgo .By ("Expect all pods are scheduled and running" )
858
859
framework .ExpectNoError (e2epod .WaitForPodsRunning (ctx , cs , ns , replicas , time .Minute ))
859
860
})
861
+
862
+ // Regression test for an extended scenario for https://issues.k8s.io/123465
863
+ ginkgo .It ("when PVC has node-affinity to non-existent/illegal nodes, the pod should be scheduled normally if suitable nodes exist" , func (ctx context.Context ) {
864
+ nodeName := GetNodeThatCanRunPod (ctx , f )
865
+ nonExistentNodeName1 := string (uuid .NewUUID ())
866
+ nonExistentNodeName2 := string (uuid .NewUUID ())
867
+ hostLabel := "kubernetes.io/hostname"
868
+ localPath := "/tmp"
869
+ podName := "bind-pv-with-non-existent-nodes"
870
+ pvcName := "pvc-" + string (uuid .NewUUID ())
871
+ _ , pvc , err := e2epv .CreatePVPVC (ctx , cs , f .Timeouts , e2epv.PersistentVolumeConfig {
872
+ PVSource : v1.PersistentVolumeSource {
873
+ Local : & v1.LocalVolumeSource {
874
+ Path : localPath ,
875
+ },
876
+ },
877
+ Prebind : & v1.PersistentVolumeClaim {
878
+ ObjectMeta : metav1.ObjectMeta {Name : pvcName , Namespace : ns },
879
+ },
880
+ NodeAffinity : & v1.VolumeNodeAffinity {
881
+ Required : & v1.NodeSelector {
882
+ NodeSelectorTerms : []v1.NodeSelectorTerm {
883
+ {
884
+ MatchExpressions : []v1.NodeSelectorRequirement {
885
+ {
886
+ Key : hostLabel ,
887
+ Operator : v1 .NodeSelectorOpIn ,
888
+ // add non-existent nodes to the list
889
+ Values : []string {nodeName , nonExistentNodeName1 , nonExistentNodeName2 },
890
+ },
891
+ },
892
+ },
893
+ },
894
+ },
895
+ },
896
+ }, e2epv.PersistentVolumeClaimConfig {
897
+ Name : pvcName ,
898
+ }, ns , true )
899
+ framework .ExpectNoError (err )
900
+ bindPvPod := & v1.Pod {
901
+ ObjectMeta : metav1.ObjectMeta {
902
+ Name : podName ,
903
+ },
904
+ Spec : v1.PodSpec {
905
+ Containers : []v1.Container {
906
+ {
907
+ Name : "pause" ,
908
+ Image : imageutils .GetE2EImage (imageutils .Pause ),
909
+ VolumeMounts : []v1.VolumeMount {
910
+ {
911
+ Name : "data" ,
912
+ MountPath : "/tmp" ,
913
+ },
914
+ },
915
+ },
916
+ },
917
+ Volumes : []v1.Volume {
918
+ {
919
+ Name : "data" ,
920
+ VolumeSource : v1.VolumeSource {
921
+ PersistentVolumeClaim : & v1.PersistentVolumeClaimVolumeSource {
922
+ ClaimName : pvc .Name ,
923
+ },
924
+ },
925
+ },
926
+ },
927
+ },
928
+ }
929
+ _ , err = f .ClientSet .CoreV1 ().Pods (ns ).Create (ctx , bindPvPod , metav1.CreateOptions {})
930
+ framework .ExpectNoError (err )
931
+ framework .ExpectNoError (e2epod .WaitForPodNotPending (ctx , f .ClientSet , ns , podName ))
932
+ })
860
933
})
861
934
862
935
func patchPod (cs clientset.Interface , old , new * v1.Pod ) (* v1.Pod , error ) {
0 commit comments