Skip to content

Commit 1c9eb58

Browse files
authored
Merge pull request #1801 from travisyx/master
Add ControllerModifyVolume functionality
2 parents dbd3bfa + 002eb8c commit 1c9eb58

File tree

28 files changed

+1064
-153
lines changed

28 files changed

+1064
-153
lines changed

cmd/gce-pd-csi-driver/main.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ var (
8484
useInstanceAPIForListVolumesPublishedNodesFlag = flag.Bool("use-instance-api-to-list-volumes-published-nodes", false, "Enables using the instances.list API to determine published_node_ids in ListVolumes. When false (default), the disks.list API is used")
8585
instancesListFiltersFlag = flag.String("instances-list-filters", "", "Comma separated list of filters to use when calling the instances.list API. By default instances.list fetches all instances in a region")
8686

87+
diskSupportsIopsChangeFlag = flag.String("supports-dynamic-iops-provisioning", "", "Comma separated list of disk types that support dynamic IOPS provisioning")
88+
diskSupportsThroughputChangeFlag = flag.String("supports-dynamic-throughput-provisioning", "", "Comma separated list of disk types that support dynamic throughput provisioning")
89+
8790
extraTagsStr = flag.String("extra-tags", "", "Extra tags to attach to each Compute Disk, Image, Snapshot created. It is a comma separated list of parent id, key and value like '<parent_id1>/<tag_key1>/<tag_value1>,...,<parent_idN>/<tag_keyN>/<tag_valueN>'. parent_id is the Organization or the Project ID or Project name where the tag key and the tag value resources exist. A maximum of 50 tags bindings is allowed for a resource. See https://cloud.google.com/resource-manager/docs/tags/tags-overview, https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing for details")
8891

8992
version string
@@ -200,6 +203,14 @@ func handle() {
200203
UseInstancesAPIForPublishedNodes: *useInstanceAPIForListVolumesPublishedNodesFlag,
201204
}
202205

206+
// Initialize provisionableDisks config
207+
supportsIopsChange := parseCSVFlag(*diskSupportsIopsChangeFlag)
208+
supportsThroughputChange := parseCSVFlag(*diskSupportsThroughputChangeFlag)
209+
provisionableDisksConfig := driver.ProvisionableDisksConfig{
210+
SupportsIopsChange: supportsIopsChange,
211+
SupportsThroughputChange: supportsThroughputChange,
212+
}
213+
203214
// Initialize requirements for the controller service
204215
var controllerServer *driver.GCEControllerServer
205216
if *runControllerService {
@@ -209,7 +220,7 @@ func handle() {
209220
}
210221
initialBackoffDuration := time.Duration(*errorBackoffInitialDurationMs) * time.Millisecond
211222
maxBackoffDuration := time.Duration(*errorBackoffMaxDurationMs) * time.Millisecond
212-
controllerServer = driver.NewControllerServer(gceDriver, cloudProvider, initialBackoffDuration, maxBackoffDuration, fallbackRequisiteZones, *enableStoragePoolsFlag, multiZoneVolumeHandleConfig, listVolumesConfig)
223+
controllerServer = driver.NewControllerServer(gceDriver, cloudProvider, initialBackoffDuration, maxBackoffDuration, fallbackRequisiteZones, *enableStoragePoolsFlag, multiZoneVolumeHandleConfig, listVolumesConfig, provisionableDisksConfig)
213224
} else if *cloudConfigFilePath != "" {
214225
klog.Warningf("controller service is disabled but cloud config given - it has no effect")
215226
}

deploy/kubernetes/base/controller/cluster_setup.yaml

+8-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ rules:
3434
- apiGroups: ["storage.k8s.io"]
3535
resources: ["storageclasses"]
3636
verbs: ["get", "list", "watch"]
37+
- apiGroups: ["storage.k8s.io"]
38+
resources: ["volumeattributesclasses"]
39+
verbs: ["get", "list", "watch"]
3740
- apiGroups: [""]
3841
resources: ["events"]
3942
verbs: ["list", "watch", "create", "update", "patch"]
@@ -69,7 +72,7 @@ roleRef:
6972
kind: ClusterRole
7073
name: csi-gce-pd-provisioner-role
7174
apiGroup: rbac.authorization.k8s.io
72-
75+
7376
---
7477
# xref: https://github.com/kubernetes-csi/external-attacher/blob/master/deploy/kubernetes/rbac.yaml
7578
kind: ClusterRole
@@ -143,6 +146,9 @@ rules:
143146
- apiGroups: [""]
144147
resources: ["persistentvolumeclaims/status"]
145148
verbs: ["update", "patch"]
149+
- apiGroups: ["storage.k8s.io"]
150+
resources: ["volumeattributesclasses"]
151+
verbs: ["get", "list", "watch"]
146152
- apiGroups: [""]
147153
resources: ["events"]
148154
verbs: ["list", "watch", "create", "update", "patch"]
@@ -312,4 +318,4 @@ subjects:
312318
roleRef:
313319
kind: Role
314320
name: csi-gce-pd-leaderelection-role
315-
apiGroup: rbac.authorization.k8s.io
321+
apiGroup: rbac.authorization.k8s.io

deploy/kubernetes/base/controller/controller.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ spec:
3737
- "--leader-election"
3838
- "--default-fstype=ext4"
3939
- "--controller-publish-readonly=true"
40+
- "--feature-gates=VolumeAttributesClass=true"
4041
env:
4142
- name: PDCSI_NAMESPACE
4243
valueFrom:
@@ -95,6 +96,7 @@ spec:
9596
- "--leader-election"
9697
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
9798
- "--handle-volume-inuse-error=false"
99+
- "--feature-gates=VolumeAttributesClass=true"
98100
env:
99101
- name: PDCSI_NAMESPACE
100102
valueFrom:

deploy/kubernetes/images/stable-master/image.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ metadata:
44
name: imagetag-csi-provisioner
55
imageTag:
66
name: registry.k8s.io/sig-storage/csi-provisioner
7-
newTag: "v3.6.3"
7+
newTag: "v5.1.0"
88

99
---
1010
apiVersion: builtin
@@ -22,7 +22,7 @@ metadata:
2222
name: imagetag-csi-resizer
2323
imageTag:
2424
name: registry.k8s.io/sig-storage/csi-resizer
25-
newTag: "v1.9.3"
25+
newTag: "v1.11.1"
2626
---
2727

2828
apiVersion: builtin

deploy/kubernetes/overlays/dev/controller_always_pull.yaml

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ spec:
77
spec:
88
containers:
99
- name: gce-pd-driver
10-
imagePullPolicy: Always
11-
10+
imagePullPolicy: Always
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- op: add
2+
path: /spec/template/spec/containers/0/args/-
3+
value: --supports-dynamic-throughput-provisioning=hyperdisk-balanced,hyperdisk-throughput,hyperdisk-ml
4+
5+
- op: add
6+
path: /spec/template/spec/containers/0/args/-
7+
value: --supports-dynamic-iops-provisioning=hyperdisk-balanced,hyperdisk-extreme

deploy/kubernetes/overlays/dev/kustomization.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ resources:
99
# Here dev overlay is using the same image as alpha
1010
transformers:
1111
- ../../images/stable-master
12+
# Apply patches to support dynamic provisioning for hyperdisks
13+
patches:
14+
- path: ./driver-args.yaml
15+
target:
16+
group: apps
17+
version: v1
18+
kind: Deployment
19+
name: csi-gce-pd-controller
1220
# To change the dev image, add something like the following.
1321
#images:
1422
#- name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
apiVersion: storage.k8s.io/v1beta1
2+
kind: VolumeAttributesClass
3+
metadata:
4+
name: silver
5+
driverName: pd.csi.storage.gke.io
6+
parameters:
7+
throughput: "350"
8+
iops: "6000"
9+
---
10+
apiVersion: storage.k8s.io/v1beta1
11+
kind: VolumeAttributesClass
12+
metadata:
13+
name: gold
14+
driverName: pd.csi.storage.gke.io
15+
parameters:
16+
throughput: "550"
17+
iops: "15000"
18+
---
19+
apiVersion: storage.k8s.io/v1
20+
kind: StorageClass
21+
metadata:
22+
name: balanced
23+
provisioner: pd.csi.storage.gke.io
24+
allowVolumeExpansion: true
25+
volumeBindingMode: WaitForFirstConsumer
26+
parameters:
27+
type: hyperdisk-balanced
28+
provisioned-throughput-on-create: "300Mi"
29+
provisioned-iops-on-create: "5000"
30+
---
31+
apiVersion: storage.k8s.io/v1
32+
kind: StorageClass
33+
metadata:
34+
name: throughput-optimized
35+
provisioner: pd.csi.storage.gke.io
36+
volumeBindingMode: WaitForFirstConsumer
37+
allowVolumeExpansion: true
38+
parameters:
39+
type: hyperdisk-balanced
40+
provisioned-throughput-on-create: "500Mi"
41+
provisioned-iops-on-create: "10000"
42+
43+
---
44+
apiVersion: v1
45+
kind: PersistentVolumeClaim
46+
metadata:
47+
name: balanced-pvc
48+
spec:
49+
volumeAttributesClassName: silver
50+
storageClassName: balanced
51+
accessModes:
52+
- ReadWriteOnce
53+
resources:
54+
requests:
55+
storage: 256Gi
56+
---
57+
apiVersion: v1
58+
kind: PersistentVolumeClaim
59+
metadata:
60+
name: throughput-optimized-pvc
61+
spec:
62+
volumeAttributesClassName: silver
63+
storageClassName: throughput-optimized
64+
accessModes:
65+
- ReadWriteOnce
66+
resources:
67+
requests:
68+
storage: 256Gi
69+
---
70+
kind: Pod
71+
apiVersion: v1
72+
metadata:
73+
name: pod-demo
74+
spec:
75+
volumes:
76+
- name: pvc-demo-vol
77+
persistentVolumeClaim:
78+
claimName: balanced-pvc
79+
- name: data-vol
80+
persistentVolumeClaim:
81+
claimName: throughput-optimized-pvc
82+
containers:
83+
- name: pod-demo
84+
image: nginx:latest
85+
resources:
86+
limits:
87+
cpu: 10m
88+
memory: 80Mi
89+
requests:
90+
cpu: 10m
91+
memory: 80Mi
92+
ports:
93+
- containerPort: 80
94+
name: "http-server"
95+
volumeMounts:
96+
- mountPath: "/usr/share/nginx/html"
97+
name: pvc-demo-vol
98+
- mountPath: "/data"
99+
name: data-vol

pkg/common/parameters.go

+30
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ type ParameterProcessor struct {
131131
EnableMultiZone bool
132132
}
133133

134+
type ModifyVolumeParameters struct {
135+
IOPS *int64
136+
Throughput *int64
137+
}
138+
134139
// ExtractAndDefaultParameters will take the relevant parameters from a map and
135140
// put them into a well defined struct making sure to default unspecified fields.
136141
// extraVolumeLabels are added as labels; if there are also labels specified in
@@ -324,3 +329,28 @@ func extractResourceTagsParameter(tagsString string, resourceTags map[string]str
324329
}
325330
return nil
326331
}
332+
333+
func ExtractModifyVolumeParameters(parameters map[string]string) (ModifyVolumeParameters, error) {
334+
335+
modifyVolumeParams := ModifyVolumeParameters{}
336+
337+
for key, value := range parameters {
338+
switch strings.ToLower(key) {
339+
case "iops":
340+
iops, err := ConvertStringToInt64(value)
341+
if err != nil {
342+
return ModifyVolumeParameters{}, fmt.Errorf("parameters contain invalid iops parameter: %w", err)
343+
}
344+
modifyVolumeParams.IOPS = &iops
345+
case "throughput":
346+
throughput, err := ConvertStringToInt64(value)
347+
if err != nil {
348+
return ModifyVolumeParameters{}, fmt.Errorf("parameters contain invalid throughput parameter: %w", err)
349+
}
350+
modifyVolumeParams.Throughput = &throughput
351+
default:
352+
return ModifyVolumeParameters{}, fmt.Errorf("parameters contain unknown parameter: %s", key)
353+
}
354+
}
355+
return modifyVolumeParams, nil
356+
}

pkg/common/parameters_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,25 @@ func TestSnapshotParameters(t *testing.T) {
482482
})
483483
}
484484
}
485+
func TestExtractModifyVolumeParameters(t *testing.T) {
486+
parameters := map[string]string{
487+
"iops": "1000",
488+
"throughput": "500",
489+
}
490+
491+
iops := int64(1000)
492+
throughput := int64(500)
493+
expected := ModifyVolumeParameters{
494+
IOPS: &iops,
495+
Throughput: &throughput,
496+
}
497+
498+
result, err := ExtractModifyVolumeParameters(parameters)
499+
if err != nil {
500+
t.Errorf("Unexpected error: %v", err)
501+
}
502+
503+
if !reflect.DeepEqual(result, expected) {
504+
t.Errorf("Got ExtractModifyVolumeParameters(%+v) = %+v; want: %v", parameters, result, expected)
505+
}
506+
}

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

+22
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,25 @@ func (d *CloudDisk) GetAccessMode() string {
267267
return ""
268268
}
269269
}
270+
271+
func (d *CloudDisk) GetProvisionedIops() int64 {
272+
switch {
273+
case d.disk != nil:
274+
return d.disk.ProvisionedIops
275+
case d.betaDisk != nil:
276+
return d.betaDisk.ProvisionedIops
277+
default:
278+
return 0
279+
}
280+
}
281+
282+
func (d *CloudDisk) GetProvisionedThroughput() int64 {
283+
switch {
284+
case d.disk != nil:
285+
return d.disk.ProvisionedThroughput
286+
case d.betaDisk != nil:
287+
return d.betaDisk.ProvisionedThroughput
288+
default:
289+
return 0
290+
}
291+
}

0 commit comments

Comments
 (0)