Skip to content

Commit 230545f

Browse files
committed
Cleanup ControllerModifyVolume logic and add e2e tests
1 parent c72a290 commit 230545f

File tree

355 files changed

+17394
-18611
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

355 files changed

+17394
-18611
lines changed

Dockerfile

+24-9
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
FROM --platform=$BUILDPLATFORM golang:1.22.3 as builder
15+
FROM --platform=$BUILDPLATFORM golang:1.23.0 as builder
1616

1717
ARG STAGINGVERSION
1818
ARG TARGETPLATFORM
@@ -22,13 +22,15 @@ ADD . .
2222
RUN GOARCH=$(echo $TARGETPLATFORM | cut -f2 -d '/') GCE_PD_CSI_STAGING_VERSION=$STAGINGVERSION make gce-pd-driver
2323

2424
# Start from Kubernetes Debian base.
25-
FROM gke.gcr.io/debian-base:bullseye-v1.4.3-gke.5 as debian
25+
26+
FROM gke.gcr.io/debian-base:bookworm-v1.0.3-gke.0 as debian
27+
2628
# Install necessary dependencies
2729
# google_nvme_id script depends on the following packages: nvme-cli, xxd, bash
2830
RUN clean-install util-linux e2fsprogs mount ca-certificates udev xfsprogs nvme-cli xxd bash
2931

3032
# Since we're leveraging apt to pull in dependencies, we use `gcr.io/distroless/base` because it includes glibc.
31-
FROM gcr.io/distroless/base-debian11 as distroless-base
33+
FROM gcr.io/distroless/base-debian12 as distroless-base
3234

3335
# The distroless amd64 image has a target triplet of x86_64
3436
FROM distroless-base AS distroless-amd64
@@ -72,8 +74,7 @@ COPY --from=debian /bin/ln /bin/ln
7274
COPY --from=debian /bin/udevadm /bin/udevadm
7375

7476
# Copy shared libraries into distroless base.
75-
COPY --from=debian /lib/${LIB_DIR_PREFIX}-linux-gnu/libpcre.so.3 \
76-
/lib/${LIB_DIR_PREFIX}-linux-gnu/libselinux.so.1 \
77+
COPY --from=debian /lib/${LIB_DIR_PREFIX}-linux-gnu/libselinux.so.1 \
7778
/lib/${LIB_DIR_PREFIX}-linux-gnu/libtinfo.so.6 \
7879
/lib/${LIB_DIR_PREFIX}-linux-gnu/libe2p.so.2 \
7980
/lib/${LIB_DIR_PREFIX}-linux-gnu/libcom_err.so.2 \
@@ -82,7 +83,21 @@ COPY --from=debian /lib/${LIB_DIR_PREFIX}-linux-gnu/libpcre.so.3 \
8283
/lib/${LIB_DIR_PREFIX}-linux-gnu/libgcc_s.so.1 \
8384
/lib/${LIB_DIR_PREFIX}-linux-gnu/liblzma.so.5 \
8485
/lib/${LIB_DIR_PREFIX}-linux-gnu/libreadline.so.8 \
85-
/lib/${LIB_DIR_PREFIX}-linux-gnu/libz.so.1 /lib/${LIB_DIR_PREFIX}-linux-gnu/
86+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libz.so.1 \
87+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libc.so.6 \
88+
/lib/${LIB_DIR_PREFIX}-linux-gnu/liburcu.so.8 \
89+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libcap.so.2 \
90+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libcrypto.so.3 \
91+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libdbus-1.so.3 \
92+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libgcrypt.so.20 \
93+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libjson-c.so.5 \
94+
/lib/${LIB_DIR_PREFIX}-linux-gnu/liblz4.so.1 \
95+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libm.so.6 \
96+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libnvme-mi.so.1 \
97+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libnvme.so.1 \
98+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libsystemd.so.0 \
99+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libgpg-error.so.0 \
100+
/lib/${LIB_DIR_PREFIX}-linux-gnu/libzstd.so.1 /lib/${LIB_DIR_PREFIX}-linux-gnu/
86101

87102
COPY --from=debian /usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libblkid.so.1 \
88103
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libbsd.so.0 \
@@ -93,9 +108,9 @@ COPY --from=debian /usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libblkid.so.1 \
93108
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libacl.so.1 \
94109
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libattr.so.1 \
95110
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libedit.so.2 \
96-
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libicudata.so.67 \
97-
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libicui18n.so.67 \
98-
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libicuuc.so.67 \
111+
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libicudata.so.72 \
112+
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libicui18n.so.72 \
113+
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libicuuc.so.72 \
99114
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libkmod.so.2 \
100115
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libmd.so.0 \
101116
/usr/lib/${LIB_DIR_PREFIX}-linux-gnu/libpcre2-8.so.0 \

Dockerfile.Windows

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
ARG BASE_IMAGE
16-
FROM --platform=$BUILDPLATFORM golang:1.22.3 AS builder
16+
FROM --platform=$BUILDPLATFORM golang:1.23.0 AS builder
1717

1818
ARG TARGETPLATFORM
1919
ARG STAGINGVERSION

Dockerfile.debug

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
FROM golang:1.22.3 as builder
15+
FROM golang:1.23.0 as builder
1616
WORKDIR /go/src/sigs.k8s.io/gcp-compute-persistent-disk-csi-driver
1717
ADD . .
1818

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ init-buildx:
126126
$(DOCKER) run --rm --privileged multiarch/qemu-user-static --reset --credential yes --persistent yes
127127
# Ensure we use a builder that can leverage it (the default on linux will not)
128128
-$(DOCKER) buildx rm multiarch-multiplatform-builder
129-
$(DOCKER) buildx create --use --name=multiarch-multiplatform-builder --driver-opt network=host --driver-opt image=moby/buildkit:v0.11.3
129+
$(DOCKER) buildx create --use --name=multiarch-multiplatform-builder --driver-opt network=host --driver-opt image=moby/buildkit:v0.14.1
130130
# Register gcloud as a Docker credential helper.
131131
# Required for "docker buildx build --push".
132132
gcloud auth configure-docker --quiet

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

+53-11
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"time"
2929

3030
"k8s.io/klog/v2"
31+
"k8s.io/utils/strings/slices"
3132

3233
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common"
3334
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/deviceutils"
@@ -83,6 +84,9 @@ var (
8384
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")
8485
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")
8586

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+
8690
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")
8791

8892
version string
@@ -98,7 +102,7 @@ func init() {
98102
// Use V(4) for general debug information logging
99103
// Use V(5) for GCE Cloud Provider Call informational logging
100104
// Use V(6) for extra repeated/polling information
101-
enumFlag(&computeEnvironment, "compute-environment", allowedComputeEnvironment, "Operating compute environment")
105+
stringEnumFlag(&computeEnvironment, "compute-environment", allowedComputeEnvironment, "Operating compute environment")
102106
urlFlag(&computeEndpoint, "compute-endpoint", "Compute endpoint")
103107
klog.InitFlags(flag.CommandLine)
104108
flag.Set("logtostderr", "true")
@@ -175,30 +179,38 @@ func handle() {
175179
identityServer := driver.NewIdentityServer(gceDriver)
176180

177181
// Initialize requisite zones
178-
fallbackRequisiteZones := strings.Split(*fallbackRequisiteZonesFlag, ",")
182+
fallbackRequisiteZones := parseCSVFlag(*fallbackRequisiteZonesFlag)
179183

180184
// Initialize multi-zone disk types
181-
multiZoneVolumeHandleDiskTypes := strings.Split(*multiZoneVolumeHandleDiskTypesFlag, ",")
185+
multiZoneVolumeHandleDiskTypes := parseCSVFlag(*multiZoneVolumeHandleDiskTypesFlag)
182186
multiZoneVolumeHandleConfig := driver.MultiZoneVolumeHandleConfig{
183187
Enable: *multiZoneVolumeHandleEnableFlag,
184188
DiskTypes: multiZoneVolumeHandleDiskTypes,
185189
}
186190

187191
// Initialize waitForAttach config
188-
useInstanceAPIOnWaitForAttachDiskTypes := strings.Split(*useInstanceAPIOnWaitForAttachDiskTypesFlag, ",")
192+
useInstanceAPIOnWaitForAttachDiskTypes := parseCSVFlag(*useInstanceAPIOnWaitForAttachDiskTypesFlag)
189193
waitForAttachConfig := gce.WaitForAttachConfig{
190194
UseInstancesAPIForDiskTypes: useInstanceAPIOnWaitForAttachDiskTypes,
191195
}
192196

193197
// Initialize listVolumes config
194-
instancesListFilters := strings.Split(*instancesListFiltersFlag, ",")
198+
instancesListFilters := parseCSVFlag(*instancesListFiltersFlag)
195199
listInstancesConfig := gce.ListInstancesConfig{
196200
Filters: instancesListFilters,
197201
}
198202
listVolumesConfig := driver.ListVolumesConfig{
199203
UseInstancesAPIForPublishedNodes: *useInstanceAPIForListVolumesPublishedNodesFlag,
200204
}
201205

206+
// Initialize provisionableDisks config
207+
supportsIopsChange := parseCSVFlag(*diskSupportsIopsChangeFlag)
208+
supportsThroughputChange := parseCSVFlag(*diskSupportsThroughputChangeFlag)
209+
provisionableDisksConfig := driver.ProvisionableDisksConfig{
210+
SupportsIopsChange: supportsIopsChange,
211+
SupportsThroughputChange: supportsThroughputChange,
212+
}
213+
202214
// Initialize requirements for the controller service
203215
var controllerServer *driver.GCEControllerServer
204216
if *runControllerService {
@@ -208,7 +220,7 @@ func handle() {
208220
}
209221
initialBackoffDuration := time.Duration(*errorBackoffInitialDurationMs) * time.Millisecond
210222
maxBackoffDuration := time.Duration(*errorBackoffMaxDurationMs) * time.Millisecond
211-
controllerServer = driver.NewControllerServer(gceDriver, cloudProvider, initialBackoffDuration, maxBackoffDuration, fallbackRequisiteZones, *enableStoragePoolsFlag, multiZoneVolumeHandleConfig, listVolumesConfig)
223+
controllerServer = driver.NewControllerServer(gceDriver, cloudProvider, initialBackoffDuration, maxBackoffDuration, fallbackRequisiteZones, *enableStoragePoolsFlag, multiZoneVolumeHandleConfig, listVolumesConfig, provisionableDisksConfig)
212224
} else if *cloudConfigFilePath != "" {
213225
klog.Warningf("controller service is disabled but cloud config given - it has no effect")
214226
}
@@ -252,18 +264,48 @@ func handle() {
252264
gceDriver.Run(*endpoint, *grpcLogCharCap, *enableOtelTracing)
253265
}
254266

255-
func enumFlag(target *gce.Environment, name string, allowedComputeEnvironment []gce.Environment, usage string) {
267+
func notEmpty(v string) bool {
268+
return v != ""
269+
}
270+
271+
func parseCSVFlag(list string) []string {
272+
return slices.Filter(nil, strings.Split(list, ","), notEmpty)
273+
}
274+
275+
type enumConverter[T any] interface {
276+
convert(v string) (T, error)
277+
eq(a, b T) bool
278+
}
279+
280+
type stringConverter[T ~string] struct{}
281+
282+
func (s stringConverter[T]) convert(v string) (T, error) {
283+
return T(v), nil
284+
}
285+
286+
func (s stringConverter[T]) eq(a, b T) bool {
287+
return a == b
288+
}
289+
290+
func stringEnumFlag[T ~string](target *T, name string, allowed []T, usage string) {
291+
enumFlag(target, name, stringConverter[T]{}, allowed, usage)
292+
}
293+
294+
func enumFlag[T any](target *T, name string, converter enumConverter[T], allowed []T, usage string) {
256295
flag.Func(name, usage, func(flagValue string) error {
257-
for _, allowedValue := range allowedComputeEnvironment {
258-
if gce.Environment(flagValue) == allowedValue {
259-
*target = gce.Environment(flagValue)
296+
tValue, err := converter.convert(flagValue)
297+
if err != nil {
298+
return err
299+
}
300+
for _, allowedValue := range allowed {
301+
if converter.eq(allowedValue, tValue) {
302+
*target = tValue
260303
return nil
261304
}
262305
}
263306
errMsg := fmt.Sprintf(`must be one of %v`, allowedComputeEnvironment)
264307
return errors.New(errMsg)
265308
})
266-
267309
}
268310

269311
func urlFlag(target **url.URL, name string, usage string) {

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/prow-stable-sidecar-rc-master/image.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ metadata:
4848
imageTag:
4949
name: registry.k8s.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
5050
newName: gcr.io/k8s-staging-cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
51-
newTag: "v1.13.3-rc1"
51+
newTag: "v1.14.2-rc1"
5252
---
5353

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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Hyperdisk Storage Pools User Guide
2+
3+
Provisioning attached disks in Storage Pools is supported in the managed version of our driver which is automatically enabled on new GKE clusters, and in a manually deployed GCE PD CSI Driver. We recommend using this feature with the managed GCE PD CSI Driver. See the public documentation [here](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/hyperdisk-storage-pools).
4+
5+
If you would like to use Storage Pools with a manual deployment of the GCE PD CSI driver, you will need to do a couple additional things to enable the feature as described below.
6+
7+
### Enabling Storage Pools for a Manual Deployment of GCE PD CSI driver.
8+
9+
>**Attention:** Note that Storage Pools is only available in the driver version [v1.13.0+](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/releases/tag/v1.13.0).
10+
11+
In addition to the install instructions [here](driver-install.md), you need to specify the CSI driver command line flags, `--enable-storage-pools=true`.
12+
13+
### Provision Volumes in a Storage Pool
14+
15+
To provision volumes in a Storage Pool, follow the instructions [here](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/hyperdisk-storage-pools#provision-attached-disk). When using the feature in a manual deployment of the GCE PD CSI Driver, in the [Create a StorageClass](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/hyperdisk-storage-pools#create-storageclass) section, you must additionally set [`allowedTopologies`](https://kubernetes.io/docs/concepts/storage/storage-classes/#allowed-topologies) to restrict the topology of provisioned volumes to specific zones where Storage Pools exist as specified in the `storage-pools` StorageClass parameter.
16+
17+
For example, looking at the example in [Create a StorageClass](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/hyperdisk-storage-pools#create-storageclass), assuming you already created a Storage Pool in `us-east4-c` according to [Create a Hyperdisk Storage Pool](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/hyperdisk-storage-pools#create-sp), your `StorageClass` would need to specify `allowedTopologies` to restrict the topology of provisioned volumes to us-east4-c, where the Storage Pool exists.
18+
19+
```yaml
20+
apiVersion: storage.k8s.io/v1
21+
kind: StorageClass
22+
metadata:
23+
name: storage-pools-sc
24+
provisioner: pd.csi.storage.gke.io
25+
volumeBindingMode: WaitForFirstConsumer
26+
allowVolumeExpansion: true
27+
parameters:
28+
type: hyperdisk-balanced
29+
provisioned-throughput-on-create: "140Mi"
30+
provisioned-iops-on-create: "3000"
31+
storage-pools: projects/my-project/zones/us-east4-c/storagePools/pool-us-east4-c
32+
allowedTopologies:
33+
- matchLabelExpressions:
34+
- key: topology.gke.io/zone
35+
values:
36+
- us-east4-c
37+
```

0 commit comments

Comments
 (0)