Skip to content

Commit b1b48db

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 7493e6d commit b1b48db

File tree

17 files changed

+1371
-18
lines changed

17 files changed

+1371
-18
lines changed

Gopkg.lock

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/controller.go

+9-2
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

+1-1
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

+2-1
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

+39-6
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ import (
2323
"time"
2424

2525
"github.com/kubernetes-csi/external-resizer/pkg/csi"
26+
"github.com/kubernetes-csi/external-resizer/pkg/util"
2627

2728
"k8s.io/api/core/v1"
2829
"k8s.io/apimachinery/pkg/api/resource"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
"k8s.io/client-go/informers"
3132
"k8s.io/client-go/kubernetes"
33+
34+
csitranslationlib "k8s.io/csi-translation-lib"
3235
"k8s.io/klog"
3336
)
3437

@@ -107,7 +110,14 @@ func (r *csiResizer) Name() string {
107110
return r.name
108111
}
109112

110-
func (r *csiResizer) CanSupport(pv *v1.PersistentVolume) bool {
113+
// CanSupport returns whether the PV is supported by resizer
114+
// Resizer will resize the volume if it is CSI volume or is migration enabled in-tree volume
115+
func (r *csiResizer) CanSupport(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) bool {
116+
resizerName := pvc.Annotations[util.VolumeResizerKey]
117+
if csitranslationlib.IsMigratedCSIDriverByName(r.name) && resizerName == r.name {
118+
return true
119+
}
120+
111121
source := pv.Spec.CSI
112122
if source == nil {
113123
klog.V(4).Infof("PV %s is not a CSI volume, skip it", pv.Name)
@@ -120,14 +130,32 @@ func (r *csiResizer) CanSupport(pv *v1.PersistentVolume) bool {
120130
return true
121131
}
122132

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

126-
source := pv.Spec.CSI
127-
if source == nil {
128-
return oldSize, false, errors.New("not a CSI volume")
138+
var volumeID string
139+
var source *v1.CSIPersistentVolumeSource
140+
if pv.Spec.CSI != nil {
141+
// handle CSI volume
142+
source = pv.Spec.CSI
143+
volumeID = source.VolumeHandle
144+
} else {
145+
if csitranslationlib.IsMigratedCSIDriverByName(r.name) {
146+
// handle migrated in-tree volume
147+
csiPV, err := csitranslationlib.TranslateInTreePVToCSI(pv)
148+
if err != nil {
149+
return oldSize, false, fmt.Errorf("failed to translate persistent volume: %v", err)
150+
}
151+
source = csiPV.Spec.CSI
152+
volumeID = source.VolumeHandle
153+
} else {
154+
// non-migrated in-tree volume
155+
return oldSize, false, fmt.Errorf("volume %v is not migrated to CSI", pv.Name)
156+
}
129157
}
130-
volumeID := source.VolumeHandle
158+
131159
if len(volumeID) == 0 {
132160
return oldSize, false, errors.New("empty volume handle")
133161
}
@@ -148,7 +176,12 @@ func (r *csiResizer) Resize(pv *v1.PersistentVolume, requestSize resource.Quanti
148176
if err != nil {
149177
return oldSize, nodeResizeRequired, err
150178
}
151-
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), nodeResizeRequired, err
179+
180+
if pv.Spec.VolumeMode == nil || *pv.Spec.VolumeMode == v1.PersistentVolumeFilesystem {
181+
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), nodeResizeRequired, err
182+
}
183+
184+
return *resource.NewQuantity(newSizeBytes, resource.BinarySI), false, err
152185
}
153186

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

0 commit comments

Comments
 (0)