@@ -26,9 +26,9 @@ import (
26
26
"google.golang.org/grpc/codes"
27
27
"google.golang.org/grpc/status"
28
28
v1 "k8s.io/api/core/v1"
29
- k8serrors "k8s.io/apimachinery/pkg/api/errors"
30
29
"k8s.io/apimachinery/pkg/api/resource"
31
30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31
+ "k8s.io/apimachinery/pkg/types"
32
32
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
33
33
"k8s.io/apimachinery/pkg/util/wait"
34
34
"k8s.io/client-go/informers"
@@ -55,15 +55,18 @@ type resizeController struct {
55
55
kubeClient kubernetes.Interface
56
56
claimQueue workqueue.RateLimitingInterface
57
57
eventRecorder record.EventRecorder
58
- pvLister corelisters.PersistentVolumeLister
59
58
pvSynced cache.InformerSynced
60
- pvcLister corelisters.PersistentVolumeClaimLister
61
59
pvcSynced cache.InformerSynced
62
60
63
61
usedPVCs * inUsePVCStore
64
62
65
- podLister corelisters.PodLister
66
- podListerSynced cache.InformerSynced
63
+ podLister corelisters.PodLister
64
+ podListerSynced cache.InformerSynced
65
+
66
+ // a cache to store PersistentVolume objects
67
+ volumes cache.Store
68
+ // a cache to store PersistentVolumeClaim objects
69
+ claims cache.Store
67
70
handleVolumeInUseError bool
68
71
}
69
72
@@ -91,11 +94,11 @@ func NewResizeController(
91
94
name : name ,
92
95
resizer : resizer ,
93
96
kubeClient : kubeClient ,
94
- pvLister : pvInformer .Lister (),
95
97
pvSynced : pvInformer .Informer ().HasSynced ,
96
- pvcLister : pvcInformer .Lister (),
97
98
pvcSynced : pvcInformer .Informer ().HasSynced ,
98
99
claimQueue : claimQueue ,
100
+ volumes : pvInformer .Informer ().GetStore (),
101
+ claims : pvcInformer .Informer ().GetStore (),
99
102
eventRecorder : eventRecorder ,
100
103
usedPVCs : newUsedPVCStore (),
101
104
handleVolumeInUseError : handleVolumeInUseError ,
@@ -266,6 +269,7 @@ func (ctrl *resizeController) syncPVCs() {
266
269
267
270
if err := ctrl .syncPVC (key .(string )); err != nil {
268
271
// Put PVC back to the queue so that we can retry later.
272
+ klog .Errorf ("Error syncing PVC: %v" , err )
269
273
ctrl .claimQueue .AddRateLimited (key )
270
274
} else {
271
275
ctrl .claimQueue .Forget (key )
@@ -278,33 +282,42 @@ func (ctrl *resizeController) syncPVC(key string) error {
278
282
279
283
namespace , name , err := cache .SplitMetaNamespaceKey (key )
280
284
if err != nil {
281
- klog .Errorf ("Split meta namespace key of pvc %s failed: %v" , key , err )
282
- return err
285
+ return fmt .Errorf ("getting namespace and name from key %s failed: %v" , key , err )
283
286
}
284
287
285
- pvc , err := ctrl .pvcLister . PersistentVolumeClaims ( namespace ). Get ( name )
288
+ pvcObject , exists , err := ctrl .claims . GetByKey ( key )
286
289
if err != nil {
287
- if k8serrors .IsNotFound (err ) {
288
- klog .V (3 ).Infof ("PVC %s/%s is deleted, no need to process it" , namespace , name )
289
- return nil
290
- }
291
- klog .Errorf ("Get PVC %s/%s failed: %v" , namespace , name , err )
292
- return err
290
+ return fmt .Errorf ("getting PVC %s/%s failed: %v" , namespace , name , err )
291
+ }
292
+
293
+ if ! exists {
294
+ klog .V (3 ).Infof ("PVC %s/%s is deleted or does not exist" , namespace , name )
295
+ return nil
296
+ }
297
+
298
+ pvc , ok := pvcObject .(* v1.PersistentVolumeClaim )
299
+ if ! ok {
300
+ return fmt .Errorf ("expected PVC got: %v" , pvcObject )
293
301
}
294
302
295
303
if ! ctrl .pvcNeedResize (pvc ) {
296
304
klog .V (4 ).Infof ("No need to resize PVC %q" , util .PVCKey (pvc ))
297
305
return nil
298
306
}
299
307
300
- pv , err := ctrl .pvLister . Get (pvc .Spec .VolumeName )
308
+ volumeObj , exists , err := ctrl .volumes . GetByKey (pvc .Spec .VolumeName )
301
309
if err != nil {
302
- if k8serrors .IsNotFound (err ) {
303
- klog .V (3 ).Infof ("PV %s is deleted, no need to process it" , pvc .Spec .VolumeName )
304
- return nil
305
- }
306
- klog .Errorf ("Get PV %q of pvc %q failed: %v" , pvc .Spec .VolumeName , util .PVCKey (pvc ), err )
307
- return err
310
+ return fmt .Errorf ("Get PV %q of pvc %q failed: %v" , pvc .Spec .VolumeName , util .PVCKey (pvc ), err )
311
+ }
312
+
313
+ if ! exists {
314
+ klog .Warningf ("PV %q bound to PVC %s not found" , pvc .Spec .VolumeName , util .PVCKey (pvc ))
315
+ return nil
316
+ }
317
+
318
+ pv , ok := volumeObj .(* v1.PersistentVolume )
319
+ if ! ok {
320
+ return fmt .Errorf ("expected volume but got %+v" , volumeObj )
308
321
}
309
322
310
323
if ! ctrl .pvNeedResize (pvc , pv ) {
@@ -369,8 +382,7 @@ func (ctrl *resizeController) pvNeedResize(pvc *v1.PersistentVolumeClaim, pv *v1
369
382
// 3. Mark pvc as resizing finished(no error, no need to resize fs), need resizing fs or resize failed.
370
383
func (ctrl * resizeController ) resizePVC (pvc * v1.PersistentVolumeClaim , pv * v1.PersistentVolume ) error {
371
384
if updatedPVC , err := ctrl .markPVCResizeInProgress (pvc ); err != nil {
372
- klog .Errorf ("Mark pvc %q as resizing failed: %v" , util .PVCKey (pvc ), err )
373
- return err
385
+ return fmt .Errorf ("marking pvc %q as resizing failed: %v" , util .PVCKey (pvc ), err )
374
386
} else if updatedPVC != nil {
375
387
pvc = updatedPVC
376
388
}
@@ -406,7 +418,6 @@ func (ctrl *resizeController) resizePVC(pvc *v1.PersistentVolumeClaim, pv *v1.Pe
406
418
// Record an event to indicate that resize operation is failed.
407
419
ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeWarning , util .VolumeResizeFailed , err .Error ())
408
420
}
409
-
410
421
return err
411
422
}
412
423
@@ -426,25 +437,48 @@ func (ctrl *resizeController) resizeVolume(
426
437
newSize , fsResizeRequired , err := ctrl .resizer .Resize (pv , requestSize )
427
438
428
439
if err != nil {
429
- klog .Errorf ("Resize volume %q by resizer %q failed: %v" , pv .Name , ctrl .name , err )
430
440
// if this error was a in-use error then it must be tracked so as we don't retry without
431
441
// first verifying if volume is in-use
432
442
if inUseError (err ) {
433
443
ctrl .usedPVCs .addPVCWithInUseError (pvc )
434
444
}
435
- return newSize , fsResizeRequired , fmt .Errorf ("resize volume %s failed: %v" , pv .Name , err )
445
+ return newSize , fsResizeRequired , fmt .Errorf ("resize volume %q by resizer %q failed: %v" , pv .Name , ctrl . name , err )
436
446
}
437
447
klog .V (4 ).Infof ("Resize volume succeeded for volume %q, start to update PV's capacity" , pv .Name )
438
448
439
- if err := util . UpdatePVCapacity (pv , newSize , ctrl . kubeClient ); err != nil {
440
- klog . Errorf ( "Update capacity of PV %q to %s failed: %v" , pv . Name , newSize . String (), err )
449
+ err = ctrl . updatePVCapacity (pv , newSize )
450
+ if err != nil {
441
451
return newSize , fsResizeRequired , err
442
452
}
443
453
klog .V (4 ).Infof ("Update capacity of PV %q to %s succeeded" , pv .Name , newSize .String ())
444
454
445
455
return newSize , fsResizeRequired , nil
446
456
}
447
457
458
+ func (ctrl * resizeController ) markPVCAsFSResizeRequired (pvc * v1.PersistentVolumeClaim ) error {
459
+ pvcCondition := v1.PersistentVolumeClaimCondition {
460
+ Type : v1 .PersistentVolumeClaimFileSystemResizePending ,
461
+ Status : v1 .ConditionTrue ,
462
+ LastTransitionTime : metav1 .Now (),
463
+ Message : "Waiting for user to (re-)start a pod to finish file system resize of volume on node." ,
464
+ }
465
+ newPVC := pvc .DeepCopy ()
466
+ newPVC .Status .Conditions = util .MergeResizeConditionsOfPVC (newPVC .Status .Conditions ,
467
+ []v1.PersistentVolumeClaimCondition {pvcCondition })
468
+
469
+ _ , err := ctrl .patchClaim (pvc , newPVC )
470
+
471
+ if err != nil {
472
+ return fmt .Errorf ("Mark PVC %q as file system resize required failed: %v" , util .PVCKey (pvc ), err )
473
+ }
474
+
475
+ klog .V (4 ).Infof ("Mark PVC %q as file system resize required" , util .PVCKey (pvc ))
476
+ ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeNormal ,
477
+ util .FileSystemResizeRequired , "Require file system resize of volume on node" )
478
+
479
+ return nil
480
+ }
481
+
448
482
func (ctrl * resizeController ) markPVCResizeInProgress (pvc * v1.PersistentVolumeClaim ) (* v1.PersistentVolumeClaim , error ) {
449
483
// Mark PVC as Resize Started
450
484
progressCondition := v1.PersistentVolumeClaimCondition {
@@ -455,7 +489,12 @@ func (ctrl *resizeController) markPVCResizeInProgress(pvc *v1.PersistentVolumeCl
455
489
newPVC := pvc .DeepCopy ()
456
490
newPVC .Status .Conditions = util .MergeResizeConditionsOfPVC (newPVC .Status .Conditions ,
457
491
[]v1.PersistentVolumeClaimCondition {progressCondition })
458
- return util .PatchPVCStatus (pvc , newPVC , ctrl .kubeClient )
492
+
493
+ updatedPVC , err := ctrl .patchClaim (pvc , newPVC )
494
+ if err != nil {
495
+ return nil , err
496
+ }
497
+ return updatedPVC , nil
459
498
}
460
499
461
500
func (ctrl * resizeController ) markPVCResizeFinished (
@@ -464,9 +503,10 @@ func (ctrl *resizeController) markPVCResizeFinished(
464
503
newPVC := pvc .DeepCopy ()
465
504
newPVC .Status .Capacity [v1 .ResourceStorage ] = newSize
466
505
newPVC .Status .Conditions = util .MergeResizeConditionsOfPVC (pvc .Status .Conditions , []v1.PersistentVolumeClaimCondition {})
467
- if _ , err := util .PatchPVCStatus (pvc , newPVC , ctrl .kubeClient ); err != nil {
468
- klog .Errorf ("Mark PVC %q as resize finished failed: %v" , util .PVCKey (pvc ), err )
469
- return err
506
+
507
+ _ , err := ctrl .patchClaim (pvc , newPVC )
508
+ if err != nil {
509
+ return fmt .Errorf ("Mark PVC %q as resize finished failed: %v" , util .PVCKey (pvc ), err )
470
510
}
471
511
472
512
klog .V (4 ).Infof ("Resize PVC %q finished" , util .PVCKey (pvc ))
@@ -475,28 +515,52 @@ func (ctrl *resizeController) markPVCResizeFinished(
475
515
return nil
476
516
}
477
517
478
- func (ctrl * resizeController ) markPVCAsFSResizeRequired (pvc * v1.PersistentVolumeClaim ) error {
479
- pvcCondition := v1.PersistentVolumeClaimCondition {
480
- Type : v1 .PersistentVolumeClaimFileSystemResizePending ,
481
- Status : v1 .ConditionTrue ,
482
- LastTransitionTime : metav1 .Now (),
483
- Message : "Waiting for user to (re-)start a pod to finish file system resize of volume on node." ,
518
+ func (ctrl * resizeController ) patchClaim (oldPVC , newPVC * v1.PersistentVolumeClaim ) (* v1.PersistentVolumeClaim , error ) {
519
+ patchBytes , err := util .GetPVCPatchData (oldPVC , newPVC )
520
+ if err != nil {
521
+ return nil , fmt .Errorf ("can't patch status of PVC %s as generate path data failed: %v" , util .PVCKey (oldPVC ), err )
484
522
}
485
- newPVC := pvc .DeepCopy ()
486
- newPVC .Status .Conditions = util .MergeResizeConditionsOfPVC (newPVC .Status .Conditions ,
487
- []v1.PersistentVolumeClaimCondition {pvcCondition })
488
-
489
- if _ , err := util .PatchPVCStatus (pvc , newPVC , ctrl .kubeClient ); err != nil {
490
- klog .Errorf ("Mark PVC %q as file system resize required failed: %v" , util .PVCKey (pvc ), err )
491
- return err
523
+ updatedClaim , updateErr := ctrl .kubeClient .CoreV1 ().PersistentVolumeClaims (oldPVC .Namespace ).
524
+ Patch (context .TODO (), oldPVC .Name , types .StrategicMergePatchType , patchBytes , metav1.PatchOptions {}, "status" )
525
+ if updateErr != nil {
526
+ return nil , fmt .Errorf ("can't patch status of PVC %s with %v" , util .PVCKey (oldPVC ), updateErr )
492
527
}
493
- klog .V (4 ).Infof ("Mark PVC %q as file system resize required" , util .PVCKey (pvc ))
494
- ctrl .eventRecorder .Eventf (pvc , v1 .EventTypeNormal ,
495
- util .FileSystemResizeRequired , "Require file system resize of volume on node" )
528
+ err = ctrl .claims .Update (updatedClaim )
529
+ if err != nil {
530
+ return nil , fmt .Errorf ("error updating PVC %s in local cache: %v" , util .PVCKey (newPVC ), err )
531
+ }
532
+
533
+ return updatedClaim , nil
534
+ }
535
+
536
+ func (ctrl * resizeController ) updatePVCapacity (pv * v1.PersistentVolume , newCapacity resource.Quantity ) error {
537
+ klog .V (4 ).Infof ("Resize volume succeeded for volume %q, start to update PV's capacity" , pv .Name )
538
+ newPV := pv .DeepCopy ()
539
+ newPV .Spec .Capacity [v1 .ResourceStorage ] = newCapacity
496
540
541
+ _ , err := ctrl .patchPersistentVolume (pv , newPV )
542
+ if err != nil {
543
+ return fmt .Errorf ("updating capacity of PV %q to %s failed: %v" , pv .Name , newCapacity .String (), err )
544
+ }
497
545
return nil
498
546
}
499
547
548
+ func (ctrl * resizeController ) patchPersistentVolume (oldPV , newPV * v1.PersistentVolume ) (* v1.PersistentVolume , error ) {
549
+ patchBytes , err := util .GetPatchData (oldPV , newPV )
550
+ if err != nil {
551
+ return nil , fmt .Errorf ("can't update capacity of PV %s as generate path data failed: %v" , newPV .Name , err )
552
+ }
553
+ updatedPV , updateErr := ctrl .kubeClient .CoreV1 ().PersistentVolumes ().Patch (context .TODO (), newPV .Name , types .StrategicMergePatchType , patchBytes , metav1.PatchOptions {})
554
+ if updateErr != nil {
555
+ return nil , fmt .Errorf ("update capacity of PV %s failed: %v" , newPV .Name , updateErr )
556
+ }
557
+ err = ctrl .volumes .Update (updatedPV )
558
+ if err != nil {
559
+ return nil , fmt .Errorf ("error updating PV %s in local cache: %v" , newPV .Name , err )
560
+ }
561
+ return updatedPV , nil
562
+ }
563
+
500
564
func parsePod (obj interface {}) * v1.Pod {
501
565
if obj == nil {
502
566
return nil
0 commit comments