From c232a0165ab7835e9b29509889ab8b1ac7d109c5 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Wed, 14 Feb 2018 16:54:25 +0100 Subject: [PATCH] Fix DownwardAPI refresh race. WaitForAttachAndMount should mark only pod in DesiredStateOfWorldPopulator (DSWP) and DSWP should mark the volume to be remounted only when the new pod has been processed. Otherwise DSWP and reconciler race who gets the new pod first. If it's reconciler, then DownwardAPI and Projected volumes of the pod are not refreshed with new content and they are updated after the next periodic sync (60-90 seconds). --- .../populator/desired_state_of_world_populator.go | 6 ++++++ .../populator/desired_state_of_world_populator_test.go | 2 ++ pkg/kubelet/volumemanager/volume_manager.go | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go index 6f86e43c3dc..f0a2a5c9f82 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator.go @@ -83,6 +83,7 @@ func NewDesiredStateOfWorldPopulator( podManager pod.Manager, podStatusProvider status.PodStatusProvider, desiredStateOfWorld cache.DesiredStateOfWorld, + actualStateOfWorld cache.ActualStateOfWorld, kubeContainerRuntime kubecontainer.Runtime, keepTerminatedPodVolumes bool) DesiredStateOfWorldPopulator { return &desiredStateOfWorldPopulator{ @@ -92,6 +93,7 @@ func NewDesiredStateOfWorldPopulator( podManager: podManager, podStatusProvider: podStatusProvider, desiredStateOfWorld: desiredStateOfWorld, + actualStateOfWorld: actualStateOfWorld, pods: processedPods{ processedPods: make(map[volumetypes.UniquePodName]bool)}, kubeContainerRuntime: kubeContainerRuntime, @@ -108,6 +110,7 @@ type desiredStateOfWorldPopulator struct { podManager pod.Manager podStatusProvider status.PodStatusProvider desiredStateOfWorld cache.DesiredStateOfWorld + actualStateOfWorld cache.ActualStateOfWorld pods processedPods kubeContainerRuntime kubecontainer.Runtime timeOfLastGetPodStatus time.Time @@ -302,6 +305,9 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(pod *v1.Pod) { // some of the volume additions may have failed, should not mark this pod as fully processed if allVolumesAdded { dswp.markPodProcessed(uniquePodName) + // New pod has been synced. Re-mount all volumes that need it + // (e.g. DownwardAPI) + dswp.actualStateOfWorld.MarkRemountRequired(uniquePodName) } } diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go index e9f27af810b..992116c4ad9 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go @@ -525,6 +525,7 @@ func createDswpWithVolume(t *testing.T, pv *v1.PersistentVolume, pvc *v1.Persist podtest.NewFakeMirrorClient(), fakeSecretManager, fakeConfigMapManager) fakesDSW := cache.NewDesiredStateOfWorld(fakeVolumePluginMgr) + fakeASW := cache.NewActualStateOfWorld("fake", fakeVolumePluginMgr) fakeRuntime := &containertest.FakeRuntime{} fakeStatusManager := status.NewManager(fakeClient, fakePodManager, &statustest.FakePodDeletionSafetyProvider{}) @@ -536,6 +537,7 @@ func createDswpWithVolume(t *testing.T, pv *v1.PersistentVolume, pvc *v1.Persist podManager: fakePodManager, podStatusProvider: fakeStatusManager, desiredStateOfWorld: fakesDSW, + actualStateOfWorld: fakeASW, pods: processedPods{ processedPods: make(map[types.UniquePodName]bool)}, kubeContainerRuntime: fakeRuntime, diff --git a/pkg/kubelet/volumemanager/volume_manager.go b/pkg/kubelet/volumemanager/volume_manager.go index 418a598085d..d8a1079858e 100644 --- a/pkg/kubelet/volumemanager/volume_manager.go +++ b/pkg/kubelet/volumemanager/volume_manager.go @@ -179,6 +179,7 @@ func NewVolumeManager( podManager, podStatusProvider, vm.desiredStateOfWorld, + vm.actualStateOfWorld, kubeContainerRuntime, keepTerminatedPodVolumes) vm.reconciler = reconciler.NewReconciler( @@ -345,7 +346,6 @@ func (vm *volumeManager) WaitForAttachAndMount(pod *v1.Pod) error { // Remount plugins for which this is true. (Atomically updating volumes, // like Downward API, depend on this to update the contents of the volume). vm.desiredStateOfWorldPopulator.ReprocessPod(uniquePodName) - vm.actualStateOfWorld.MarkRemountRequired(uniquePodName) err := wait.Poll( podAttachAndMountRetryInterval,