Commit 9a1a9cbe authored by Hemant Kumar's avatar Hemant Kumar

detach the volume when pod is terminated

Make sure volume is detached when pod is terminated because of any reason and not deleted from api server.
parent 7408f6b3
...@@ -569,8 +569,7 @@ func StartControllers(controllers map[string]InitFunc, s *options.CMServer, root ...@@ -569,8 +569,7 @@ func StartControllers(controllers map[string]InitFunc, s *options.CMServer, root
cloud, cloud,
ProbeAttachableVolumePlugins(s.VolumeConfiguration), ProbeAttachableVolumePlugins(s.VolumeConfiguration),
s.DisableAttachDetachReconcilerSync, s.DisableAttachDetachReconcilerSync,
s.ReconcilerSyncLoopPeriod.Duration, s.ReconcilerSyncLoopPeriod.Duration)
)
if attachDetachControllerErr != nil { if attachDetachControllerErr != nil {
return fmt.Errorf("failed to start attach/detach controller: %v", attachDetachControllerErr) return fmt.Errorf("failed to start attach/detach controller: %v", attachDetachControllerErr)
} }
......
...@@ -208,6 +208,7 @@ CPU_CFS_QUOTA=${CPU_CFS_QUOTA:-true} ...@@ -208,6 +208,7 @@ CPU_CFS_QUOTA=${CPU_CFS_QUOTA:-true}
ENABLE_HOSTPATH_PROVISIONER=${ENABLE_HOSTPATH_PROVISIONER:-"false"} ENABLE_HOSTPATH_PROVISIONER=${ENABLE_HOSTPATH_PROVISIONER:-"false"}
CLAIM_BINDER_SYNC_PERIOD=${CLAIM_BINDER_SYNC_PERIOD:-"15s"} # current k8s default CLAIM_BINDER_SYNC_PERIOD=${CLAIM_BINDER_SYNC_PERIOD:-"15s"} # current k8s default
ENABLE_CONTROLLER_ATTACH_DETACH=${ENABLE_CONTROLLER_ATTACH_DETACH:-"true"} # current default ENABLE_CONTROLLER_ATTACH_DETACH=${ENABLE_CONTROLLER_ATTACH_DETACH:-"true"} # current default
KEEP_TERMINATED_POD_VOLUMES=${KEEP_TERMINATED_POD_VOLUMES:-"true"}
# This is the default dir and filename where the apiserver will generate a self-signed cert # This is the default dir and filename where the apiserver will generate a self-signed cert
# which should be able to be used as the CA to verify itself # which should be able to be used as the CA to verify itself
CERT_DIR=${CERT_DIR:-"/var/run/kubernetes"} CERT_DIR=${CERT_DIR:-"/var/run/kubernetes"}
...@@ -638,7 +639,7 @@ function start_kubelet { ...@@ -638,7 +639,7 @@ function start_kubelet {
--enable-controller-attach-detach="${ENABLE_CONTROLLER_ATTACH_DETACH}" \ --enable-controller-attach-detach="${ENABLE_CONTROLLER_ATTACH_DETACH}" \
--cgroups-per-qos=${CGROUPS_PER_QOS} \ --cgroups-per-qos=${CGROUPS_PER_QOS} \
--cgroup-driver=${CGROUP_DRIVER} \ --cgroup-driver=${CGROUP_DRIVER} \
--keep-terminated-pod-volumes=true \ --keep-terminated-pod-volumes=${KEEP_TERMINATED_POD_VOLUMES} \
--eviction-hard=${EVICTION_HARD} \ --eviction-hard=${EVICTION_HARD} \
--eviction-soft=${EVICTION_SOFT} \ --eviction-soft=${EVICTION_SOFT} \
--eviction-pressure-transition-period=${EVICTION_PRESSURE_TRANSITION_PERIOD} \ --eviction-pressure-transition-period=${EVICTION_PRESSURE_TRANSITION_PERIOD} \
......
...@@ -385,8 +385,13 @@ func (adc *attachDetachController) podAdd(obj interface{}) { ...@@ -385,8 +385,13 @@ func (adc *attachDetachController) podAdd(obj interface{}) {
return return
} }
util.ProcessPodVolumes(pod, true, /* addVolumes */ if volumehelper.IsPodTerminated(pod, pod.Status) {
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister) util.ProcessPodVolumes(pod, false, /* addVolumes */
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
} else {
util.ProcessPodVolumes(pod, true, /* addVolumes */
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
}
} }
// GetDesiredStateOfWorld returns desired state of world associated with controller // GetDesiredStateOfWorld returns desired state of world associated with controller
...@@ -395,8 +400,23 @@ func (adc *attachDetachController) GetDesiredStateOfWorld() cache.DesiredStateOf ...@@ -395,8 +400,23 @@ func (adc *attachDetachController) GetDesiredStateOfWorld() cache.DesiredStateOf
} }
func (adc *attachDetachController) podUpdate(oldObj, newObj interface{}) { func (adc *attachDetachController) podUpdate(oldObj, newObj interface{}) {
// The flow for update is the same as add. pod, ok := newObj.(*v1.Pod)
adc.podAdd(newObj) if pod == nil || !ok {
return
}
if pod.Spec.NodeName == "" {
// Ignore pods without NodeName, indicating they are not scheduled.
return
}
addPodFlag := true
if volumehelper.IsPodTerminated(pod, pod.Status) {
addPodFlag = false
}
util.ProcessPodVolumes(pod, addPodFlag, /* addVolumes */
adc.desiredStateOfWorld, &adc.volumePluginMgr, adc.pvcLister, adc.pvLister)
} }
func (adc *attachDetachController) podDelete(obj interface{}) { func (adc *attachDetachController) podDelete(obj interface{}) {
......
...@@ -213,6 +213,7 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2 ...@@ -213,6 +213,7 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2
plugins, plugins,
false, false,
time.Second*1) time.Second*1)
if err != nil { if err != nil {
t.Fatalf("Run failed with error. Expected: <no error> Actual: <%v>", err) t.Fatalf("Run failed with error. Expected: <no error> Actual: <%v>", err)
} }
......
...@@ -127,11 +127,13 @@ func (dswp *desiredStateOfWorldPopulator) findAndRemoveDeletedPods() { ...@@ -127,11 +127,13 @@ func (dswp *desiredStateOfWorldPopulator) findAndRemoveDeletedPods() {
glog.Errorf("podLister Get failed for pod %q (UID %q) with %v", dswPodKey, dswPodUID, err) glog.Errorf("podLister Get failed for pod %q (UID %q) with %v", dswPodKey, dswPodUID, err)
continue continue
default: default:
informerPodUID := volumehelper.GetUniquePodName(informerPod) if !volumehelper.IsPodTerminated(informerPod, informerPod.Status) {
// Check whether the unique identifier of the pod from dsw matches the one retrieved from pod informer informerPodUID := volumehelper.GetUniquePodName(informerPod)
if informerPodUID == dswPodUID { // Check whether the unique identifier of the pod from dsw matches the one retrieved from pod informer
glog.V(10).Infof("Verified pod %q (UID %q) from dsw exists in pod informer.", dswPodKey, dswPodUID) if informerPodUID == dswPodUID {
continue glog.V(10).Infof("Verified pod %q (UID %q) from dsw exists in pod informer.", dswPodKey, dswPodUID)
continue
}
} }
} }
......
...@@ -149,6 +149,77 @@ func TestPodDeletionWithDswp(t *testing.T) { ...@@ -149,6 +149,77 @@ func TestPodDeletionWithDswp(t *testing.T) {
close(stopCh) close(stopCh)
} }
func TestPodUpdateWithWithADC(t *testing.T) {
_, server := framework.RunAMaster(nil)
defer server.Close()
namespaceName := "test-pod-update"
node := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node-sandbox",
Annotations: map[string]string{
volumehelper.ControllerManagedAttachAnnotation: "true",
},
},
}
ns := framework.CreateTestingNamespace(namespaceName, server, t)
defer framework.DeleteTestingNamespace(ns, server, t)
testClient, ctrl, informers := createAdClients(ns, t, server, defaultSyncPeriod)
pod := fakePodWithVol(namespaceName)
podStopCh := make(chan struct{})
if _, err := testClient.Core().Nodes().Create(node); err != nil {
t.Fatalf("Failed to created node : %v", err)
}
go informers.Core().V1().Nodes().Informer().Run(podStopCh)
if _, err := testClient.Core().Pods(ns.Name).Create(pod); err != nil {
t.Errorf("Failed to create pod : %v", err)
}
podInformer := informers.Core().V1().Pods().Informer()
go podInformer.Run(podStopCh)
// start controller loop
stopCh := make(chan struct{})
go informers.Core().V1().PersistentVolumeClaims().Informer().Run(stopCh)
go informers.Core().V1().PersistentVolumes().Informer().Run(stopCh)
go ctrl.Run(stopCh)
waitToObservePods(t, podInformer, 1)
podKey, err := cache.MetaNamespaceKeyFunc(pod)
if err != nil {
t.Fatalf("MetaNamespaceKeyFunc failed with : %v", err)
}
_, _, err = podInformer.GetStore().GetByKey(podKey)
if err != nil {
t.Fatalf("Pod not found in Pod Informer cache : %v", err)
}
waitForPodsInDSWP(t, ctrl.GetDesiredStateOfWorld())
pod.Status.Phase = v1.PodSucceeded
if _, err := testClient.Core().Pods(ns.Name).UpdateStatus(pod); err != nil {
t.Errorf("Failed to update pod : %v", err)
}
time.Sleep(20 * time.Second)
podsToAdd := ctrl.GetDesiredStateOfWorld().GetPodToAdd()
if len(podsToAdd) != 0 {
t.Fatalf("All pods should have been removed")
}
close(podStopCh)
close(stopCh)
}
// wait for the podInformer to observe the pods. Call this function before // wait for the podInformer to observe the pods. Call this function before
// running the RC manager to prevent the rc manager from creating new pods // running the RC manager to prevent the rc manager from creating new pods
// rather than adopting the existing ones. // rather than adopting the existing ones.
...@@ -213,8 +284,8 @@ func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, sy ...@@ -213,8 +284,8 @@ func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, sy
cloud, cloud,
plugins, plugins,
false, false,
time.Second*5, time.Second*5)
)
if err != nil { if err != nil {
t.Fatalf("Error creating AttachDetach : %v", err) t.Fatalf("Error creating AttachDetach : %v", err)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment