@@ -28,6 +28,7 @@ import (
2828 "github.com/kubernetes-csi/csi-lib-utils/slowset"
2929 "github.com/kubernetes-csi/external-resizer/pkg/modifier"
3030 v1 "k8s.io/api/core/v1"
31+ apierrors "k8s.io/apimachinery/pkg/api/errors"
3132 "k8s.io/apimachinery/pkg/labels"
3233 "k8s.io/apimachinery/pkg/util/wait"
3334 utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -41,6 +42,7 @@ import (
4142 "k8s.io/client-go/tools/record"
4243 "k8s.io/client-go/util/workqueue"
4344 "k8s.io/klog/v2"
45+ "k8s.io/utils/ptr"
4446)
4547
4648// ModifyController watches PVCs and checks if they are requesting an modify operation.
@@ -63,8 +65,11 @@ type modifyController struct {
6365 vacLister storagev1listers.VolumeAttributesClassLister
6466 vacListerSynced cache.InformerSynced
6567 extraModifyMetadata bool
66- // the key of the map is {PVC_NAMESPACE}/{PVC_NAME}
67- uncertainPVCs map [string ]v1.PersistentVolumeClaim
68+ // uncertainPVCs tracks PVCs that failed with non-final errors.
69+ // We must not change the target when retrying.
70+ // All in-progress PVCs are added here on initialization.
71+ // The key of the map is {PVC_NAMESPACE}/{PVC_NAME}, value is not important now.
72+ uncertainPVCs sync.Map
6873 // slowSet tracks PVCs for which modification failed with infeasible error and should be retried at slower rate.
6974 slowSet * slowset.SlowSet
7075}
@@ -124,19 +129,18 @@ func NewModifyController(
124129}
125130
126131func (ctrl * modifyController ) initUncertainPVCs () error {
127- ctrl .uncertainPVCs = make (map [string ]v1.PersistentVolumeClaim )
128132 allPVCs , err := ctrl .pvcLister .List (labels .Everything ())
129133 if err != nil {
130134 klog .Errorf ("Failed to list pvcs when init uncertain pvcs: %v" , err )
131135 return err
132136 }
133137 for _ , pvc := range allPVCs {
134- if pvc .Status .ModifyVolumeStatus != nil && (pvc .Status .ModifyVolumeStatus .Status == v1 .PersistentVolumeClaimModifyVolumeInProgress || pvc . Status . ModifyVolumeStatus . Status == v1 . PersistentVolumeClaimModifyVolumeInfeasible ) {
138+ if pvc .Status .ModifyVolumeStatus != nil && (pvc .Status .ModifyVolumeStatus .Status == v1 .PersistentVolumeClaimModifyVolumeInProgress ) {
135139 pvcKey , err := cache .MetaNamespaceKeyFunc (pvc )
136140 if err != nil {
137141 return err
138142 }
139- ctrl .uncertainPVCs [ pvcKey ] = * pvc . DeepCopy ( )
143+ ctrl .uncertainPVCs . Store ( pvcKey , pvc )
140144 }
141145 }
142146
@@ -163,18 +167,18 @@ func (ctrl *modifyController) updatePVC(oldObj, newObj interface{}) {
163167 }
164168
165169 // Only trigger modify volume if the following conditions are met
166- // 1. Non empty vac name
167- // 2. oldVacName != newVacName
168- // 3. PVC is in Bound state
169- oldVacName := oldPVC .Spec .VolumeAttributesClassName
170- newVacName := newPVC .Spec .VolumeAttributesClassName
171- if newVacName != nil && * newVacName != "" && (oldVacName == nil || * newVacName != * oldVacName ) && oldPVC .Status .Phase == v1 .ClaimBound {
170+ // 1. VAC changed or modify finished (check pending modify request while we are modifying)
171+ // 2. PVC is in Bound state
172+ oldVacName := ptr .Deref (oldPVC .Spec .VolumeAttributesClassName , "" )
173+ newVacName := ptr .Deref (newPVC .Spec .VolumeAttributesClassName , "" )
174+ if (newVacName != oldVacName || newPVC .Status .ModifyVolumeStatus == nil ) && newPVC .Status .Phase == v1 .ClaimBound {
172175 _ , err := ctrl .pvLister .Get (oldPVC .Spec .VolumeName )
173176 if err != nil {
174177 klog .Errorf ("Get PV %q of pvc %q in PVInformer cache failed: %v" , oldPVC .Spec .VolumeName , klog .KObj (oldPVC ), err )
175178 return
176179 }
177180 // Handle modify volume by adding to the claimQueue to avoid race conditions
181+ klog .V (4 ).InfoS ("Enqueueing PVC for modify" , "PVC" , klog .KObj (newPVC ))
178182 ctrl .addPVC (newObj )
179183 } else {
180184 klog .V (4 ).InfoS ("No need to modify PVC" , "PVC" , klog .KObj (newPVC ))
@@ -190,10 +194,7 @@ func (ctrl *modifyController) deletePVC(obj interface{}) {
190194}
191195
192196func (ctrl * modifyController ) init (ctx context.Context ) bool {
193- informersSyncd := []cache.InformerSynced {ctrl .pvListerSynced , ctrl .pvcListerSynced }
194- informersSyncd = append (informersSyncd , ctrl .vacListerSynced )
195-
196- if ! cache .WaitForCacheSync (ctx .Done (), informersSyncd ... ) {
197+ if ! cache .WaitForCacheSync (ctx .Done (), ctrl .pvListerSynced , ctrl .pvcListerSynced , ctrl .vacListerSynced ) {
197198 klog .ErrorS (nil , "Cannot sync pod, pv, pvc or vac caches" )
198199 return false
199200 }
@@ -224,15 +225,15 @@ func (ctrl *modifyController) Run(
224225 go ctrl .slowSet .Run (stopCh )
225226
226227 if utilfeature .DefaultFeatureGate .Enabled (features .ReleaseLeaderElectionOnExit ) {
227- for i := 0 ; i < workers ; i ++ {
228+ for range workers {
228229 wg .Add (1 )
229230 go func () {
230231 defer wg .Done ()
231232 wait .Until (ctrl .sync , 0 , stopCh )
232233 }()
233234 }
234235 } else {
235- for i := 0 ; i < workers ; i ++ {
236+ for range workers {
236237 go wait .Until (ctrl .sync , 0 , stopCh )
237238 }
238239 }
@@ -268,6 +269,10 @@ func (ctrl *modifyController) syncPVC(key string) error {
268269
269270 pvc , err := ctrl .pvcLister .PersistentVolumeClaims (namespace ).Get (name )
270271 if err != nil {
272+ if apierrors .IsNotFound (err ) {
273+ klog .V (3 ).InfoS ("PVC is deleted or does not exist" , "PVC" , klog .KRef (namespace , name ))
274+ return nil
275+ }
271276 return fmt .Errorf ("getting PVC %s/%s failed: %v" , namespace , name , err )
272277 }
273278
@@ -283,15 +288,13 @@ func (ctrl *modifyController) syncPVC(key string) error {
283288
284289 // Only trigger modify volume if the following conditions are met
285290 // 1. PV provisioned by CSI driver AND driver name matches local driver
286- // 2. Non-empty vac name
287- // 3. PVC is in Bound state
291+ // 2. PVC is in Bound state
288292 if pv .Spec .CSI == nil || pv .Spec .CSI .Driver != ctrl .name {
289293 klog .V (7 ).InfoS ("Skipping PV provisioned by different driver" , "PV" , klog .KObj (pv ))
290294 return nil
291295 }
292296
293- vacName := pvc .Spec .VolumeAttributesClassName
294- if vacName != nil && * vacName != "" && pvc .Status .Phase == v1 .ClaimBound {
297+ if pvc .Status .Phase == v1 .ClaimBound {
295298 _ , _ , err , _ := ctrl .modify (pvc , pv )
296299 if err != nil {
297300 return err
0 commit comments