Skip to content

Commit 31d2f5c

Browse files
committed
feat: add volume resize support
fix
1 parent c5f0687 commit 31d2f5c

File tree

10 files changed

+263
-27
lines changed

10 files changed

+263
-27
lines changed

charts/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ The following table lists the configurable parameters of the latest SMB CSI Driv
7777
| `controller.workingMountDir` | working directory for provisioner to mount smb shares temporarily | `/tmp` |
7878
| `controller.runOnMaster` | run controller on master node | `false` |
7979
| `controller.runOnControlPlane` | run controller on control plane node | `false` |
80-
| `controller.resources.csiProvisioner.limits.memory` | csi-provisioner memory limits | `100Mi` |
80+
| `controller.resources.csiProvisioner.limits.memory` | csi-provisioner memory limits | `400Mi` |
8181
| `controller.resources.csiProvisioner.requests.cpu` | csi-provisioner cpu requests limits | `10m` |
8282
| `controller.resources.csiProvisioner.requests.memory` | csi-provisioner memory requests limits | `20Mi` |
8383
| `controller.resources.livenessProbe.limits.memory` | liveness-probe memory limits | `300Mi` |
@@ -86,7 +86,7 @@ The following table lists the configurable parameters of the latest SMB CSI Driv
8686
| `controller.resources.smb.limits.memory` | smb-csi-driver memory limits | `200Mi` |
8787
| `controller.resources.smb.requests.cpu` | smb-csi-driver cpu requests limits | `10m` |
8888
| `controller.resources.smb.requests.memory` | smb-csi-driver memory requests limits | `20Mi` |
89-
| `controller.resources.csiResizer.limits.memory` | csi-resizer memory limits | `300Mi` |
89+
| `controller.resources.csiResizer.limits.memory` | csi-resizer memory limits | `400Mi` |
9090
| `controller.resources.csiResizer.requests.cpu` | csi-resizer cpu requests limits | `10m` |
9191
| `controller.resources.csiResizer.requests.memory` | csi-resizer memory requests limits | `20Mi` |
9292
| `controller.affinity` | controller pod affinity | `{}` |
0 Bytes
Binary file not shown.

deploy/csi-smb-controller.yaml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,31 @@ spec:
5555
resources:
5656
limits:
5757
cpu: 1
58-
memory: 300Mi
58+
memory: 400Mi
59+
requests:
60+
cpu: 10m
61+
memory: 20Mi
62+
securityContext:
63+
capabilities:
64+
drop:
65+
- ALL
66+
- name: csi-resizer
67+
image: registry.k8s.io/sig-storage/csi-resizer:v1.12.0
68+
args:
69+
- "-csi-address=$(ADDRESS)"
70+
- "-v=2"
71+
- "-leader-election"
72+
- "--leader-election-namespace=kube-system"
73+
- '-handle-volume-inuse-error=false'
74+
env:
75+
- name: ADDRESS
76+
value: /csi/csi.sock
77+
volumeMounts:
78+
- name: socket-dir
79+
mountPath: /csi
80+
resources:
81+
limits:
82+
memory: 400Mi
5983
requests:
6084
cpu: 10m
6185
memory: 20Mi

deploy/rbac-csi-smb.yaml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ rules:
4141
resources: ["secrets"]
4242
verbs: ["get"]
4343
---
44-
4544
kind: ClusterRoleBinding
4645
apiVersion: rbac.authorization.k8s.io/v1
4746
metadata:
@@ -54,3 +53,37 @@ roleRef:
5453
kind: ClusterRole
5554
name: smb-external-provisioner-role
5655
apiGroup: rbac.authorization.k8s.io
56+
---
57+
kind: ClusterRole
58+
apiVersion: rbac.authorization.k8s.io/v1
59+
metadata:
60+
name: smb-external-resizer-role
61+
rules:
62+
- apiGroups: [""]
63+
resources: ["persistentvolumes"]
64+
verbs: ["get", "list", "watch", "update", "patch"]
65+
- apiGroups: [""]
66+
resources: ["persistentvolumeclaims"]
67+
verbs: ["get", "list", "watch"]
68+
- apiGroups: [""]
69+
resources: ["persistentvolumeclaims/status"]
70+
verbs: ["update", "patch"]
71+
- apiGroups: [""]
72+
resources: ["events"]
73+
verbs: ["list", "watch", "create", "update", "patch"]
74+
- apiGroups: ["coordination.k8s.io"]
75+
resources: ["leases"]
76+
verbs: ["get", "list", "watch", "create", "update", "patch"]
77+
---
78+
kind: ClusterRoleBinding
79+
apiVersion: rbac.authorization.k8s.io/v1
80+
metadata:
81+
name: smb-csi-resizer-role
82+
subjects:
83+
- kind: ServiceAccount
84+
name: csi-smb-controller-sa
85+
namespace: kube-system
86+
roleRef:
87+
kind: ClusterRole
88+
name: smb-external-resizer-role
89+
apiGroup: rbac.authorization.k8s.io

hack/verify-helm-chart.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ pip install yq --break-system-packages --ignore-installed PyYAML
6262

6363
# Extract images from csi-smb-controller.yaml
6464
expected_csi_provisioner_image="$(cat ${PKG_ROOT}/deploy/csi-smb-controller.yaml | yq -r .spec.template.spec.containers[0].image | head -n 1)"
65-
expected_liveness_probe_image="$(cat ${PKG_ROOT}/deploy/csi-smb-controller.yaml | yq -r .spec.template.spec.containers[1].image | head -n 1)"
66-
expected_smb_image="$(cat ${PKG_ROOT}/deploy/csi-smb-controller.yaml | yq -r .spec.template.spec.containers[2].image | head -n 1)"
65+
expected_csi_resizer_image="$(cat ${PKG_ROOT}/deploy/csi-smb-controller.yaml | yq -r .spec.template.spec.containers[1].image | head -n 1)"
66+
expected_liveness_probe_image="$(cat ${PKG_ROOT}/deploy/csi-smb-controller.yaml | yq -r .spec.template.spec.containers[2].image | head -n 1)"
67+
expected_smb_image="$(cat ${PKG_ROOT}/deploy/csi-smb-controller.yaml | yq -r .spec.template.spec.containers[3].image | head -n 1)"
6768

6869
csi_provisioner_image="$(get_image_from_helm_chart "csiProvisioner")"
6970
validate_image "${expected_csi_provisioner_image}" "${csi_provisioner_image}"

pkg/smb/controllerserver.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,19 @@ func (d *Driver) ListVolumes(_ context.Context, _ *csi.ListVolumesRequest) (*csi
308308
}
309309

310310
// ControllerExpandVolume expand volume
311-
func (d *Driver) ControllerExpandVolume(_ context.Context, _ *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) {
312-
return nil, status.Error(codes.Unimplemented, "")
311+
func (d *Driver) ControllerExpandVolume(_ context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) {
312+
if len(req.GetVolumeId()) == 0 {
313+
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
314+
}
315+
316+
if req.GetCapacityRange() == nil {
317+
return nil, status.Error(codes.InvalidArgument, "Capacity Range missing in request")
318+
}
319+
320+
volSizeBytes := int64(req.GetCapacityRange().GetRequiredBytes())
321+
klog.V(2).Infof("ControllerExpandVolume(%s) successfully, currentQuota: %d bytes", req.VolumeId, volSizeBytes)
322+
323+
return &csi.ControllerExpandVolumeResponse{CapacityBytes: req.GetCapacityRange().GetRequiredBytes()}, nil
313324
}
314325

315326
func (d *Driver) CreateSnapshot(_ context.Context, _ *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) {

pkg/smb/controllerserver_test.go

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,54 @@ func TestListVolumes(t *testing.T) {
398398

399399
func TestControllerExpandVolume(t *testing.T) {
400400
d := NewFakeDriver()
401-
req := csi.ControllerExpandVolumeRequest{}
402-
resp, err := d.ControllerExpandVolume(context.Background(), &req)
403-
assert.Nil(t, resp)
404-
if !reflect.DeepEqual(err, status.Error(codes.Unimplemented, "")) {
405-
t.Errorf("Unexpected error: %v", err)
401+
402+
testCases := []struct {
403+
name string
404+
testFunc func(t *testing.T)
405+
}{
406+
{
407+
name: "volume ID missing",
408+
testFunc: func(t *testing.T) {
409+
req := &csi.ControllerExpandVolumeRequest{}
410+
_, err := d.ControllerExpandVolume(context.Background(), req)
411+
expectedErr := status.Error(codes.InvalidArgument, "Volume ID missing in request")
412+
if !reflect.DeepEqual(err, expectedErr) {
413+
t.Errorf("actualErr: (%v), expectedErr: (%v)", err, expectedErr)
414+
}
415+
},
416+
},
417+
{
418+
name: "Capacity Range missing",
419+
testFunc: func(t *testing.T) {
420+
req := &csi.ControllerExpandVolumeRequest{
421+
VolumeId: "unit-test",
422+
}
423+
_, err := d.ControllerExpandVolume(context.Background(), req)
424+
expectedErr := status.Error(codes.InvalidArgument, "Capacity Range missing in request")
425+
if !reflect.DeepEqual(err, expectedErr) {
426+
t.Errorf("actualErr: (%v), expectedErr: (%v)", err, expectedErr)
427+
}
428+
},
429+
},
430+
{
431+
name: "Error = nil",
432+
testFunc: func(t *testing.T) {
433+
req := &csi.ControllerExpandVolumeRequest{
434+
VolumeId: "unit-test",
435+
CapacityRange: &csi.CapacityRange{
436+
RequiredBytes: 10000,
437+
},
438+
}
439+
_, err := d.ControllerExpandVolume(context.Background(), req)
440+
if !reflect.DeepEqual(err, nil) {
441+
t.Errorf("actualErr: (%v), expectedErr: (%v)", err, nil)
442+
}
443+
},
444+
},
445+
}
446+
447+
for _, tc := range testCases {
448+
t.Run(tc.name, tc.testFunc)
406449
}
407450
}
408451

test/e2e/dynamic_provisioning_test.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
5454
})
5555

5656
testDriver = driver.InitSMBDriver()
57-
ginkgo.It("should create a volume after driver restart [smb.csi.k8s.io]", func(ctx ginkgo.SpecContext) {
57+
ginkgo.It("should create a volume after driver restart", func(ctx ginkgo.SpecContext) {
5858
ginkgo.Skip("test case is disabled since node logs would be lost after driver restart")
5959
pod := testsuites.PodDetails{
6060
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' >> /mnt/test-1/data && while true; do sleep 3600; done"),
@@ -102,7 +102,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
102102
test.Run(ctx, cs, ns)
103103
})
104104

105-
ginkgo.It("should create a volume on demand with mount options [smb.csi.k8s.io] [Windows]", func(ctx ginkgo.SpecContext) {
105+
ginkgo.It("should create a volume on demand with mount options [Windows]", func(ctx ginkgo.SpecContext) {
106106
pods := []testsuites.PodDetails{
107107
{
108108
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
@@ -137,7 +137,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
137137
test.Run(ctx, cs, ns)
138138
})
139139

140-
ginkgo.It("should create multiple PV objects, bind to PVCs and attach all to different pods on the same node [smb.csi.k8s.io] [Windows]", func(ctx ginkgo.SpecContext) {
140+
ginkgo.It("should create multiple PV objects, bind to PVCs and attach all to different pods on the same node [Windows]", func(ctx ginkgo.SpecContext) {
141141
pods := []testsuites.PodDetails{
142142
{
143143
Cmd: convertToPowershellCommandIfNecessary("while true; do echo $(date -u) >> /mnt/test-1/data; sleep 100; done"),
@@ -178,7 +178,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
178178
})
179179

180180
// Track issue https://github.com/kubernetes/kubernetes/issues/70505
181-
ginkgo.It("should create a volume on demand and mount it as readOnly in a pod [smb.csi.k8s.io]", func(ctx ginkgo.SpecContext) {
181+
ginkgo.It("should create a volume on demand and mount it as readOnly in a pod", func(ctx ginkgo.SpecContext) {
182182
// Windows volume does not support readOnly
183183
skipIfTestingInWindowsCluster()
184184
pods := []testsuites.PodDetails{
@@ -206,7 +206,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
206206
test.Run(ctx, cs, ns)
207207
})
208208

209-
ginkgo.It("should create a deployment object, write and read to it, delete the pod and write and read to it again [smb.csi.k8s.io] [Windows]", func(ctx ginkgo.SpecContext) {
209+
ginkgo.It("should create a deployment object, write and read to it, delete the pod and write and read to it again [Windows]", func(ctx ginkgo.SpecContext) {
210210
skipIfTestingInWindowsCluster()
211211
pod := testsuites.PodDetails{
212212
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' >> /mnt/test-1/data && while true; do sleep 100; done"),
@@ -246,7 +246,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
246246
})
247247

248248
// Track issue https://github.com/kubernetes-csi/csi-driver-smb/issues/834
249-
ginkgo.It(fmt.Sprintf("should delete PV with reclaimPolicy even if it contains read-only subdir %q [smb.csi.k8s.io]", v1.PersistentVolumeReclaimDelete), func(ctx ginkgo.SpecContext) {
249+
ginkgo.It(fmt.Sprintf("should delete PV with reclaimPolicy even if it contains read-only subdir %q", v1.PersistentVolumeReclaimDelete), func(ctx ginkgo.SpecContext) {
250250
skipIfTestingInWindowsCluster()
251251
reclaimPolicy := v1.PersistentVolumeReclaimDelete
252252
pod := testsuites.PodDetails{
@@ -286,7 +286,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
286286
test.Run(ctx, cs, ns)
287287
})
288288

289-
ginkgo.It(fmt.Sprintf("should delete PV with reclaimPolicy %q [smb.csi.k8s.io] [Windows]", v1.PersistentVolumeReclaimDelete), func(ctx ginkgo.SpecContext) {
289+
ginkgo.It(fmt.Sprintf("should delete PV with reclaimPolicy %q [Windows]", v1.PersistentVolumeReclaimDelete), func(ctx ginkgo.SpecContext) {
290290
reclaimPolicy := v1.PersistentVolumeReclaimDelete
291291
volumes := []testsuites.VolumeDetails{
292292
{
@@ -302,7 +302,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
302302
test.Run(ctx, cs, ns)
303303
})
304304

305-
ginkgo.It(fmt.Sprintf("should retain PV with reclaimPolicy %q [smb.csi.k8s.io] [Windows]", v1.PersistentVolumeReclaimRetain), func(ctx ginkgo.SpecContext) {
305+
ginkgo.It(fmt.Sprintf("should retain PV with reclaimPolicy %q [Windows]", v1.PersistentVolumeReclaimRetain), func(ctx ginkgo.SpecContext) {
306306
reclaimPolicy := v1.PersistentVolumeReclaimRetain
307307
volumes := []testsuites.VolumeDetails{
308308
{
@@ -319,7 +319,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
319319
test.Run(ctx, cs, ns)
320320
})
321321

322-
ginkgo.It("should create a pod with multiple volumes [smb.csi.k8s.io] [Windows]", func(ctx ginkgo.SpecContext) {
322+
ginkgo.It("should create a pod with multiple volumes [Windows]", func(ctx ginkgo.SpecContext) {
323323
volumes := []testsuites.VolumeDetails{}
324324
for i := 1; i <= 6; i++ {
325325
volume := testsuites.VolumeDetails{
@@ -348,7 +348,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
348348
test.Run(ctx, cs, ns)
349349
})
350350

351-
ginkgo.It("should create a pod with volume mount subpath [smb.csi.k8s.io] [Windows]", func(ctx ginkgo.SpecContext) {
351+
ginkgo.It("should create a pod with volume mount subpath [Windows]", func(ctx ginkgo.SpecContext) {
352352
pods := []testsuites.PodDetails{
353353
{
354354
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
@@ -373,7 +373,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
373373
test.Run(ctx, cs, ns)
374374
})
375375

376-
ginkgo.It("should clone a volume from an existing volume [smb.csi.k8s.io]", func(ctx ginkgo.SpecContext) {
376+
ginkgo.It("should clone a volume from an existing volume", func(ctx ginkgo.SpecContext) {
377377
skipIfTestingInWindowsCluster()
378378

379379
pod := testsuites.PodDetails{
@@ -409,7 +409,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
409409
test.Run(ctx, cs, ns)
410410
})
411411

412-
ginkgo.It("should create a volume on demand with retaining subdir on delete [smb.csi.k8s.io]", func(ctx ginkgo.SpecContext) {
412+
ginkgo.It("should create a volume on demand with retaining subdir on delete", func(ctx ginkgo.SpecContext) {
413413
pods := []testsuites.PodDetails{
414414
{
415415
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
@@ -443,7 +443,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
443443
test.Run(ctx, cs, ns)
444444
})
445445

446-
ginkgo.It("should create a volume on demand with archive on archive [smb.csi.k8s.io]", func(ctx ginkgo.SpecContext) {
446+
ginkgo.It("should create a volume on demand with archive on archive", func(ctx ginkgo.SpecContext) {
447447
pods := []testsuites.PodDetails{
448448
{
449449
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
@@ -477,7 +477,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
477477
test.Run(ctx, cs, ns)
478478
})
479479

480-
ginkgo.It("should create a volume on demand with archive on archive subDir [smb.csi.k8s.io]", func(ctx ginkgo.SpecContext) {
480+
ginkgo.It("should create a volume on demand with archive on archive subDir", func(ctx ginkgo.SpecContext) {
481481
pods := []testsuites.PodDetails{
482482
{
483483
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
@@ -510,4 +510,27 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
510510
}
511511
test.Run(ctx, cs, ns)
512512
})
513+
514+
ginkgo.It("should create a volume on demand and resize it", func(ctx ginkgo.SpecContext) {
515+
pods := []testsuites.PodDetails{
516+
{
517+
Cmd: "echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data",
518+
Volumes: []testsuites.VolumeDetails{
519+
{
520+
ClaimSize: "10Gi",
521+
VolumeMount: testsuites.VolumeMountDetails{
522+
NameGenerate: "test-volume-",
523+
MountPathGenerate: "/mnt/test-",
524+
},
525+
},
526+
},
527+
},
528+
}
529+
test := testsuites.DynamicallyProvisionedResizeVolumeTest{
530+
CSIDriver: testDriver,
531+
Pods: pods,
532+
StorageClassParameters: archiveSubDirStorageClassParameters,
533+
}
534+
test.Run(ctx, cs, ns)
535+
})
513536
})

0 commit comments

Comments
 (0)