@@ -23,6 +23,7 @@ import (
23
23
24
24
"k8s.io/api/core/v1"
25
25
apierrors "k8s.io/apimachinery/pkg/api/errors"
26
+ apierrs "k8s.io/apimachinery/pkg/api/errors"
26
27
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
28
"k8s.io/apimachinery/pkg/fields"
28
29
utilerrors "k8s.io/apimachinery/pkg/util/errors"
@@ -60,7 +61,7 @@ var initVolSources = map[string]func() volSource{
60
61
"hostPath" : initHostpath ,
61
62
"hostPathSymlink" : initHostpathSymlink ,
62
63
"emptyDir" : initEmptydir ,
63
- "gcePD" : initGCEPD ,
64
+ "gcePDPVC" : initGCEPD ,
64
65
"gcePDPartitioned" : initGCEPDPartition ,
65
66
"nfs" : initNFS ,
66
67
"nfsPVC" : initNFSPVC ,
@@ -307,6 +308,17 @@ var _ = utils.SIGDescribe("Subpath", func() {
307
308
308
309
testPodContainerRestart (f , pod , filePathInVolume , filePathInSubpath )
309
310
})
311
+
312
+ It ("should unmount if pod is gracefully deleted while kubelet is down [Disruptive][Slow]" , func () {
313
+ testSubpathReconstruction (f , pod , false )
314
+ })
315
+
316
+ It ("should unmount if pod is force deleted while kubelet is down [Disruptive][Slow]" , func () {
317
+ if curVolType == "hostPath" || curVolType == "hostPathSymlink" {
318
+ framework .Skipf ("%s volume type does not support reconstruction, skipping" , curVolType )
319
+ }
320
+ testSubpathReconstruction (f , pod , true )
321
+ })
310
322
})
311
323
}
312
324
@@ -549,6 +561,85 @@ func testPodContainerRestart(f *framework.Framework, pod *v1.Pod, fileInVolume,
549
561
Expect (strings .TrimSpace (out )).To (BeEquivalentTo ("test-after" ))
550
562
}
551
563
564
+ func testSubpathReconstruction (f * framework.Framework , pod * v1.Pod , forceDelete bool ) {
565
+ // This is mostly copied from TestVolumeUnmountsFromDeletedPodWithForceOption()
566
+
567
+ // Change to busybox
568
+ pod .Spec .Containers [0 ].Image = "busybox"
569
+ pod .Spec .Containers [0 ].Command = []string {"/bin/sh" , "-ec" , "sleep 100000" }
570
+ pod .Spec .Containers [1 ].Image = "busybox"
571
+ pod .Spec .Containers [1 ].Command = []string {"/bin/sh" , "-ec" , "sleep 100000" }
572
+
573
+ By (fmt .Sprintf ("Creating pod %s" , pod .Name ))
574
+ pod , err := f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).Create (pod )
575
+ Expect (err ).ToNot (HaveOccurred ())
576
+
577
+ err = framework .WaitTimeoutForPodRunningInNamespace (f .ClientSet , pod .Name , pod .Namespace , time .Minute )
578
+ Expect (err ).ToNot (HaveOccurred ())
579
+
580
+ pod , err = f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).Get (pod .Name , metav1.GetOptions {})
581
+ Expect (err ).ToNot (HaveOccurred ())
582
+
583
+ nodeIP , err := framework .GetHostExternalAddress (f .ClientSet , pod )
584
+ Expect (err ).NotTo (HaveOccurred ())
585
+ nodeIP = nodeIP + ":22"
586
+
587
+ By ("Expecting the volume mount to be found." )
588
+ result , err := framework .SSH (fmt .Sprintf ("mount | grep %s | grep -v volume-subpaths" , pod .UID ), nodeIP , framework .TestContext .Provider )
589
+ framework .LogSSHResult (result )
590
+ Expect (err ).NotTo (HaveOccurred (), "Encountered SSH error." )
591
+ Expect (result .Code ).To (BeZero (), fmt .Sprintf ("Expected grep exit code of 0, got %d" , result .Code ))
592
+
593
+ By ("Expecting the subpath volume mount to be found." )
594
+ result , err = framework .SSH (fmt .Sprintf ("cat /proc/self/mountinfo | grep volume-subpaths | grep %s" , pod .UID ), nodeIP , framework .TestContext .Provider )
595
+ framework .LogSSHResult (result )
596
+ Expect (err ).NotTo (HaveOccurred (), "Encountered SSH error." )
597
+ Expect (result .Code ).To (BeZero (), fmt .Sprintf ("Expected grep exit code of 0, got %d" , result .Code ))
598
+
599
+ By ("Stopping the kubelet." )
600
+ utils .KubeletCommand (utils .KStop , f .ClientSet , pod )
601
+ defer func () {
602
+ if err != nil {
603
+ utils .KubeletCommand (utils .KStart , f .ClientSet , pod )
604
+ }
605
+ }()
606
+
607
+ By (fmt .Sprintf ("Deleting Pod %q" , pod .Name ))
608
+ if forceDelete {
609
+ err = f .ClientSet .CoreV1 ().Pods (pod .Namespace ).Delete (pod .Name , metav1 .NewDeleteOptions (0 ))
610
+ } else {
611
+ err = f .ClientSet .CoreV1 ().Pods (pod .Namespace ).Delete (pod .Name , & metav1.DeleteOptions {})
612
+ }
613
+ Expect (err ).NotTo (HaveOccurred ())
614
+
615
+ By ("Starting the kubelet and waiting for pod to delete." )
616
+ utils .KubeletCommand (utils .KStart , f .ClientSet , pod )
617
+ err = f .WaitForPodTerminated (pod .Name , "" )
618
+ if ! apierrs .IsNotFound (err ) && err != nil {
619
+ Expect (err ).NotTo (HaveOccurred (), "Expected pod to terminate." )
620
+ }
621
+
622
+ if forceDelete {
623
+ // With forceDelete, since pods are immediately deleted from API server, there is no way to be sure when volumes are torn down
624
+ // so wait some time to finish
625
+ time .Sleep (30 * time .Second )
626
+ }
627
+
628
+ By ("Expecting the volume mount not to be found." )
629
+ result , err = framework .SSH (fmt .Sprintf ("mount | grep %s | grep -v volume-subpaths" , pod .UID ), nodeIP , framework .TestContext .Provider )
630
+ framework .LogSSHResult (result )
631
+ Expect (err ).NotTo (HaveOccurred (), "Encountered SSH error." )
632
+ Expect (result .Stdout ).To (BeEmpty (), "Expected grep stdout to be empty (i.e. no mount found)." )
633
+ framework .Logf ("Volume unmounted on node %s" , pod .Spec .NodeName )
634
+
635
+ By ("Expecting the subpath volume mount not to be found." )
636
+ result , err = framework .SSH (fmt .Sprintf ("cat /proc/self/mountinfo | grep volume-subpaths | grep %s" , pod .UID ), nodeIP , framework .TestContext .Provider )
637
+ framework .LogSSHResult (result )
638
+ Expect (err ).NotTo (HaveOccurred (), "Encountered SSH error." )
639
+ Expect (result .Stdout ).To (BeEmpty (), "Expected grep stdout to be empty (i.e. no subpath mount found)." )
640
+ framework .Logf ("Subpath volume unmounted on node %s" , pod .Spec .NodeName )
641
+ }
642
+
552
643
func podContainerExec (pod * v1.Pod , containerIndex int , bashExec string ) (string , error ) {
553
644
return framework .RunKubectl ("exec" , fmt .Sprintf ("--namespace=%s" , pod .Namespace ), pod .Name , "--container" , pod .Spec .Containers [containerIndex ].Name , "--" , "/bin/sh" , "-c" , bashExec )
554
645
}
0 commit comments