Skip to content

Commit 0f20a96

Browse files
committed
Resizer changes and add vendored resizefs package for node level resize.
Add README changes and a user guide.
1 parent 64fecda commit 0f20a96

File tree

16 files changed

+462
-24
lines changed

16 files changed

+462
-24
lines changed

Gopkg.lock

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

README.md

+14-15
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ This plugin is compatible with CSI versions [v1.0.0](https://github.com/containe
3434

3535
### Kubernetes Compatibility
3636

37-
| GCE PD CSI Driver\Kubernetes Version | 1.10.5 - 1.11 | 1.12 | 1.13 | 1.14+
38-
|--------------------------------------|---------------|------|------|------|
39-
| v0.1.x.alpha | yes | no | no | no |
40-
| v0.2.x (alpha) | no | yes | no | no |
41-
| v0.3.x (beta) | no | no | yes | yes |
42-
| v0.4.x (beta) | no | no | yes | yes |
43-
| v0.5.x (beta) | no | no | no | yes |
44-
| dev | no | no | no | yes |
37+
| GCE PD CSI Driver\Kubernetes Version | 1.10.5 - 1.11 | 1.12 | 1.13 | 1.14 | 1.15+|
38+
|--------------------------------------|---------------|------|------|------|------|
39+
| v0.1.x.alpha | yes | no | no | no | no |
40+
| v0.2.x (alpha) | no | yes | no | no | no |
41+
| v0.3.x (beta) | no | no | yes | yes | yes |
42+
| v0.4.x (beta) | no | no | yes | yes | yes |
43+
| v0.5.x (beta) | no | no | no | yes | yes |
44+
| dev | no | no | no | no | yes |
4545

4646
### Known Issues
4747

@@ -62,14 +62,13 @@ This driver supports only one topology key:
6262
`topology.gke.io/zone`
6363
that represents availability by zone.
6464

65-
### Kubernetes Beta Features
65+
### Features in Development
6666

67-
* Topology: Requires K8s 1.14+ on Master and Nodes and PD driver v0.5.0+
68-
69-
### Kubernetes Alpha Features
70-
71-
* Snapshots: Requires K8s 1.13+ on Master and PD driver v0.3.0+ with the alpha
72-
overlay
67+
| Feature | Stage | Min Kubernetes Master Version | Min Kubernetes Nodes Version | Min Driver Version | Deployment Overlay |
68+
|-----------------|-------|-------------------------------|------------------------------|--------------------|--------------------|
69+
| Topology | Beta | 1.14 | 1.14 | v0.5.0 | Stable |
70+
| Snapshots | Alpha | 1.13 | Any | v0.3.0 | Alpha |
71+
| Resize (Expand) | Alpha | 1.14 | 1.14 | dev | Alpha |
7372

7473
### Future Features
7574

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
kind: StatefulSet
2+
apiVersion: apps/v1
3+
metadata:
4+
name: csi-gce-pd-controller
5+
spec:
6+
template:
7+
spec:
8+
containers:
9+
- name: csi-resizer
10+
imagePullPolicy: Always
11+
image: quay.io/k8scsi/csi-resizer:canary
12+
args:
13+
- "--v=5"
14+
- "--csi-address=/csi/csi.sock"
15+
volumeMounts:
16+
- name: socket-dir
17+
mountPath: /csi

deploy/kubernetes/overlays/alpha/kustomization.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ bases:
44
- ../stable
55
patches:
66
- controller_add_snapshotter.yaml
7+
- controller_add_resizer.yaml
78
patchesJson6902:
89
- target:
910
group: rbac.authorization.k8s.io
@@ -13,3 +14,4 @@ patchesJson6902:
1314
path: rbac_add_snapshots_to_provisioner.yaml
1415
resources:
1516
- rbac_add_snapshotter.yaml
17+
- rbac_add_resizer.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Resizer must be able to work with PVCs, PVs, SCs.
2+
kind: ClusterRole
3+
apiVersion: rbac.authorization.k8s.io/v1
4+
metadata:
5+
name: external-resizer-role
6+
rules:
7+
- apiGroups: [""]
8+
resources: ["persistentvolumes"]
9+
verbs: ["get", "list", "watch", "update", "patch"]
10+
- apiGroups: [""]
11+
resources: ["persistentvolumeclaims"]
12+
verbs: ["get", "list", "watch"]
13+
- apiGroups: [""]
14+
resources: ["persistentvolumeclaims/status"]
15+
verbs: ["update", "patch"]
16+
- apiGroups: [""]
17+
resources: ["events"]
18+
verbs: ["list", "watch", "create", "update", "patch"]
19+
20+
---
21+
kind: ClusterRoleBinding
22+
apiVersion: rbac.authorization.k8s.io/v1
23+
metadata:
24+
name: csi-resizer-role
25+
subjects:
26+
- kind: ServiceAccount
27+
name: csi-controller-sa
28+
namespace: default
29+
roleRef:
30+
kind: ClusterRole
31+
name: external-resizer-role
32+
apiGroup: rbac.authorization.k8s.io

docs/kubernetes/user-guides/resize.md

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Kubernetes Resize User Guide (Alpha)
2+
3+
>**Attention:** Volume Resize is an alpha feature. Make sure you have enabled it in Kubernetes API server using `--feature-gates=ExpandCSIVolumes=true` flag.
4+
>**Attention:** Volume Resize is only available in the driver version v0.6.0+
5+
6+
### Install Driver with alpha resize feature
7+
8+
1. [One-time per project] Create GCP service account for the CSI driver and set required roles
9+
10+
```
11+
$ PROJECT=your-project-here # GCP project
12+
$ GCE_PD_SA_NAME=my-gce-pd-csi-sa # Name of the service account to create
13+
$ GCE_PD_SA_DIR=/my/safe/credentials/directory # Directory to save the service account key
14+
$ ./deploy/setup-project.sh
15+
```
16+
17+
2. Deploy driver to Kubernetes Cluster
18+
19+
```
20+
$ GCE_PD_SA_DIR=/my/safe/credentials/directory # Directory to get the service account key
21+
$ GCE_PD_DRIVER_VERSION=alpha # Driver version to deploy
22+
$ ./deploy/kubernetes/deploy-driver.sh
23+
```
24+
25+
### Resize Example
26+
27+
This example provisions a zonal PD in both single-zone and regional clusters.
28+
29+
1. Add resize field to example Zonal Storage Class
30+
```
31+
apiVersion: storage.k8s.io/v1
32+
kind: StorageClass
33+
metadata:
34+
name: csi-gce-pd
35+
provisioner: pd.csi.storage.gke.io
36+
parameters:
37+
type: pd-standard
38+
volumeBindingMode: WaitForFirstConsumer
39+
allowVolumeExpansion: true
40+
```
41+
42+
2. Create example Zonal Storage Class with resize enabled
43+
```
44+
$ kubectl apply -f ./examples/kubernetes/demo-zonal-sc.yaml
45+
```
46+
47+
3. Create example PVC and Pod
48+
```
49+
$ kubectl apply -f ./examples/kubernetes/demo-pod.yaml
50+
```
51+
52+
4. Verify PV is created and bound to PVC
53+
```
54+
$ kubectl get pvc
55+
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
56+
podpvc Bound pvc-e36abf50-84f3-11e8-8538-42010a800002 10Gi RWO csi-gce-pd 9s
57+
```
58+
59+
5. Verify pod is created and in `RUNNING` state (it may take a few minutes to get to running state)
60+
```
61+
$ kubectl get pods
62+
NAME READY STATUS RESTARTS AGE
63+
web-server 1/1 Running 0 1m
64+
```
65+
66+
8. Check current filesystem size on the running pod
67+
```
68+
$ kubectl exec web-server -- df -h /var/lib/www/html
69+
Filesystem Size Used Avail Use% Mounted on
70+
/dev/sdb 5.9G 24M 5.9G 1% /var/lib/www/html
71+
```
72+
73+
6. Resize volume by modifying the field `spec -> resources -> requests -> storage`
74+
```
75+
$ kubectl edit pvc podpvc
76+
apiVersion: v1
77+
kind: PersistentVolumeClaim
78+
...
79+
spec:
80+
resources:
81+
requests:
82+
storage: 9Gi
83+
...
84+
...
85+
```
86+
87+
7. Verify actual disk resized on cloud
88+
```
89+
$ gcloud compute disks describe ${disk_name} --zone=${zone}
90+
description: Disk created by GCE-PD CSI Driver
91+
name: pvc-10ea155f-e5a4-4a82-a171-21481742c80c
92+
...
93+
sizeGb: '9'
94+
```
95+
96+
8. Verify filesystem resized on the running pod
97+
```
98+
$ kubectl exec web-server -- df -h /var/lib/www/html
99+
Filesystem Size Used Avail Use% Mounted on
100+
/dev/sdb 8.8G 27M 8.8G 1% /var/lib/www/html
101+
```

pkg/gce-cloud-provider/compute/cloud-disk.go

+11
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,17 @@ func (d *CloudDisk) GetSizeGb() int64 {
124124
}
125125
}
126126

127+
// setSizeGb sets the size of the disk used ONLY
128+
// for testing purposes.
129+
func (d *CloudDisk) setSizeGb(size int64) {
130+
switch d.Type() {
131+
case Zonal:
132+
d.ZonalDisk.SizeGb = size
133+
case Regional:
134+
d.RegionalDisk.SizeGb = size
135+
}
136+
}
137+
127138
func (d *CloudDisk) GetZone() string {
128139
switch d.Type() {
129140
case Zonal:

pkg/gce-cloud-provider/compute/fake-gce.go

+12
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,18 @@ func (cloud *FakeCloudProvider) CreateSnapshot(ctx context.Context, volKey *meta
368368
return snapshotToCreate, nil
369369
}
370370

371+
func (cloud *FakeCloudProvider) ResizeDisk(ctx context.Context, volKey *meta.Key, requestBytes int64) (int64, error) {
372+
disk, ok := cloud.disks[volKey.Name]
373+
if !ok {
374+
return -1, notFoundError()
375+
}
376+
377+
disk.setSizeGb(common.BytesToGb(requestBytes))
378+
379+
return requestBytes, nil
380+
381+
}
382+
371383
// Snapshot Methods
372384
func (cloud *FakeCloudProvider) DeleteSnapshot(ctx context.Context, snapshotName string) error {
373385
delete(cloud.snapshots, snapshotName)

pkg/gce-cloud-provider/compute/gce-compute.go

+60
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type GCECompute interface {
5050
GetDiskSourceURI(volKey *meta.Key) string
5151
GetDiskTypeURI(volKey *meta.Key, diskType string) string
5252
WaitForAttach(ctx context.Context, volKey *meta.Key, instanceZone, instanceName string) error
53+
ResizeDisk(ctx context.Context, volKey *meta.Key, requestBytes int64) (int64, error)
5354
// Regional Disk Methods
5455
GetReplicaZoneURI(zone string) string
5556
// Instance Methods
@@ -593,6 +594,65 @@ func (cloud *CloudProvider) CreateSnapshot(ctx context.Context, volKey *meta.Key
593594
}
594595
}
595596

597+
func (cloud *CloudProvider) ResizeDisk(ctx context.Context, volKey *meta.Key, requestBytes int64) (int64, error) {
598+
cloudDisk, err := cloud.GetDisk(ctx, volKey)
599+
if err != nil {
600+
return -1, fmt.Errorf("failed to get disk: %v", err)
601+
}
602+
603+
sizeGb := cloudDisk.GetSizeGb()
604+
requestGb := common.BytesToGb(requestBytes)
605+
606+
// If disk is already of size equal or greater than requested size, we simply return
607+
if sizeGb >= requestGb {
608+
return requestBytes, nil
609+
}
610+
611+
switch volKey.Type() {
612+
case meta.Zonal:
613+
return cloud.resizeZonalDisk(ctx, volKey, requestGb)
614+
case meta.Regional:
615+
return cloud.resizeRegionalDisk(ctx, volKey, requestGb)
616+
default:
617+
return -1, fmt.Errorf("could not resize disk, key was neither zonal nor regional, instead got: %v", volKey.String())
618+
}
619+
}
620+
621+
func (cloud *CloudProvider) resizeZonalDisk(ctx context.Context, volKey *meta.Key, requestGb int64) (int64, error) {
622+
resizeReq := &compute.DisksResizeRequest{
623+
SizeGb: requestGb,
624+
}
625+
op, err := cloud.service.Disks.Resize(cloud.project, volKey.Zone, volKey.Name, resizeReq).Context(ctx).Do()
626+
if err != nil {
627+
return -1, fmt.Errorf("failed to resize zonal volume %v: %v", volKey.String(), err)
628+
}
629+
630+
err = cloud.waitForZonalOp(ctx, op, volKey.Zone)
631+
if err != nil {
632+
return -1, fmt.Errorf("failed waiting for op for zonal resize for %s: %v", volKey.String(), err)
633+
}
634+
635+
return requestGb, nil
636+
}
637+
638+
func (cloud *CloudProvider) resizeRegionalDisk(ctx context.Context, volKey *meta.Key, requestGb int64) (int64, error) {
639+
resizeReq := &computebeta.RegionDisksResizeRequest{
640+
SizeGb: requestGb,
641+
}
642+
643+
op, err := cloud.betaService.RegionDisks.Resize(cloud.project, volKey.Region, volKey.Name, resizeReq).Context(ctx).Do()
644+
if err != nil {
645+
return -1, fmt.Errorf("failed to resize regional volume %v: %v", volKey.String(), err)
646+
}
647+
648+
err = cloud.waitForRegionalOp(ctx, op, volKey.Region)
649+
if err != nil {
650+
return -1, fmt.Errorf("failed waiting for op for regional resize for %s: %v", volKey.String(), err)
651+
}
652+
653+
return requestGb, nil
654+
}
655+
596656
func (cloud *CloudProvider) createZonalDiskSnapshot(ctx context.Context, volKey *meta.Key, snapshotName string) (*compute.Snapshot, error) {
597657
snapshotToCreate := &compute.Snapshot{
598658
Name: snapshotName,

pkg/gce-pd-csi-driver/controller.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,30 @@ func (gceCS *GCEControllerServer) ListSnapshots(ctx context.Context, req *csi.Li
614614
}
615615

616616
func (gceCS *GCEControllerServer) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) {
617-
return nil, status.Error(codes.Unimplemented, "ControllerExpandVolume is not yet implemented")
617+
volumeID := req.GetVolumeId()
618+
if len(volumeID) == 0 {
619+
return nil, status.Error(codes.InvalidArgument, "ControllerExpandVolume volume ID must be provided")
620+
}
621+
capacityRange := req.GetCapacityRange()
622+
reqBytes, err := getRequestCapacity(capacityRange)
623+
if err != nil {
624+
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("ControllerExpandVolume capacity range is invalid: %v", err))
625+
}
626+
627+
volKey, err := common.VolumeIDToKey(volumeID)
628+
if err != nil {
629+
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("ControllerExpandVolume volume ID is invalid: %v", err))
630+
}
631+
632+
resizedGb, err := gceCS.CloudProvider.ResizeDisk(ctx, volKey, reqBytes)
633+
if err != nil {
634+
return nil, status.Error(codes.Internal, fmt.Sprintf("ControllerExpandVolume failed to resize disk: %v", err))
635+
}
636+
637+
return &csi.ControllerExpandVolumeResponse{
638+
CapacityBytes: common.GbToBytes(resizedGb),
639+
NodeExpansionRequired: true,
640+
}, nil
618641
}
619642

620643
func (gceCS *GCEControllerServer) getSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {

pkg/gce-pd-csi-driver/gce-pd-driver.go

+2
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ func (gceDriver *GCEDriver) SetupGCEDriver(cloudProvider gce.GCECompute, mounter
6565
csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
6666
csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
6767
csi.ControllerServiceCapability_RPC_PUBLISH_READONLY,
68+
csi.ControllerServiceCapability_RPC_EXPAND_VOLUME,
6869
}
6970
gceDriver.AddControllerServiceCapabilities(csc)
7071
ns := []csi.NodeServiceCapability_RPC_Type{
7172
csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
73+
csi.NodeServiceCapability_RPC_EXPAND_VOLUME,
7274
}
7375
gceDriver.AddNodeServiceCapabilities(ns)
7476

0 commit comments

Comments
 (0)