Skip to content

Commit 83d5dff

Browse files
author
Cheng Pan
committed
Implement CSI migration logic for volume resize
* Using PVC annotation for sychronication between in-tree resizer and extternal resizer * Modify enqueue condition for resizer migration * Add unit tests
1 parent ad72116 commit 83d5dff

File tree

17 files changed

+1390
-16
lines changed

17 files changed

+1390
-16
lines changed

Gopkg.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/controller.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,18 @@ func (ctrl *resizeController) updatePVC(oldObj, newObj interface{}) {
123123
newSize := newPVC.Spec.Resources.Requests[v1.ResourceStorage]
124124
oldSize := oldPVC.Spec.Resources.Requests[v1.ResourceStorage]
125125

126+
newResizerName := newPVC.Annotations[util.VolumeResizerKey]
127+
oldResizerName := oldPVC.Annotations[util.VolumeResizerKey]
128+
126129
// We perform additional checks to avoid double processing of PVCs, as we will also receive Update event when:
127130
// 1. Administrator or users may introduce other changes(such as add labels, modify annotations, etc.)
128131
// unrelated to volume resize.
129132
// 2. Informer will resync and send Update event periodically without any changes.
130-
if newSize.Cmp(oldSize) > 0 {
133+
//
134+
// We add the PVC into work queue when the new size is larger then the old size
135+
// or when the resizer name annotation is missing from old PVC
136+
// but present in the new PVC. This is needed for CSI migration
137+
if newSize.Cmp(oldSize) > 0 || (newResizerName != "" && oldResizerName == "") {
131138
ctrl.addPVC(newObj)
132139
}
133140
}
@@ -249,7 +256,7 @@ func (ctrl *resizeController) pvcNeedResize(pvc *v1.PersistentVolumeClaim) bool
249256

250257
// pvNeedResize returns true if a pv supports and also requests resize.
251258
func (ctrl *resizeController) pvNeedResize(pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) bool {
252-
if !ctrl.resizer.CanSupport(pv) {
259+
if !ctrl.resizer.CanSupport(pv, pvc) {
253260
klog.V(4).Infof("Resizer %q doesn't support PV %q", ctrl.name, pv.Name)
254261
return false
255262
}

pkg/controller/controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func TestController(t *testing.T) {
6565
NodeResize: true,
6666
},
6767
} {
68-
client := csi.NewMockClient(test.NodeResize, true, true)
68+
client := csi.NewMockClient("mock", test.NodeResize, true, true)
6969
driverName, _ := client.GetDriverName(context.TODO())
7070

7171
initialObjects := []runtime.Object{}

pkg/csi/mock_client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package csi
33
import "context"
44

55
func NewMockClient(
6+
name string,
67
supportsNodeResize bool,
78
supportsControllerResize bool,
89
supportsPluginControllerService bool) *MockClient {
910
return &MockClient{
10-
name: "mock",
11+
name: name,
1112
supportsNodeResize: supportsNodeResize,
1213
supportsControllerResize: supportsControllerResize,
1314
supportsPluginControllerService: supportsPluginControllerService,

pkg/resizer/csi_resizer.go

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

2626
"github.com/kubernetes-csi/external-resizer/pkg/csi"
27+
"github.com/kubernetes-csi/external-resizer/pkg/util"
2728

2829
"k8s.io/api/core/v1"
2930
"k8s.io/apimachinery/pkg/api/resource"
@@ -33,6 +34,8 @@ import (
3334
"k8s.io/client-go/informers"
3435
"k8s.io/client-go/kubernetes"
3536
storagev1listers "k8s.io/client-go/listers/storage/v1"
37+
38+
csitranslationlib "k8s.io/csi-translation-lib"
3639
"k8s.io/klog"
3740
)
3841

@@ -118,7 +121,14 @@ func (r *csiResizer) Name() string {
118121
return r.name
119122
}
120123

121-
func (r *csiResizer) CanSupport(pv *v1.PersistentVolume) bool {
124+
// CanSupport returns whether the PV is supported by resizer
125+
// Resizer will resize the volume if it is CSI volume or is migration enabled in-tree volume
126+
func (r *csiResizer) CanSupport(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) bool {
127+
resizerName := pvc.Annotations[util.VolumeResizerKey]
128+
if csitranslationlib.IsMigratedCSIDriverByName(r.name) && resizerName == r.name {
129+
return true
130+
}
131+
122132
source := pv.Spec.CSI
123133
if source == nil {
124134
klog.V(4).Infof("PV %s is not a CSI volume, skip it", pv.Name)
@@ -131,14 +141,30 @@ func (r *csiResizer) CanSupport(pv *v1.PersistentVolume) bool {
131141
return true
132142
}
133143

144+
// Resize resizes the persistence volume given request size
145+
// It supports both CSI volume and migrated in-tree volume
134146
func (r *csiResizer) Resize(pv *v1.PersistentVolume, requestSize resource.Quantity) (resource.Quantity, bool, error) {
135147
oldSize := pv.Spec.Capacity[v1.ResourceStorage]
136148

137-
source := pv.Spec.CSI
138-
if source == nil {
139-
return oldSize, false, errors.New("not a CSI volume")
149+
var volumeID string
150+
if pv.Spec.CSI != nil {
151+
// handle CSI volume
152+
source := pv.Spec.CSI
153+
volumeID = source.VolumeHandle
154+
} else {
155+
if csitranslationlib.IsMigratedCSIDriverByName(r.name) {
156+
// handle migrated in-tree volume
157+
csiPV, err := csitranslationlib.TranslateInTreePVToCSI(pv)
158+
if err != nil {
159+
return oldSize, false, fmt.Errorf("failed to translate persistent volume: %v", err)
160+
}
161+
volumeID = csiPV.Spec.CSI.VolumeHandle
162+
} else {
163+
// non-migrated in-tree volume
164+
return oldSize, false, fmt.Errorf("volume %v is not migrated to CSI", pv.Name)
165+
}
140166
}
141-
volumeID := source.VolumeHandle
167+
142168
if len(volumeID) == 0 {
143169
return oldSize, false, errors.New("empty volume handle")
144170
}
@@ -167,7 +193,12 @@ func (r *csiResizer) Resize(pv *v1.PersistentVolume, requestSize resource.Quanti
167193
if err != nil {
168194
return oldSize, nodeResizeRequired, err
169195
}
170-
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), nodeResizeRequired, err
196+
197+
if pv.Spec.VolumeMode == nil || *pv.Spec.VolumeMode == v1.PersistentVolumeFilesystem {
198+
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), nodeResizeRequired, err
199+
}
200+
201+
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), false, err
171202
}
172203

173204
func getDriverName(client csi.Client, timeout time.Duration) (string, error) {

0 commit comments

Comments
 (0)