Repository: kubernetes-sigs/gcp-compute-persistent-disk-csi-driver
Pull request #933 (2022-03-17 01:52:27)

Add support for NVMe to NodePublishVolume
**What type of PR is this?**
/kind feature

**What this PR does / why we need it**: This PR adds support for NVMe persistent disks to GCP PD CSI Driver. Currently only SCSI disks are supported.

**Does this PR introduce a user-facing change?**:
```release-note
Add support for NVMe persistent disks
```


k8s-ci-robot: Hi @pwschuurman. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fgcp-compute-persistent-disk-csi-driver).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/pull/933#" title="Author self-approved">pwschuurman</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **msau42** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @msau42` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fgcp-compute-persistent-disk-csi-driver).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["msau42"]} -->
pwschuurman: /cc saikat-royc
mattcary: lgtm modulo a nit

Patch:
diff --git a/CHANGELOG/README.md b/CHANGELOG/README.md
index 54d5a2da..0f73a279 100644
--- a/CHANGELOG/README.md
+++ b/CHANGELOG/README.md
@@ -1,9 +1,5 @@
 # CHANGELOGs
 
-- [CHANGELOG v1.3.0](./CHANGELOG-1.4.md)
-- [CHANGELOG v1.3.0](./CHANGELOG-1.3.md)
-- [CHANGELOG v1.2.0](./CHANGELOG-1.2.md)
-- [CHANGELOG v1.1.0](./CHANGELOG-1.1.md)
 - [CHANGELOG v1.0.0](./CHANGELOG-1.0.md)
 - [CHANGELOG v0.7.0](./CHANGELOG-0.7.md)
 - [CHANGELOG v0.6.0](./CHANGELOG-0.6.md)
diff --git a/Dockerfile b/Dockerfile
index 77d0caed..51fc37e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -14,7 +14,7 @@
 
 ARG BUILDPLATFORM
 
-FROM --platform=$BUILDPLATFORM golang:1.17.8 as builder
+FROM --platform=$BUILDPLATFORM golang:1.17.2 as builder
 
 ARG STAGINGVERSION
 ARG TARGETPLATFORM
@@ -26,7 +26,8 @@ RUN GOARCH=$(echo $TARGETPLATFORM | cut -f2 -d '/') GCE_PD_CSI_STAGING_VERSION=$
 # Start from Kubernetes Debian base.
 FROM k8s.gcr.io/build-image/debian-base:buster-v1.9.0 as debian
 # Install necessary dependencies
-RUN clean-install util-linux e2fsprogs mount ca-certificates udev xfsprogs
+# google_nvme_id script depends on the following packages: nvme-cli, xxd, bash
+RUN clean-install util-linux e2fsprogs mount ca-certificates udev xfsprogs nvme-cli xxd bash
 # Since we're leveraging apt to pull in dependencies, we use `gcr.io/distroless/base` because it includes glibc.
 FROM gcr.io/distroless/base-debian11
 # Copy necessary dependencies into distroless base.
@@ -50,6 +51,14 @@ COPY --from=debian /sbin/xfs_repair /sbin/xfs_repair
 COPY --from=debian /usr/include/xfs /usr/include/xfs
 COPY --from=debian /usr/lib/xfsprogs/xfs* /usr/lib/xfsprogs/
 COPY --from=debian /usr/sbin/xfs* /usr/sbin/
+# Add dependencies for /lib/udev_containerized/google_nvme_id script
+COPY --from=debian /usr/sbin/nvme /usr/sbin/nvme
+COPY --from=debian /usr/bin/xxd /usr/bin/xxd
+COPY --from=debian /bin/bash /bin/bash
+COPY --from=debian /bin/date /bin/date
+COPY --from=debian /bin/grep /bin/grep
+COPY --from=debian /bin/sed /bin/sed
+COPY --from=debian /bin/ln /bin/ln
 
 # Copy x86 shared libraries into distroless base.
 COPY --from=debian /lib/x86_64-linux-gnu/libblkid.so.1 /lib/x86_64-linux-gnu/libblkid.so.1
diff --git a/Dockerfile.Windows b/Dockerfile.Windows
index 64c74f2d..32416c7a 100644
--- a/Dockerfile.Windows
+++ b/Dockerfile.Windows
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 ARG BASE_IMAGE
-FROM --platform=$BUILDPLATFORM golang:1.17.8 AS builder
+FROM --platform=$BUILDPLATFORM golang:1.13.15 AS builder
 
 ARG TARGETPLATFORM
 ARG BUILDPLATFORM
diff --git a/Dockerfile.arm64 b/Dockerfile.arm64
index 9052db4d..08f04a7b 100644
--- a/Dockerfile.arm64
+++ b/Dockerfile.arm64
@@ -14,7 +14,7 @@
 
 ARG BUILDPLATFORM
 
-FROM --platform=$BUILDPLATFORM golang:1.17.8 as builder
+FROM --platform=$BUILDPLATFORM golang:1.17.2 as builder
 
 ARG STAGINGVERSION
 ARG TARGETPLATFORM
@@ -32,7 +32,11 @@ RUN clean-install udev
 FROM k8s.gcr.io/build-image/debian-base:buster-v1.9.0
 COPY --from=builder /go/src/sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/bin/gce-pd-csi-driver /gce-pd-csi-driver
 # Install necessary dependencies
-RUN clean-install util-linux e2fsprogs mount ca-certificates udev xfsprogs
+# google_nvme_id script depends on the following packages: nvme-cli, xxd, bash
+RUN clean-install util-linux e2fsprogs mount ca-certificates udev xfsprogs nvme-cli xxd bash
 COPY --from=mad-hack /lib/udev/scsi_id /lib/udev_containerized/scsi_id
 
+# Copy google_nvme_id script, which is needed for NVMe support.
+COPY deploy/kubernetes/udev/google_nvme_id /lib/udev_containerized/google_nvme_id
+
 ENTRYPOINT ["/gce-pd-csi-driver"]
diff --git a/Dockerfile.debug b/Dockerfile.debug
index 9a1dae55..0336eec3 100644
--- a/Dockerfile.debug
+++ b/Dockerfile.debug
@@ -38,5 +38,5 @@ COPY --from=mad-hack /lib/udev/scsi_id /lib/udev_containerized/scsi_id
 
 # PDCSI driver isn't copied to / because of delve not being able to correlate
 # the binary and the source code, instead just run the binary where it was
-# compiled, the overlay noauth-debug calls this binary
+# compiled, the overlay noauth-dev calls this binary
 ENTRYPOINT ["/go/src/sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/bin/gce-pd-csi-driver"]
diff --git a/README.md b/README.md
index 6d7255fb..2ab07c0e 100644
--- a/README.md
+++ b/README.md
@@ -40,11 +40,11 @@ The following table captures the compatibility matrix of the core persistent dis
 | dev                                  | yes   |
 
 The manifest bundle which captures all the driver components (driver pod which includes the containers csi-provisioner, csi-resizer, csi-snapshotter, gce-pd-driver, csi-driver-registrar;
-csi driver object, rbacs, pod security policies etc) can be picked up from the master branch [overlays](deploy/kubernetes/overlays) directory. We structure the overlays directory, per minor version of kubernetes because not all driver components can be used with all kubernetes versions. 
+csi driver object, rbacs, pod security policies etc) can be picked up from the master branch [overlays](deploy/kubernetes/overlays) directory. We structure the overlays directory, per minor version of kubernetes because not all driver components can be used with all kubernetes versions. For example, v1 CSIDriver resources are supported in 1.18+ only, so [stable-1-17](deploy/kubernetes/overlays/stable-1-17) driver manifests use the v1beta1 version.
 
 Example:
 
-`stable-1-21` overlays bundle can be used to deploy all the components of the driver on kubernetes 1.21.
+`stable-1-19` overlays bundle can be used to deploy all the components of the driver on kubernetes 1.19.
 
 `stable-master` overlays bundle can be used to deploy all the components of the driver on kubernetes master.
 
@@ -79,10 +79,9 @@ GCE PD driver starts to support CSI Windows with [CSI Proxy] (https://github.com
 
 | Feature         | Stage | Min Kubernetes Master Version | Min Kubernetes Nodes Version | Min Driver Version | Deployment Overlay |
 |-----------------|-------|-------------------------------|------------------------------|--------------------|--------------------|
-| Snapshots       | GA    | 1.17                          | Any                          | v1.0.0             | stable-1-21, stable-1-22, stable-1-23, stable-master |
-| Clones          | GA    | 1.18                          | Any                          | v1.4.0             | stable-1-21, stable-1-22, stable-1-23, stable-master |
-| Resize (Expand) | Beta  | 1.16                          | 1.16                         | v0.7.0             | stable-1-21, stable-1-22, stable-1-23, stable-master |
-| Windows*        | GA    | 1.19                          | 1.19                         | v1.1.0             | stable-1-21, stable-1-22, stable-1-23, stable-master |
+| Snapshots       | Beta  | 1.17                          | Any                          | v1.0.0             | stable-1-17, stable-1-18, stable-1-19, stable-master |
+| Resize (Expand) | Beta  | 1.16                          | 1.16                         | v0.7.0             | stable-1-17, stable-1-18, stable-1-19, stable-master |
+| Windows*        | Beta  | 1.18                          | 1.18                         | v1.1.0             | stable-1-18, stable-1-19, stable-master |
 
 \* For Windows, it is recommended to use this driver with CSI proxy v0.2.2+. The master version of driver requires disk v1beta2 group, which is only available in CSI proxy v0.2.2+
 
diff --git a/deploy/kubernetes/README.md b/deploy/kubernetes/README.md
index 4b64a33b..f9fe6825 100644
--- a/deploy/kubernetes/README.md
+++ b/deploy/kubernetes/README.md
@@ -5,22 +5,24 @@
 The current structure for kustomization is as follows. Note that Windows support is currently an alpha feature.
 
 * `base`: It contains the setup that is common to different driver versions.
-  * `controller`: Includes cluster setup and controller yaml files.
-  * `node_linux`: Includes node yaml file and related setting that is only applicable for Linux.
-  * `node_windows`: Includes node yaml file and related setting that is only applicable for Windows.
-* `images`: Contains driver and sidecar image versions for the various [overlays](deploy/kubernetes/overlays/). 
-  * `stable-master`: Image versions for the stable-master overlay. 
-  * `stable-{k8s-minor}`: Image versions for the stable-{k8s-minor} overlays. 
-  * `prow-stable-sidecar-rc-master`: Image versions for the prow-stable-sidecar-rc-master overlay. 
-  * `prow-canary-sidecar`: Image versions for the prow-canary-sidecar overlay.
-* `overlays`: Contains various k8s resources driver manifest bundles used to deploy all the components of the driver. 
+  * `controller_setup`: Includes cluster setup and controller yaml files.
+  * `node_setup`:
+    * Linux: Includes node yaml file and related setting that is only applicable for Linux.
+    * Windows: Includes node yaml file and related setting that is only applicable for Windows.
+* `images`: It has a list of images for different versions.
+  * `stable-master`: Image list of a stable driver for latest k8s master.
+  * `alpha`: Image list containing features in development, in addition to images in `stable-master`. It also includes Windows images.
+  * `prow-gke-release-xxx`: Image list used for Prow tests.
+* `overlays`: It has the k8s minor version-specific driver manifest bundle.
   * `stable-master`: Contains deployment specs of a stable driver for k8s master.
-  * `stable-{k8s-minor}`: Contains deployment specs of a stable driver for given k8s minor version release. 
-  * `dev`: Based on stable-master, and also contains the developer's specs for use in driver development.
-  * `noauth` Based on stable-master, patches the [base controller configuration](deploy/kubernetes/base/controller.yaml) to remove any dependencies on service account keys.
-  * `noauth-debug`: Based on stable-master, used for debugging purposes only, see docs/kubernetes/development.md.
-  * `prow-stable-sidecar-rc-master`: Used for prow tests on OSS testgrid to test the latest sidecars. Contains deployment specs of a driver with k8s master branch, driver latest release candidate, and stable sidecars.
-  * `prow-canary-sidecar`: Used for prow tests on OSS testgrid to test release candidates when a new release is being cut. Contains deployment specs of a driver with k8s master branch, Kubernetes driver latest build, and canary sidecars. 
+  * `stable-{k8s-minor}`: Contains deployment specs of a stable driver for given k8s minor version release.
+  * `alpha`: Contains deployment specs for features in development. Both Linux and Windows are supported.
+  * `dev`: Based on alpha, and also contains the developer's specs for use in driver development.
+  * `noauth-debug`: Based on alpha, used for debugging purposes only, see docs/kubernetes/development.md.
+  * `prow-gke-release-staging-rc-master`: Used for prow tests. Contains deployment specs of a driver for latest k8s master.
+  * `prow-gke-release-staging-rc-{k8s-minor}`: Used for prow tests. Contains deployment specs of a driver for given k8s    minor version release.
+  * `prow-gke-release-staging-rc-head`: Used for prow tests. Contains deployment specs of a driver with latest sidecar images, for latest k8s master.
+  * `stable`, `prow-gke-release-staging-rc`: Soon to be removed!
 
   ## NVME support
   udev folder under deploy/kubernetes contains google_nvme_id script required for NVME support. Source is downloaded from [GoogleCloudPlatform/guest-configs](https://github.com/GoogleCloudPlatform/guest-configs). README file in the folder contains the downloaded version.
diff --git a/deploy/kubernetes/images/alpha/image.yaml b/deploy/kubernetes/images/alpha/image.yaml
new file mode 100644
index 00000000..8c6f62d1
--- /dev/null
+++ b/deploy/kubernetes/images/alpha/image.yaml
@@ -0,0 +1,7 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-alpha
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v3.0.0"
diff --git a/deploy/kubernetes/images/alpha/kustomization.yaml b/deploy/kubernetes/images/alpha/kustomization.yaml
new file mode 100644
index 00000000..2dfbdfd4
--- /dev/null
+++ b/deploy/kubernetes/images/alpha/kustomization.yaml
@@ -0,0 +1,5 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- ../stable-master/
+- image.yaml
diff --git a/deploy/kubernetes/images/prow-canary-sidecar/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-head/image.yaml
similarity index 94%
rename from deploy/kubernetes/images/prow-canary-sidecar/image.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-head/image.yaml
index ce0d779f..e3c9ef1b 100644
--- a/deploy/kubernetes/images/prow-canary-sidecar/image.yaml
+++ b/deploy/kubernetes/images/prow-gke-release-staging-head/image.yaml
@@ -3,7 +3,7 @@ kind: ImageTagTransformer
 metadata:
   name: imagetag-gcepd-driver-prow-head
 imageTag:
-  name: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
   newName: gcr.io/k8s-staging-cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
   newTag: "master"
 ---
diff --git a/deploy/kubernetes/images/prow-canary-sidecar/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-head/kustomization.yaml
similarity index 100%
rename from deploy/kubernetes/images/prow-canary-sidecar/kustomization.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-head/kustomization.yaml
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-1-15/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-15/image.yaml
new file mode 100644
index 00000000..0e8cc360
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-15/image.yaml
@@ -0,0 +1,36 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v1.6.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v2.2.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-gce-driver-prow-rc
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  newName: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  newTag: "v1.2.2"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
diff --git a/deploy/kubernetes/images/prow-stable-sidecar-rc-master/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-15/kustomization.yaml
similarity index 100%
rename from deploy/kubernetes/images/prow-stable-sidecar-rc-master/kustomization.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-rc-1-15/kustomization.yaml
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-1-16/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-16/image.yaml
new file mode 100644
index 00000000..9f08045a
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-16/image.yaml
@@ -0,0 +1,45 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v1.6.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v2.2.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resize-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.0.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-gce-driver-prow-rc
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  newName: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  newTag: "v1.2.2"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
diff --git a/deploy/kubernetes/images/stable-1-21/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-16/kustomization.yaml
similarity index 100%
rename from deploy/kubernetes/images/stable-1-21/kustomization.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-rc-1-16/kustomization.yaml
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-1-17/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-17/image.yaml
new file mode 100644
index 00000000..e66bc5f5
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-17/image.yaml
@@ -0,0 +1,45 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v3.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resize-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-gce-driver-prow-rc
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  newName: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  newTag: "v1.2.2"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
diff --git a/deploy/kubernetes/images/stable-1-22/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-17/kustomization.yaml
similarity index 100%
rename from deploy/kubernetes/images/stable-1-22/kustomization.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-rc-1-17/kustomization.yaml
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-1-18/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-18/image.yaml
new file mode 100644
index 00000000..392eb33b
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-18/image.yaml
@@ -0,0 +1,55 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v3.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resize-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-gce-driver-prow-rc
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  newName: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  newTag: "v1.2.2"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-snapshotter-prow-head
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-snapshotter
+  newTag: "v3.0.3"
+---
+
diff --git a/deploy/kubernetes/images/stable-1-23/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-18/kustomization.yaml
similarity index 100%
rename from deploy/kubernetes/images/stable-1-23/kustomization.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-rc-1-18/kustomization.yaml
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-1-19/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-19/image.yaml
new file mode 100644
index 00000000..392eb33b
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-19/image.yaml
@@ -0,0 +1,55 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v3.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resize-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-gce-driver-prow-rc
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  newName: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  newTag: "v1.2.2"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-snapshotter-prow-head
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-snapshotter
+  newTag: "v3.0.3"
+---
+
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-1-19/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-19/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-1-19/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/prow-stable-sidecar-rc-master/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-master/image.yaml
similarity index 92%
rename from deploy/kubernetes/images/prow-stable-sidecar-rc-master/image.yaml
rename to deploy/kubernetes/images/prow-gke-release-staging-rc-master/image.yaml
index 59e7472e..bbb5ba52 100644
--- a/deploy/kubernetes/images/prow-stable-sidecar-rc-master/image.yaml
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-master/image.yaml
@@ -7,7 +7,7 @@ metadata:
   name: imagetag-csi-provisioner-prow-rc
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-provisioner
-  newTag: "v3.1.0"
+  newTag: "v3.0.0"
 ---
 apiVersion: builtin
 kind: ImageTagTransformer
@@ -15,7 +15,7 @@ metadata:
   name: imagetag-csi-attacher-prow-rc
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-attacher
-  newTag: "v3.4.0"
+  newTag: "v3.2.1"
 ---
 apiVersion: builtin
 kind: ImageTagTransformer
@@ -23,7 +23,7 @@ metadata:
   name: imagetag-csi-resize-prow-rc
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-resizer
-  newTag: "v1.4.0"
+  newTag: "v1.2.0"
 ---
 apiVersion: builtin
 kind: ImageTagTransformer
@@ -31,7 +31,7 @@ metadata:
   name: imagetag-csi-snapshotter-prow-head
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-snapshotter
-  newTag: "v4.1.1"
+  newTag: "v3.0.3"
 ---
 apiVersion: builtin
 kind: ImageTagTransformer
@@ -39,7 +39,7 @@ metadata:
   name: imagetag-csi-node-registrar-prow-rc
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
-  newTag: "v2.5.0"
+  newTag: "v2.3.0"
 ---
 apiVersion: builtin
 kind: ImageTagTransformer
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc-master/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc-master/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc-master/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc/image.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc/image.yaml
new file mode 100644
index 00000000..4827f31c
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc/image.yaml
@@ -0,0 +1,55 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v2.2.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v3.2.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resize-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.2.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-gce-driver-prow-rc
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  newName: k8s.gcr.io/cloud-provider-gcp/gcp-compute-persistent-disk-csi-driver
+  newTag: "v1.2.2"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar-prow-rc
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-snapshotter-prow-head
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-snapshotter
+  newTag: "v3.0.3"
+---
+
diff --git a/deploy/kubernetes/images/prow-gke-release-staging-rc/kustomization.yaml b/deploy/kubernetes/images/prow-gke-release-staging-rc/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/prow-gke-release-staging-rc/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/stable-1-15/image.yaml b/deploy/kubernetes/images/stable-1-15/image.yaml
new file mode 100644
index 00000000..309863c3
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-15/image.yaml
@@ -0,0 +1,46 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v1.6.1"
+
+---
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v2.2.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resizer
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.0.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-gcepd-driver
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  # Don't change stable image without changing pdImagePlaceholder in
+  # test/k8s-integration/main.go
+  newTag: "v1.2.1-gke.0"
+---
diff --git a/deploy/kubernetes/images/stable-1-15/kustomization.yaml b/deploy/kubernetes/images/stable-1-15/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-15/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/stable-1-16/image.yaml b/deploy/kubernetes/images/stable-1-16/image.yaml
new file mode 100644
index 00000000..309863c3
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-16/image.yaml
@@ -0,0 +1,46 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v1.6.1"
+
+---
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v2.2.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resizer
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.0.1"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-gcepd-driver
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  # Don't change stable image without changing pdImagePlaceholder in
+  # test/k8s-integration/main.go
+  newTag: "v1.2.1-gke.0"
+---
diff --git a/deploy/kubernetes/images/stable-1-16/kustomization.yaml b/deploy/kubernetes/images/stable-1-16/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-16/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/stable-1-23/image.yaml b/deploy/kubernetes/images/stable-1-17/image.yaml
similarity index 82%
rename from deploy/kubernetes/images/stable-1-23/image.yaml
rename to deploy/kubernetes/images/stable-1-17/image.yaml
index c84eeea6..43d79c95 100644
--- a/deploy/kubernetes/images/stable-1-23/image.yaml
+++ b/deploy/kubernetes/images/stable-1-17/image.yaml
@@ -4,7 +4,7 @@ metadata:
   name: imagetag-csi-provisioner
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-provisioner
-  newTag: "v3.1.0"
+  newTag: "v2.1.0"
 
 ---
 apiVersion: builtin
@@ -13,7 +13,7 @@ metadata:
   name: imagetag-csi-attacher
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-attacher
-  newTag: "v3.4.0"
+  newTag: "v3.1.0"
 ---
 
 apiVersion: builtin
@@ -22,7 +22,7 @@ metadata:
   name: imagetag-csi-resizer
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-resizer
-  newTag: "v1.4.0"
+  newTag: "v1.1.0"
 ---
 
 apiVersion: builtin
@@ -31,7 +31,7 @@ metadata:
   name: imagetag-csi-snapshotter
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-snapshotter
-  newTag: "v4.0.1"
+  newTag: "v3.0.3"
 ---
 
 apiVersion: builtin
@@ -40,7 +40,7 @@ metadata:
   name: imagetag-csi-node-registrar
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
-  newTag: "v2.5.0"
+  newTag: "v2.1.0"
 ---
 
 apiVersion: builtin
@@ -49,5 +49,7 @@ metadata:
   name: imagetag-gcepd-driver
 imageTag:
   name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
-  newTag: "v1.4.0"
+  # Don't change stable image without changing pdImagePlaceholder in
+  # test/k8s-integration/main.go
+  newTag: "v1.2.1-gke.0"
 ---
diff --git a/deploy/kubernetes/images/stable-1-17/kustomization.yaml b/deploy/kubernetes/images/stable-1-17/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-17/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/stable-1-21/image.yaml b/deploy/kubernetes/images/stable-1-18/image.yaml
similarity index 82%
rename from deploy/kubernetes/images/stable-1-21/image.yaml
rename to deploy/kubernetes/images/stable-1-18/image.yaml
index c84eeea6..43d79c95 100644
--- a/deploy/kubernetes/images/stable-1-21/image.yaml
+++ b/deploy/kubernetes/images/stable-1-18/image.yaml
@@ -4,7 +4,7 @@ metadata:
   name: imagetag-csi-provisioner
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-provisioner
-  newTag: "v3.1.0"
+  newTag: "v2.1.0"
 
 ---
 apiVersion: builtin
@@ -13,7 +13,7 @@ metadata:
   name: imagetag-csi-attacher
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-attacher
-  newTag: "v3.4.0"
+  newTag: "v3.1.0"
 ---
 
 apiVersion: builtin
@@ -22,7 +22,7 @@ metadata:
   name: imagetag-csi-resizer
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-resizer
-  newTag: "v1.4.0"
+  newTag: "v1.1.0"
 ---
 
 apiVersion: builtin
@@ -31,7 +31,7 @@ metadata:
   name: imagetag-csi-snapshotter
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-snapshotter
-  newTag: "v4.0.1"
+  newTag: "v3.0.3"
 ---
 
 apiVersion: builtin
@@ -40,7 +40,7 @@ metadata:
   name: imagetag-csi-node-registrar
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
-  newTag: "v2.5.0"
+  newTag: "v2.1.0"
 ---
 
 apiVersion: builtin
@@ -49,5 +49,7 @@ metadata:
   name: imagetag-gcepd-driver
 imageTag:
   name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
-  newTag: "v1.4.0"
+  # Don't change stable image without changing pdImagePlaceholder in
+  # test/k8s-integration/main.go
+  newTag: "v1.2.1-gke.0"
 ---
diff --git a/deploy/kubernetes/images/stable-1-18/kustomization.yaml b/deploy/kubernetes/images/stable-1-18/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-18/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/stable-1-22/image.yaml b/deploy/kubernetes/images/stable-1-19/image.yaml
similarity index 82%
rename from deploy/kubernetes/images/stable-1-22/image.yaml
rename to deploy/kubernetes/images/stable-1-19/image.yaml
index c84eeea6..43d79c95 100644
--- a/deploy/kubernetes/images/stable-1-22/image.yaml
+++ b/deploy/kubernetes/images/stable-1-19/image.yaml
@@ -4,7 +4,7 @@ metadata:
   name: imagetag-csi-provisioner
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-provisioner
-  newTag: "v3.1.0"
+  newTag: "v2.1.0"
 
 ---
 apiVersion: builtin
@@ -13,7 +13,7 @@ metadata:
   name: imagetag-csi-attacher
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-attacher
-  newTag: "v3.4.0"
+  newTag: "v3.1.0"
 ---
 
 apiVersion: builtin
@@ -22,7 +22,7 @@ metadata:
   name: imagetag-csi-resizer
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-resizer
-  newTag: "v1.4.0"
+  newTag: "v1.1.0"
 ---
 
 apiVersion: builtin
@@ -31,7 +31,7 @@ metadata:
   name: imagetag-csi-snapshotter
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-snapshotter
-  newTag: "v4.0.1"
+  newTag: "v3.0.3"
 ---
 
 apiVersion: builtin
@@ -40,7 +40,7 @@ metadata:
   name: imagetag-csi-node-registrar
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
-  newTag: "v2.5.0"
+  newTag: "v2.1.0"
 ---
 
 apiVersion: builtin
@@ -49,5 +49,7 @@ metadata:
   name: imagetag-gcepd-driver
 imageTag:
   name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
-  newTag: "v1.4.0"
+  # Don't change stable image without changing pdImagePlaceholder in
+  # test/k8s-integration/main.go
+  newTag: "v1.2.1-gke.0"
 ---
diff --git a/deploy/kubernetes/images/stable-1-19/kustomization.yaml b/deploy/kubernetes/images/stable-1-19/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/stable-1-19/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/images/stable-master/image.yaml b/deploy/kubernetes/images/stable-master/image.yaml
index 110e6ee6..cd0b33d8 100644
--- a/deploy/kubernetes/images/stable-master/image.yaml
+++ b/deploy/kubernetes/images/stable-master/image.yaml
@@ -4,7 +4,7 @@ metadata:
   name: imagetag-csi-provisioner
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-provisioner
-  newTag: "v3.1.0"
+  newTag: "v3.0.0"
 
 ---
 apiVersion: builtin
@@ -13,7 +13,7 @@ metadata:
   name: imagetag-csi-attacher
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-attacher
-  newTag: "v3.4.0"
+  newTag: "v3.2.1"
 ---
 
 apiVersion: builtin
@@ -22,7 +22,7 @@ metadata:
   name: imagetag-csi-resizer
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-resizer
-  newTag: "v1.4.0"
+  newTag: "v1.2.0"
 ---
 
 apiVersion: builtin
@@ -31,7 +31,7 @@ metadata:
   name: imagetag-csi-snapshotter
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-snapshotter
-  newTag: "v4.0.1"
+  newTag: "v3.0.3"
 ---
 
 apiVersion: builtin
@@ -40,7 +40,7 @@ metadata:
   name: imagetag-csi-node-registrar
 imageTag:
   name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
-  newTag: "v2.5.0"
+  newTag: "v2.3.0"
 ---
 
 apiVersion: builtin
diff --git a/deploy/kubernetes/images/stable/image.yaml b/deploy/kubernetes/images/stable/image.yaml
new file mode 100644
index 00000000..108eda3d
--- /dev/null
+++ b/deploy/kubernetes/images/stable/image.yaml
@@ -0,0 +1,55 @@
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-provisioner
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-provisioner
+  newTag: "v2.1.0"
+
+---
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-attacher
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-attacher
+  newTag: "v3.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-resizer
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-resizer
+  newTag: "v1.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-snapshotter
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-snapshotter
+  newTag: "v3.0.3"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-csi-node-registrar
+imageTag:
+  name: k8s.gcr.io/sig-storage/csi-node-driver-registrar
+  newTag: "v2.1.0"
+---
+
+apiVersion: builtin
+kind: ImageTagTransformer
+metadata:
+  name: imagetag-gcepd-driver
+imageTag:
+  name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
+  # Don't change stable image without changing pdImagePlaceholder in
+  # test/k8s-integration/main.go
+  newTag: "v1.2.0-gke.8"
+---
diff --git a/deploy/kubernetes/images/stable/kustomization.yaml b/deploy/kubernetes/images/stable/kustomization.yaml
new file mode 100644
index 00000000..f16988f1
--- /dev/null
+++ b/deploy/kubernetes/images/stable/kustomization.yaml
@@ -0,0 +1,4 @@
+namespace:
+  gce-pd-csi-driver
+resources:
+- image.yaml
diff --git a/deploy/kubernetes/overlays/alpha/WARNING.md b/deploy/kubernetes/overlays/alpha/WARNING.md
new file mode 100644
index 00000000..947a35cd
--- /dev/null
+++ b/deploy/kubernetes/overlays/alpha/WARNING.md
@@ -0,0 +1,3 @@
+WARNING: DO NOT USE THE ALPHA VERSION OF THE DRIVER FOR PRODUCTION
+
+Alpha features are unsupported and may be unstable and have breaking changes across releases.
diff --git a/deploy/kubernetes/overlays/alpha/kustomization.yaml b/deploy/kubernetes/overlays/alpha/kustomization.yaml
new file mode 100644
index 00000000..ebf7e456
--- /dev/null
+++ b/deploy/kubernetes/overlays/alpha/kustomization.yaml
@@ -0,0 +1,7 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: gce-pd-csi-driver
+resources:
+- ../../base/
+transformers:
+- ../../images/alpha
diff --git a/deploy/kubernetes/overlays/dev/kustomization.yaml b/deploy/kubernetes/overlays/dev/kustomization.yaml
index f6ffff39..2db58d45 100644
--- a/deploy/kubernetes/overlays/dev/kustomization.yaml
+++ b/deploy/kubernetes/overlays/dev/kustomization.yaml
@@ -8,9 +8,9 @@ resources:
 - ../../base/
 # Here dev overlay is using the same image as alpha
 transformers:
-- ../../images/stable-master
+- ../../images/alpha
 # To change the dev image, add something like the following.
 #images:
 #- name: gke.gcr.io/gcp-compute-persistent-disk-csi-driver
 #  newName: gcr.io/mattcary-gke-dev-owned/csi/gce-pd-driver
-#  newTag: latest
+#  newTag: latest.
diff --git a/deploy/kubernetes/overlays/noauth-debug/kustomization.yaml b/deploy/kubernetes/overlays/noauth-debug/kustomization.yaml
index d85ab5e7..ce063e75 100644
--- a/deploy/kubernetes/overlays/noauth-debug/kustomization.yaml
+++ b/deploy/kubernetes/overlays/noauth-debug/kustomization.yaml
@@ -2,9 +2,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 resources:
 - ../../base/
-# Here noauth overlay is using the same image as stable-master
+# Here noauth overlay is using the same image as alpha
 transformers:
-- ../../images/stable-master
+- ../../images/alpha
 patchesStrategicMerge:
 - noauth.yaml
 - controller-overlay.yaml
diff --git a/deploy/kubernetes/overlays/noauth/kustomization.yaml b/deploy/kubernetes/overlays/noauth/kustomization.yaml
index caeed135..f4c1b0d5 100644
--- a/deploy/kubernetes/overlays/noauth/kustomization.yaml
+++ b/deploy/kubernetes/overlays/noauth/kustomization.yaml
@@ -2,9 +2,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 resources:
 - ../../base/
-# Here noauth overlay is using the same image as stable-master
+# Here noauth overlay is using the same image as alpha
 transformers:
-- ../../images/stable-master
+- ../../images/alpha
 patchesStrategicMerge:
 - noauth.yaml
 namespace: gce-pd-csi-driver
diff --git a/deploy/kubernetes/overlays/prow-canary-sidecar/README.md b/deploy/kubernetes/overlays/prow-gke-release-staging-head/README.md
similarity index 100%
rename from deploy/kubernetes/overlays/prow-canary-sidecar/README.md
rename to deploy/kubernetes/overlays/prow-gke-release-staging-head/README.md
diff --git a/deploy/kubernetes/overlays/prow-canary-sidecar/kustomization.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-head/kustomization.yaml
similarity index 70%
rename from deploy/kubernetes/overlays/prow-canary-sidecar/kustomization.yaml
rename to deploy/kubernetes/overlays/prow-gke-release-staging-head/kustomization.yaml
index 6e9d9e13..2bad6646 100644
--- a/deploy/kubernetes/overlays/prow-canary-sidecar/kustomization.yaml
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-head/kustomization.yaml
@@ -3,4 +3,4 @@ kind: Kustomization
 resources:
 - ../stable-master
 transformers:
-- ../../images/prow-canary-sidecar
+- ../../images/prow-gke-release-staging-head
diff --git a/deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/README.md b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/README.md
similarity index 100%
rename from deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/README.md
rename to deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/README.md
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/kustomization.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/kustomization.yaml
new file mode 100644
index 00000000..8315e48b
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/kustomization.yaml
@@ -0,0 +1,9 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../stable-1-17
+- v1beta1_csidriver.yaml
+patchesStrategicMerge:
+- no_v1_csidriver.yaml
+transformers:
+- ../../images/prow-gke-release-staging-rc-1-17
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/no_v1_csidriver.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/no_v1_csidriver.yaml
new file mode 100644
index 00000000..b45cfc07
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/no_v1_csidriver.yaml
@@ -0,0 +1,5 @@
+$patch: delete
+apiVersion: storage.k8s.io/v1
+kind: CSIDriver
+metadata:
+  name: pd.csi.storage.gke.io
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/v1beta1_csidriver.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/v1beta1_csidriver.yaml
new file mode 100644
index 00000000..d15a496b
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-17/v1beta1_csidriver.yaml
@@ -0,0 +1,7 @@
+apiVersion: storage.k8s.io/v1beta1
+kind: CSIDriver
+metadata:
+  name: pd.csi.storage.gke.io
+spec:
+  attachRequired: true
+  podInfoOnMount: false
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-18/README.md b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-18/README.md
new file mode 100644
index 00000000..de722221
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-18/README.md
@@ -0,0 +1,1 @@
+These overlays are intended to be only used by prow for CI testing.
diff --git a/deploy/kubernetes/overlays/stable-1-21/kustomization.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-18/kustomization.yaml
similarity index 64%
rename from deploy/kubernetes/overlays/stable-1-21/kustomization.yaml
rename to deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-18/kustomization.yaml
index 6665a3e9..9863938f 100644
--- a/deploy/kubernetes/overlays/stable-1-21/kustomization.yaml
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-18/kustomization.yaml
@@ -3,6 +3,6 @@ kind: Kustomization
 namespace:
   gce-pd-csi-driver
 resources:
-- ../../base/
+- ../stable-1-18
 transformers:
-- ../../images/stable-1-21
+- ../../images/prow-gke-release-staging-rc-1-18
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/README.md b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/README.md
new file mode 100644
index 00000000..de722221
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/README.md
@@ -0,0 +1,1 @@
+These overlays are intended to be only used by prow for CI testing.
diff --git a/deploy/kubernetes/overlays/stable-1-22/kustomization.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/kustomization.yaml
similarity index 64%
rename from deploy/kubernetes/overlays/stable-1-22/kustomization.yaml
rename to deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/kustomization.yaml
index 6665a3e9..5f949505 100644
--- a/deploy/kubernetes/overlays/stable-1-22/kustomization.yaml
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/kustomization.yaml
@@ -3,6 +3,6 @@ kind: Kustomization
 namespace:
   gce-pd-csi-driver
 resources:
-- ../../base/
+- ../stable-1-19
 transformers:
-- ../../images/stable-1-21
+- ../../images/prow-gke-release-staging-rc-1-19
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/README.md b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/README.md
new file mode 100644
index 00000000..de722221
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/README.md
@@ -0,0 +1,1 @@
+These overlays are intended to be only used by prow for CI testing.
diff --git a/deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/disk_labels.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/disk_labels.yaml
similarity index 100%
rename from deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/disk_labels.yaml
rename to deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/disk_labels.yaml
diff --git a/deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/kustomization.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/kustomization.yaml
similarity index 87%
rename from deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/kustomization.yaml
rename to deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/kustomization.yaml
index c2351500..eb1c6f6f 100644
--- a/deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/kustomization.yaml
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc-master/kustomization.yaml
@@ -13,4 +13,4 @@ patchesJson6902:
     name: csi-gce-pd-controller
   path: disk_labels.yaml
 transformers:
-- ../../images/prow-stable-sidecar-rc-master
+- ../../images/prow-gke-release-staging-rc-master
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc/README.md b/deploy/kubernetes/overlays/prow-gke-release-staging-rc/README.md
new file mode 100644
index 00000000..de722221
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc/README.md
@@ -0,0 +1,1 @@
+These overlays are intended to be only used by prow for CI testing.
diff --git a/deploy/kubernetes/overlays/prow-gke-release-staging-rc/kustomization.yaml b/deploy/kubernetes/overlays/prow-gke-release-staging-rc/kustomization.yaml
new file mode 100644
index 00000000..64418666
--- /dev/null
+++ b/deploy/kubernetes/overlays/prow-gke-release-staging-rc/kustomization.yaml
@@ -0,0 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../stable
+transformers:
+- ../../images/prow-gke-release-staging-rc
diff --git a/deploy/kubernetes/overlays/stable-1-17/kustomization.yaml b/deploy/kubernetes/overlays/stable-1-17/kustomization.yaml
new file mode 100644
index 00000000..c33410d0
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-17/kustomization.yaml
@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace:
+  gce-pd-csi-driver
+resources:
+- ../../base/controller
+- ../../base/node_linux
+- v1beta1_csidriver.yaml
+patchesStrategicMerge:
+- no_win_roles.yaml
+- no_v1_csidriver.yaml
+- no-node-driver-registrar-probe.yaml
+transformers:
+- ../../images/stable-1-17
diff --git a/deploy/kubernetes/overlays/stable-1-17/no-node-driver-registrar-probe.yaml b/deploy/kubernetes/overlays/stable-1-17/no-node-driver-registrar-probe.yaml
new file mode 100644
index 00000000..bb5dfe96
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-17/no-node-driver-registrar-probe.yaml
@@ -0,0 +1,25 @@
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node-win
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
+---
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
diff --git a/deploy/kubernetes/overlays/stable-1-17/no_v1_csidriver.yaml b/deploy/kubernetes/overlays/stable-1-17/no_v1_csidriver.yaml
new file mode 100644
index 00000000..b45cfc07
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-17/no_v1_csidriver.yaml
@@ -0,0 +1,5 @@
+$patch: delete
+apiVersion: storage.k8s.io/v1
+kind: CSIDriver
+metadata:
+  name: pd.csi.storage.gke.io
diff --git a/deploy/kubernetes/overlays/stable-1-17/no_win_roles.yaml b/deploy/kubernetes/overlays/stable-1-17/no_win_roles.yaml
new file mode 100644
index 00000000..0d9bc051
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-17/no_win_roles.yaml
@@ -0,0 +1,17 @@
+$patch: delete
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: csi-gce-pd-node-sa-win
+---
+$patch: delete
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-gce-pd-node-deploy-win
+---
+$patch: delete
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: csi-gce-pd-node-win
diff --git a/deploy/kubernetes/overlays/stable-1-17/v1beta1_csidriver.yaml b/deploy/kubernetes/overlays/stable-1-17/v1beta1_csidriver.yaml
new file mode 100644
index 00000000..d15a496b
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-17/v1beta1_csidriver.yaml
@@ -0,0 +1,7 @@
+apiVersion: storage.k8s.io/v1beta1
+kind: CSIDriver
+metadata:
+  name: pd.csi.storage.gke.io
+spec:
+  attachRequired: true
+  podInfoOnMount: false
diff --git a/deploy/kubernetes/overlays/stable-1-18/kustomization.yaml b/deploy/kubernetes/overlays/stable-1-18/kustomization.yaml
new file mode 100644
index 00000000..09543ee6
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-18/kustomization.yaml
@@ -0,0 +1,10 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace:
+  gce-pd-csi-driver
+resources:
+- ../../base
+patchesStrategicMerge:
+- no-node-driver-registrar-probe.yaml
+transformers:
+- ../../images/stable-1-18
diff --git a/deploy/kubernetes/overlays/stable-1-18/no-node-driver-registrar-probe.yaml b/deploy/kubernetes/overlays/stable-1-18/no-node-driver-registrar-probe.yaml
new file mode 100644
index 00000000..bb5dfe96
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-18/no-node-driver-registrar-probe.yaml
@@ -0,0 +1,25 @@
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node-win
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
+---
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
diff --git a/deploy/kubernetes/overlays/stable-1-19/kustomization.yaml b/deploy/kubernetes/overlays/stable-1-19/kustomization.yaml
new file mode 100644
index 00000000..965394dc
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-19/kustomization.yaml
@@ -0,0 +1,10 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace:
+  gce-pd-csi-driver
+resources:
+- ../../base/
+patchesStrategicMerge:
+- no-node-driver-registrar-probe.yaml
+transformers:
+- ../../images/stable-1-19
diff --git a/deploy/kubernetes/overlays/stable-1-19/no-node-driver-registrar-probe.yaml b/deploy/kubernetes/overlays/stable-1-19/no-node-driver-registrar-probe.yaml
new file mode 100644
index 00000000..bb5dfe96
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-1-19/no-node-driver-registrar-probe.yaml
@@ -0,0 +1,25 @@
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node-win
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
+---
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
diff --git a/deploy/kubernetes/overlays/stable-master/kustomization.yaml b/deploy/kubernetes/overlays/stable-master/kustomization.yaml
index 9f35ef38..96ed93d4 100644
--- a/deploy/kubernetes/overlays/stable-master/kustomization.yaml
+++ b/deploy/kubernetes/overlays/stable-master/kustomization.yaml
@@ -3,6 +3,8 @@ kind: Kustomization
 namespace:
   gce-pd-csi-driver
 resources:
-- ../../base/
+- ../../base
+patchesStrategicMerge:
+- no-node-driver-registrar-probe.yaml
 transformers:
 - ../../images/stable-master
diff --git a/deploy/kubernetes/overlays/stable-master/no-node-driver-registrar-probe.yaml b/deploy/kubernetes/overlays/stable-master/no-node-driver-registrar-probe.yaml
new file mode 100644
index 00000000..516ad260
--- /dev/null
+++ b/deploy/kubernetes/overlays/stable-master/no-node-driver-registrar-probe.yaml
@@ -0,0 +1,27 @@
+# TODO(mauriciopoppe): remove this file once testgrid is green with
+# prow-gke-release-staging-rc-master
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node-win
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
+---
+kind: DaemonSet
+apiVersion: apps/v1
+metadata:
+  name: csi-gce-pd-node
+spec:
+  template:
+    spec:
+      containers:
+        - name: csi-driver-registrar
+          # introduced in node-driver-registrar v2.3.0
+          livenessProbe:
+            $patch: delete
diff --git a/deploy/kubernetes/overlays/stable-1-23/kustomization.yaml b/deploy/kubernetes/overlays/stable/kustomization.yaml
similarity index 83%
rename from deploy/kubernetes/overlays/stable-1-23/kustomization.yaml
rename to deploy/kubernetes/overlays/stable/kustomization.yaml
index e95118c9..fbdbb235 100644
--- a/deploy/kubernetes/overlays/stable-1-23/kustomization.yaml
+++ b/deploy/kubernetes/overlays/stable/kustomization.yaml
@@ -5,4 +5,4 @@ namespace:
 resources:
 - ../../base/
 transformers:
-- ../../images/stable-1-23
+- ../../images/stable
diff --git a/docs/release/overlays.md b/docs/release/overlays.md
index 7ea9d5e9..7805d216 100644
--- a/docs/release/overlays.md
+++ b/docs/release/overlays.md
@@ -1,46 +1,47 @@
 # Overview of per kubernetes minor version overlays
 
-The Persistent Disk CSI Driver manifest [bundle](../../deploy/kubernetes/base) is a set of many kubernetes resources (driver pod which includes the containers csi-provisioner, csi-resizer, csi-snapshotter, gce-pd-driver, csi-driver-registrar; csi driver object, rbacs, pod security policies etc). Not all driver capabilties can be used with all kubernetes versions. For example [volume snapshots](https://kubernetes.io/docs/concepts/storage/volume-snapshots/) are supported on 1.17+ kubernetes versions. Thus structuring the overlays on a per kubernetes minor version is beneficial to quickly identify driver capabilities supported for a given minor version of kubernetes (example `stable-1-16` driver manifests did not contain the snapshotter sidecar), and facilitates easy maintenance/updates of the CSI driver. The master branch has the up-to-date [overlays](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/tree/master/deploy/kubernetes/overlays) for each kubernetes version, which specify which driver release version to use with each kubernetes version.
+The Persistent Disk CSI Driver manifest [bundle](../../deploy/kubernetes/base) is a set of many kubernetes resources (driver pod which includes the containers csi-provisioner, csi-resizer, csi-snapshotter, gce-pd-driver, csi-driver-registrar; csi driver object, rbacs, pod security policies etc). Not all driver capabilties can be used with all kubernetes versions. For example [volume snapshots](https://kubernetes.io/docs/concepts/storage/volume-snapshots/) are supported on 1.17+ kubernetes versions. Thus structuring the overlays on a per kubernetes minor version is beneficial to quickly identify driver capabilities supported for a given minor version of kubernetes (example [stable-1-16](../../deploy/kubernetes/overlays/stable-1-16) driver manifests does not contain the snapshotter sidecar), and facilitates easy maintenance/updates of the CSI driver. The master branch has the up-to-date [overlays](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/tree/master/deploy/kubernetes/overlays) for each kubernetes version, which specify which driver release version to use with each kubernetes version.
 
 Example:
-`stable-1-22` [overlays](../../deploy/kubernetes/overlays/stable-1-22) bundle can be used to deploy all the components of the driver on kubernetes 1.22. This overlay uses persistent disk driver release version [1.4.0](../../deploy/kubernetes/images/stable-1-22/image.yaml).
+`stable-1-19` [overlays](../../deploy/kubernetes/overlays/stable-1-19) bundle can be used to deploy all the components of the driver on kubernetes 1.19. This overlay uses persistent disk driver release version [1.2.0](../../deploy/kubernetes/images/stable-1-19/image.yaml).
+`prow-gke-staging-release-rc-1-19` [overlays](../../deploy/kubernetes/overlays/prow-gke-staging-release-rc-1-19) bundle can be used to test all the components of the driver on kubernetes 1.19.
 
 ## General guidelines for creation/modification of new/existing overlays
 
 When it comes to creation of overlays there are no strict rules on how overlays must be created/modified but the following captures some of the common scenarios of adding new capabilities to the CSI driver bundle and how it would affect the overlays creation/modification.
 
 1. Creating a new k8s minor version overlay with an existing released driver image
-   * Consider a scenario where we have existing overlays `stable-1-22`, `stable-master`. We plan to now create a new overlay for k8s 1.23
-   * Update the `deploy/kubernetes/images/prow-stable-sidecar-rc-master` directory with appropriate image versions. If the images used in `stable-master` or `stable-1-22` are compatible with 1.23, no updates are necessary. 
-   * Update the `deploy/kubernetes/images/prow-stable-sidecar-rc-master` directory. If there are no additional kustomize diff patches to add, no updates are necessary.
-   * At this stage, validate the changes made to the `prow-stable-sidecar-rc-master` overlay. Ensure the upstream testgrids like [this](https://k8s-testgrid.appspot.com/provider-gcp-compute-persistent-disk-csi-driver) are green, and verify with repository maintainers that downstream test grids (e.g GKE internal prow test grids) are green. Care must be taken to avoid directly making changes to `deploy/kubernetes/base` manifests at this stage, as they may impact existing overlays.
+   * Consider a scenario where we have existing overlays `stable-1-18`, `stable-master`. We plan to now create a new overlay for k8s 1.19
+   * Create a new `deploy/kubernetes/images/prow-gke-staging-release-rc-1-19` directory with appropriate image versions. If the images used in `stable-master` or `stable-1-18` are compatible with 1.19, we can clone from either `deploy/kubernetes/images/stable-master/image.yaml` or `deploy/kubernetes/images/stable-1-18/image.yaml`
+   * Create a new `deploy/kubernetes/overlays/prow-gke-staging-release-rc-1-19` directory and clone contents from either `deploy/kubernetes/overlays/stable-master/*` or `deploy/kubernetes/overlays/stable-1-18/*`, depending on which manifests would be compatible with the 1.19 driver bundle and add the necessary kustomize diff patches to `deploy/kubernetes/overlays/stable-1-19/*`.
+   * At this stage, validate the changes made to the `prow-gke-release-staging-rc-1-19` overlay. Ensure the upstream testgrids like [this](https://k8s-testgrid.appspot.com/provider-gcp-compute-persistent-disk-csi-driver) are green, and verify with repository maintainers that downstream test grids (e.g GKE internal prow test grids) are green. Care must be taken to avoid directly making changes to `deploy/kubernetes/base` manifests at this stage, as they may impact existing overlays.
 
    A sample kustomize patch file would look like this:
 
    ```
-   deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/your-1-23-kustomize-diff-patch.yaml
+   deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/your-1-19-kustomize-diff-patch.yaml
    ```
 
-   In deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/kustomize.yaml,
+   In deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/kustomize.yaml,
 
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
     resources:
-    - ../stable-master (If this 1.23 overlay is created based out of stable-master)
+    - ../stable-master (If this 1.19 overlay is created based out of stable-master)
     patchesStrategicMerge: # or any other patch strategies (such as JsonPatches6902)
-    - <your-1-23-kustomize-diff-patch.yaml>
+    - <your-1-19-kustomize-diff-patch.yaml>
     transformers:
-    - ../../images/prow-stable-sidecar-rc-master
+    - ../../images/prow-gke-release-staging-rc-1-19
    ```
 
-   * When `prow-stable-sidecar-rc-master` is validated, we have couple of options to update the stable-1-23. If the kustomize diffs are a one-off change specific to 1.23, we can simply move the kustomize patches to stable-1-23. The kustomize patch file would now look like this.
+   * When `prow-gke-release-staging-rc-1-19` is validated, we have couple of options to update the stable-1-19. If the kustomize diffs are a one-off change specific to 1.19, we can simply move the kustomize patches to stable-1-19. The kustomize patch file would now look like this.
 
    ```
-   $ mv deploy/kubernetes/overlays/prow-stable-sidecar-rc-master/your-1-23-kustomize-diff-patch.yaml deploy/kubernetes/overlays/stable-1-23/your-1-23-kustomize-diff-patch.yaml
+   $ mv deploy/kubernetes/overlays/prow-gke-release-staging-rc-1-19/your-1-19-kustomize-diff-patch.yaml deploy/kubernetes/overlays/stable-1-19/your-1-19-kustomize-diff-patch.yaml
    ```
 
-   For `stable-1-23`, 
+   For `stable-1-19`, 
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
@@ -50,24 +51,24 @@ When it comes to creation of overlays there are no strict rules on how overlays
     - ../../base/controller
     - ../../base/node_linux
     patchesStrategicMerge: # or any other patch strategies (such as JsonPatches6902)
-    - <your-1-23-kustomize-diff-patch.yaml>
+    - <your-1-19-kustomize-diff-patch.yaml>
     transformers:
-    - ../../images/stable-1-23
+    - ../../images/stable-1-19
    ```
 
-   For `prow-stable-sidecar-rc-master`,
+   For `prow-gke-release-staging-rc-1-19`,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
     resources:
-    - ../stable-master
+    - ../stable-1-19
     transformers:
-    - ../../images/prow-stable-sidecar-rc-master
+    - ../../images/prow-gke-release-staging-rc-1-19
    ```
 
-   * If the changes are long term, make the changes to `deploy/kubernetes/base`, add the appropriate diff to remove the changes from the overlays less than `stable-1-23`. The overlay kustomize would look something like this
+   * If the changes are long term, make the changes to `deploy/kubernetes/base`, add the appropriate diff to remove the changes from the overlays less than `stable-1-19`. The overlay kustomize would look something like this
 
-   For `stable-1-23`,
+   For `stable-1-19`,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
@@ -77,20 +78,20 @@ When it comes to creation of overlays there are no strict rules on how overlays
     - ../../base
     # no patches needed since changes merged to deploy/kubernetes/base
     transformers:
-    - ../../images/stable-1-23
+    - ../../images/stable-1-19
    ```
 
-   For `prow-stable-sidecar-rc-master`,
+   For `prow-gke-release-staging-rc-1-19`,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
     resources:
-    - ../stable-master
+    - ../stable-1-19
     transformers:
-    - ../../images/prow-stable-sidecar-rc-master
+    - ../../images/prow-gke-release-staging-rc-1-19
    ```
 
-   For `stable-1-22` and older overlays,
+   For `stable-1-18` and older overlays,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
@@ -99,30 +100,30 @@ When it comes to creation of overlays there are no strict rules on how overlays
     resources:
     - ../../base
     patchesStrategicMerge: # or any other patch strategies (such as JsonPatches6902)
-    - <your-1-22-kustomize-diff-remove-1-23-changes-patch.yaml>
+    - <your-1-18-kustomize-diff-remove-1-19-changes-patch.yaml>
     transformers:
-    - ../../images/stable-1-22
+    - ../../images/stable-1-18
    ```
 
 2. Sidecar image version update for existing overlays
-   * Consider a scenario where we have three existing stable overlays `stable-1-22`, `stable-1-23`, `stable-master`. Sidecar S1 is available 1.22+, S2 is available 1.23+. If we need to upgrade the image versions for these sidecars, we would do the following:
-   * Update the `deploy/kubernetes/images/prow-stable-sidecar-rc-master` for sidecar S1 and S2.
+   * Consider a scenario where we have three existing stable overlays `stable-1-17`, `stable-1-18`, `stable-master`. Sidecar S1 is available 1.17+, S2 is available 1.18+. If we need to upgrade the image versions for these sidecars, we would do the following:
+   * Update the `deploy/kubernetes/images/prow-gke-staging-release-rc-1-17` for sidecar S1, `deploy/kubernetes/images/prow-gke-staging-release-rc-1-18` and `deploy/kubernetes/images/prow-gke-staging-release-rc-master` for S1 and S2.
    * Validate the changes made to the staging overlays. Ensure the upstream testgrids like [this](https://k8s-testgrid.appspot.com/provider-gcp-compute-persistent-disk-csi-driver) are green, and verify with repository maintainers that downstream test grids (e.g GKE internal prow test grids) are green.
-   * Now update `deploy/kubernetes/images/stable-1-22` for sidecar S1, and `deploy/kubernetes/images/stable-1-23`, `deploy/kubernetes/images/stable-master` for sidecar S1 and S2. Repository maintainers should ensure that any internal downstream testgrids are green before approving the pull request to merge changes to a stable overlay.
+   * Now update `deploy/kubernetes/images/stable-1-17` for sidecar S1, and `deploy/kubernetes/images/stable-1-18`, `deploy/kubernetes/images/stable-master` for sidecar S1 and S2. Repository maintainers should ensure that any internal downstream testgrids are green before approving the pull request to merge changes to a stable overlay.
 
 3. Sidecar spec changes
-   * Consider a scenario where a sidecar S1 has version V1 in 1.22 and V2 in 1.23. V2 introcudes a new capability via a new arg 'new-flag' (and say this flag deprecates 'old-flag'). To introduce this change, first we make changes to the `deploy/kubernetes/images/prow-stable-sidecar-rc-master` sidecar spec.
+   * Consider a scenario where a sidecar S1 has version V1 in 1.17 and V2 in 1.18. V2 introcudes a new capability via a new arg 'new-flag' (and say this flag deprecates 'old-flag'). To introduce this change, first we make changes to the `deploy/kubernetes/images/prow-gke-staging-release-rc-1-18` sidecar spec.
 
-   For `prow-stable-sidecar-rc-master` overlay, 
+   For `prow-gke-staging-release-rc-1-18` overlay, 
    ```
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
-   - ../stable-master
+   - ../stable-1-18
    patchesStrategicMerge: # or any other patch strategies (such as JsonPatches6902)
-   - <your-1-23-kustomize-diff-patch-for-new-sidecar-spec.yaml>
+   - <your-1-18-kustomize-diff-patch-for-new-sidecar-spec.yaml>
    transformers:
-   - ../../images/prow-stable-sidecar-rc-master
+   - ../../images/prow-gke-release-staging-rc-1-18
    ```
 
    * Validate the changes made to the staging overlays. Ensure the upstream testgrids like [this](https://k8s-testgrid.appspot.com/provider-gcp-compute-persistent-disk-csi-driver) are green, and verify with repository maintainers that downstream test grids (e.g GKE internal prow test grids) are green.
@@ -137,7 +138,7 @@ When it comes to creation of overlays there are no strict rules on how overlays
    ```
 
    * 
-   For `stable-1-23`,
+   For `stable-1-18`,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
@@ -147,20 +148,20 @@ When it comes to creation of overlays there are no strict rules on how overlays
     - ../../base
     # no patches needed since changes merged to deploy/kubernetes/base
     transformers:
-    - ../../images/stable-1-23
+    - ../../images/stable-1-18
    ```
 
-   For `prow-stable-sidecar-rc-master`,
+   For `prow-gke-release-staging-rc-1-18`,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
     resources:
-    - ../stable-master
+    - ../stable-1-18
     transformers:
-    - ../../images/prow-stable-sidecar-rc-master
+    - ../../images/prow-gke-release-staging-rc-1-18
    ```
 
-   For `stable-1-22` and older overlays,
+   For `stable-1-17` and older overlays,
    ```
     apiVersion: kustomize.config.k8s.io/v1beta1
     kind: Kustomization
@@ -169,14 +170,14 @@ When it comes to creation of overlays there are no strict rules on how overlays
     resources:
     - ../../base
     patchesStrategicMerge: # or any other patch strategies (such as JsonPatches6902)
-    - <your-1-22-kustomize-diff-patch-to-replace-new-flag-with-old-flag.yaml>
+    - <your-1-17-kustomize-diff-patch-to-replace-new-flag-with-old-flag.yaml>
     transformers:
-    - ../../images/stable-1-22
+    - ../../images/stable-1-17
    ```
 
 4. Driver image update
-   * If we have released a new driver image version, update the drivers image version in `deploy/kubernetes/images/prow-stable-sidecar-rc-master/image.yaml`. 
-   * Validate the staging drivers and then make changes to the `deploy/kubernetes/images/stable-{k8s-minor}/image.yaml` and `deploy/kubernetes/images/stable-master/image.yaml`, for whichever k8s minor versions are compatible with the new driver image version.
+   * If we have released a new driver image version, update the `deploy/kubernetes/images/prow-gke-release-staging-rc-{k8s-minor}/image.yaml` and `deploy/kubernetes/images/prow-gke-release-staging-rc-master/image.yaml`, for whichever k8s minor version are compatible with the new driver image version.
+   * Validate the staging drivers and then make changes to the `deploy/kubernetes/images/stable-{k8s-minor}/image.yaml`and `deploy/kubernetes/images/stable-master/image.yaml` (as needed).
 
 5. Cutting new releases
    * With the master branch maintaining the stable-x.y overlays, the master branch stable overlays can always be the referenced to pick the latest and greatest stable driver manifest bundle.
diff --git a/pkg/common/parameters.go b/pkg/common/parameters.go
index ea36f627..8ef4e3ed 100644
--- a/pkg/common/parameters.go
+++ b/pkg/common/parameters.go
@@ -30,11 +30,8 @@ const (
 
 	// Parameters for VolumeSnapshotClass
 	ParameterKeyStorageLocations = "storage-locations"
-	ParameterKeySnapshotType     = "snapshot-type"
-	ParameterKeyImageFamily      = "image-family"
-	DiskSnapshotType             = "snapshots"
-	DiskImageType                = "images"
-	replicationTypeNone          = "none"
+
+	replicationTypeNone = "none"
 
 	// Keys for PV and PVC parameters as reported by external-provisioner
 	ParameterKeyPVCName      = "csi.storage.k8s.io/pvc/name"
@@ -70,8 +67,6 @@ type DiskParameters struct {
 // SnapshotParameters contains normalized and defaulted parameters for snapshots
 type SnapshotParameters struct {
 	StorageLocations []string
-	SnapshotType     string
-	ImageFamily      string
 }
 
 // ExtractAndDefaultParameters will take the relevant parameters from a map and
@@ -136,7 +131,6 @@ func ExtractAndDefaultParameters(parameters map[string]string, driverName string
 func ExtractAndDefaultSnapshotParameters(parameters map[string]string) (SnapshotParameters, error) {
 	p := SnapshotParameters{
 		StorageLocations: []string{},
-		SnapshotType:     DiskSnapshotType,
 	}
 	for k, v := range parameters {
 		switch strings.ToLower(k) {
@@ -146,14 +140,6 @@ func ExtractAndDefaultSnapshotParameters(parameters map[string]string) (Snapshot
 				return p, err
 			}
 			p.StorageLocations = normalizedStorageLocations
-		case ParameterKeySnapshotType:
-			err := ValidateSnapshotType(v)
-			if err != nil {
-				return p, err
-			}
-			p.SnapshotType = v
-		case ParameterKeyImageFamily:
-			p.ImageFamily = v
 		default:
 			return p, fmt.Errorf("parameters contains invalid option %q", k)
 		}
diff --git a/pkg/common/utils.go b/pkg/common/utils.go
index d5842ea3..6b71feb7 100644
--- a/pkg/common/utils.go
+++ b/pkg/common/utils.go
@@ -114,15 +114,15 @@ func GenerateUnderspecifiedVolumeID(diskName string, isZonal bool) string {
 	return fmt.Sprintf(volIDRegionalFmt, UnspecifiedValue, UnspecifiedValue, diskName)
 }
 
-func SnapshotIDToProjectKey(id string) (string, string, string, error) {
+func SnapshotIDToProjectKey(id string) (string, string, error) {
 	splitId := strings.Split(id, "/")
 	if len(splitId) != snapshotTotalElements {
-		return "", "", "", fmt.Errorf("failed to get id components. Expected projects/{project}/global/{snapshots|images}/{name}. Got: %s", id)
+		return "", "", fmt.Errorf("failed to get id components. Expected projects/{project}/global/snapshot/{name}. Got: %s", id)
 	}
 	if splitId[snapshotTopologyKey] == "global" {
-		return splitId[snapshotProjectKey], splitId[snapshotTotalElements-2], splitId[snapshotTotalElements-1], nil
+		return splitId[snapshotProjectKey], splitId[snapshotTotalElements-1], nil
 	} else {
-		return "", "", "", fmt.Errorf("could not get id components, expected global, got: %v", splitId[snapshotTopologyKey])
+		return "", "", fmt.Errorf("could not get id components, expected global, got: %v", splitId[snapshotTopologyKey])
 	}
 }
 
@@ -238,13 +238,3 @@ func ProcessStorageLocations(storageLocations string) ([]string, error) {
 	}
 	return []string{normalizedLoc}, nil
 }
-
-// ValidateSnapshotType validates the type
-func ValidateSnapshotType(snapshotType string) error {
-	switch snapshotType {
-	case DiskSnapshotType, DiskImageType:
-		return nil
-	default:
-		return fmt.Errorf("invalid snapshot type %s", snapshotType)
-	}
-}
diff --git a/pkg/gce-cloud-provider/compute/fake-gce.go b/pkg/gce-cloud-provider/compute/fake-gce.go
index dd995316..6a7adeff 100644
--- a/pkg/gce-cloud-provider/compute/fake-gce.go
+++ b/pkg/gce-cloud-provider/compute/fake-gce.go
@@ -17,6 +17,7 @@ package gcecloudprovider
 import (
 	"context"
 	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
@@ -36,7 +37,6 @@ const (
 	Timestamp                 = "2018-09-05T15:17:08.270-07:00"
 	BasePath                  = "https://www.googleapis.com/compute/v1/projects/"
 	snapshotURITemplateGlobal = "%s/global/snapshots/%s" //{gce.projectID}/global/snapshots/{snapshot.Name}"
-	imageURITemplateGlobal    = "%s/global/images/%s"    //{gce.projectID}/global/images/{image.Name}"
 )
 
 type FakeCloudProvider struct {
@@ -47,7 +47,6 @@ type FakeCloudProvider struct {
 	pageTokens map[string]sets.String
 	instances  map[string]*computev1.Instance
 	snapshots  map[string]*computev1.Snapshot
-	images     map[string]*computev1.Image
 
 	// marker to set disk status during InsertDisk operation.
 	mockDiskStatus string
@@ -62,7 +61,6 @@ func CreateFakeCloudProvider(project, zone string, cloudDisks []*CloudDisk) (*Fa
 		disks:      map[string]*CloudDisk{},
 		instances:  map[string]*computev1.Instance{},
 		snapshots:  map[string]*computev1.Snapshot{},
-		images:     map[string]*computev1.Image{},
 		pageTokens: map[string]sets.String{},
 		// A newly created disk is marked READY by default.
 		mockDiskStatus: "READY",
@@ -124,7 +122,7 @@ func (cloud *FakeCloudProvider) ListDisks(ctx context.Context) ([]*computev1.Dis
 	return d, "", nil
 }
 
-func (cloud *FakeCloudProvider) ListSnapshots(ctx context.Context, filter string) ([]*computev1.Snapshot, string, error) {
+func (cloud *FakeCloudProvider) ListSnapshots(ctx context.Context, filter string, maxEntries int64, pageToken string) ([]*computev1.Snapshot, string, error) {
 	var sourceDisk string
 	snapshots := []*computev1.Snapshot{}
 	if len(filter) > 0 {
@@ -143,7 +141,45 @@ func (cloud *FakeCloudProvider) ListSnapshots(ctx context.Context, filter string
 		snapshots = append(snapshots, snapshot)
 	}
 
-	return snapshots, "", nil
+	var (
+		ulenSnapshots = len(snapshots)
+		startingToken int
+	)
+
+	if len(pageToken) > 0 {
+		i, err := strconv.ParseUint(pageToken, 10, 32)
+		if err != nil {
+			return nil, "", invalidError()
+		}
+		startingToken = int(i)
+	}
+
+	if startingToken > ulenSnapshots {
+		return nil, "", invalidError()
+	}
+
+	// Discern the number of remaining entries.
+	rem := ulenSnapshots - startingToken
+
+	// If maxEntries is 0 or greater than the number of remaining entries then
+	// set maxEntries to the number of remaining entries.
+	max := int(maxEntries)
+	if max == 0 || max > rem {
+		max = rem
+	}
+
+	results := []*computev1.Snapshot{}
+	j := startingToken
+	for i := 0; i < max; i++ {
+		results = append(results, snapshots[j])
+		j++
+	}
+
+	var nextToken string
+	if j < ulenSnapshots {
+		nextToken = fmt.Sprintf("%d", j)
+	}
+	return results, nextToken, nil
 }
 
 // Disk Methods
@@ -202,7 +238,6 @@ func (cloud *FakeCloudProvider) InsertDisk(ctx context.Context, project string,
 		Type:             cloud.GetDiskTypeURI(project, volKey, params.DiskType),
 		SourceSnapshotId: snapshotID,
 		SourceDiskId:     volumeContentSourceVolumeID,
-		SourceImageId:    snapshotID,
 		Status:           cloud.mockDiskStatus,
 		Labels:           params.Labels,
 	}
@@ -364,71 +399,6 @@ func (cloud *FakeCloudProvider) DeleteSnapshot(ctx context.Context, project, sna
 	return nil
 }
 
-func (cloud *FakeCloudProvider) ListImages(ctx context.Context, filter string) ([]*computev1.Image, string, error) {
-	var sourceDisk string
-	images := []*computev1.Image{}
-	if len(filter) > 0 {
-		filterSplits := strings.Fields(filter)
-		if len(filterSplits) != 3 || filterSplits[0] != "sourceDisk" {
-			return nil, "", invalidError()
-		}
-		sourceDisk = filterSplits[2]
-	}
-	for _, image := range cloud.images {
-		if len(sourceDisk) > 0 {
-			if image.SourceDisk == sourceDisk {
-				continue
-			}
-		}
-		images = append(images, image)
-	}
-
-	return images, "", nil
-}
-
-func (cloud *FakeCloudProvider) GetImage(ctx context.Context, project, imageName string) (*computev1.Image, error) {
-	image, ok := cloud.images[imageName]
-	if !ok {
-		return nil, notFoundError()
-	}
-	image.Status = "READY"
-	return image, nil
-}
-
-func (cloud *FakeCloudProvider) CreateImage(ctx context.Context, project string, volKey *meta.Key, imageName string, snapshotParams common.SnapshotParameters) (*computev1.Image, error) {
-	if image, ok := cloud.images[imageName]; ok {
-		return image, nil
-	}
-
-	imageToCreate := &computev1.Image{
-		CreationTimestamp: Timestamp,
-		DiskSizeGb:        int64(DiskSizeGb),
-		Family:            snapshotParams.ImageFamily,
-		Name:              imageName,
-		SelfLink:          cloud.getGlobalImageURI(project, imageName),
-		SourceType:        "RAW",
-		Status:            "PENDING",
-		StorageLocations:  snapshotParams.StorageLocations,
-	}
-
-	switch volKey.Type() {
-	case meta.Zonal:
-		imageToCreate.SourceDisk = cloud.getZonalDiskSourceURI(project, volKey.Name, volKey.Zone)
-	case meta.Regional:
-		imageToCreate.SourceDisk = cloud.getRegionalDiskSourceURI(project, volKey.Name, volKey.Region)
-	default:
-		return nil, fmt.Errorf("could not create image, disk key was neither zonal nor regional, instead got: %v", volKey.String())
-	}
-
-	cloud.images[imageName] = imageToCreate
-	return imageToCreate, nil
-}
-
-func (cloud *FakeCloudProvider) DeleteImage(ctx context.Context, project, imageName string) error {
-	delete(cloud.images, imageName)
-	return nil
-}
-
 func (cloud *FakeCloudProvider) ValidateExistingSnapshot(resp *computev1.Snapshot, volKey *meta.Key) error {
 	if resp == nil {
 		return fmt.Errorf("disk does not exist")
@@ -477,13 +447,6 @@ func (cloud *FakeCloudProvider) getGlobalSnapshotURI(project, snapshotName strin
 		snapshotName)
 }
 
-func (cloud *FakeCloudProvider) getGlobalImageURI(project, imageName string) string {
-	return BasePath + fmt.Sprintf(
-		imageURITemplateGlobal,
-		project,
-		imageName)
-}
-
 func (cloud *FakeCloudProvider) UpdateDiskStatus(s string) {
 	cloud.mockDiskStatus = s
 }
@@ -504,13 +467,6 @@ func (cloud *FakeBlockingCloudProvider) CreateSnapshot(ctx context.Context, proj
 	return cloud.FakeCloudProvider.CreateSnapshot(ctx, project, volKey, snapshotName, snapshotParams)
 }
 
-func (cloud *FakeBlockingCloudProvider) CreateImage(ctx context.Context, project string, volKey *meta.Key, imageName string, snapshotParams common.SnapshotParameters) (*computev1.Image, error) {
-	executeCreateSnapshot := make(chan struct{})
-	cloud.ReadyToExecute <- executeCreateSnapshot
-	<-executeCreateSnapshot
-	return cloud.FakeCloudProvider.CreateImage(ctx, project, volKey, imageName, snapshotParams)
-}
-
 func notFoundError() *googleapi.Error {
 	return &googleapi.Error{
 		Errors: []googleapi.ErrorItem{
diff --git a/pkg/gce-cloud-provider/compute/gce-compute.go b/pkg/gce-cloud-provider/compute/gce-compute.go
index 8d1818c5..f8949950 100644
--- a/pkg/gce-cloud-provider/compute/gce-compute.go
+++ b/pkg/gce-cloud-provider/compute/gce-compute.go
@@ -35,7 +35,6 @@ import (
 const (
 	operationStatusDone            = "DONE"
 	waitForSnapshotCreationTimeOut = 2 * time.Minute
-	waitForImageCreationTimeOut    = 5 * time.Minute
 	diskKind                       = "compute#disk"
 	cryptoKeyVerDelimiter          = "/cryptoKeyVersions"
 )
@@ -72,14 +71,10 @@ type GCECompute interface {
 	GetInstanceOrError(ctx context.Context, instanceZone, instanceName string) (*computev1.Instance, error)
 	// Zone Methods
 	ListZones(ctx context.Context, region string) ([]string, error)
-	ListSnapshots(ctx context.Context, filter string) ([]*computev1.Snapshot, string, error)
+	ListSnapshots(ctx context.Context, filter string, maxEntries int64, pageToken string) ([]*computev1.Snapshot, string, error)
 	GetSnapshot(ctx context.Context, project, snapshotName string) (*computev1.Snapshot, error)
 	CreateSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters) (*computev1.Snapshot, error)
 	DeleteSnapshot(ctx context.Context, project, snapshotName string) error
-	ListImages(ctx context.Context, filter string) ([]*computev1.Image, string, error)
-	GetImage(ctx context.Context, project, imageName string) (*computev1.Image, error)
-	CreateImage(ctx context.Context, project string, volKey *meta.Key, imageName string, snapshotParams common.SnapshotParameters) (*computev1.Image, error)
-	DeleteImage(ctx context.Context, project, imageName string) error
 }
 
 // GetDefaultProject returns the project that was used to instantiate this GCE client.
@@ -194,19 +189,18 @@ func (cloud *CloudProvider) ListZones(ctx context.Context, region string) ([]str
 
 }
 
-func (cloud *CloudProvider) ListSnapshots(ctx context.Context, filter string) ([]*computev1.Snapshot, string, error) {
-	klog.V(5).Infof("Listing snapshots with filter: %s", filter)
-	items := []*computev1.Snapshot{}
-	lCall := cloud.service.Snapshots.List(cloud.project).Filter(filter)
-	nextPageToken := "pageToken"
-	for nextPageToken != "" {
-		snapshotList, err := lCall.Do()
-		if err != nil {
-			return nil, "", err
-		}
-		items = append(items, snapshotList.Items...)
+func (cloud *CloudProvider) ListSnapshots(ctx context.Context, filter string, maxEntries int64, pageToken string) ([]*computev1.Snapshot, string, error) {
+	klog.V(5).Infof("Listing snapshots with filter: %s, max entries: %v, page token: %s", filter, maxEntries, pageToken)
+	snapshots := []*computev1.Snapshot{}
+	snapshotList, err := cloud.service.Snapshots.List(cloud.project).Filter(filter).MaxResults(maxEntries).PageToken(pageToken).Do()
+	if err != nil {
+		return snapshots, "", err
 	}
-	return items, "", nil
+	for _, snapshot := range snapshotList.Items {
+		snapshots = append(snapshots, snapshot)
+	}
+	return snapshots, snapshotList.NextPageToken, nil
+
 }
 
 func (cloud *CloudProvider) GetDisk(ctx context.Context, project string, key *meta.Key, gceAPIVersion GCEAPIVersion) (*CloudDisk, error) {
@@ -404,23 +398,11 @@ func (cloud *CloudProvider) insertRegionalDisk(
 		Labels:      params.Labels,
 	}
 	if snapshotID != "" {
-		_, snapshotType, _, err := common.SnapshotIDToProjectKey(snapshotID)
-		if err != nil {
-			return err
-		}
-		switch snapshotType {
-		case common.DiskSnapshotType:
-			diskToCreate.SourceSnapshot = snapshotID
-		case common.DiskImageType:
-			diskToCreate.SourceImage = snapshotID
-		default:
-			return fmt.Errorf("invalid snapshot type in snapshot ID: %s", snapshotType)
-		}
+		diskToCreate.SourceSnapshot = snapshotID
 	}
 	if volumeContentSourceVolumeID != "" {
 		diskToCreate.SourceDisk = volumeContentSourceVolumeID
 	}
-
 	if len(replicaZones) != 0 {
 		diskToCreate.ReplicaZones = replicaZones
 	}
@@ -517,18 +499,7 @@ func (cloud *CloudProvider) insertZonalDisk(
 	}
 
 	if snapshotID != "" {
-		_, snapshotType, _, err := common.SnapshotIDToProjectKey(snapshotID)
-		if err != nil {
-			return err
-		}
-		switch snapshotType {
-		case common.DiskSnapshotType:
-			diskToCreate.SourceSnapshot = snapshotID
-		case common.DiskImageType:
-			diskToCreate.SourceImage = snapshotID
-		default:
-			return fmt.Errorf("invalid snapshot type in snapshot ID: %s", snapshotType)
-		}
+		diskToCreate.SourceSnapshot = snapshotID
 	}
 	if volumeContentSourceVolumeID != "" {
 		diskToCreate.SourceDisk = volumeContentSourceVolumeID
@@ -858,94 +829,6 @@ func (cloud *CloudProvider) CreateSnapshot(ctx context.Context, project string,
 	}
 }
 
-func (cloud *CloudProvider) CreateImage(ctx context.Context, project string, volKey *meta.Key, imageName string, snapshotParams common.SnapshotParameters) (*computev1.Image, error) {
-	klog.V(5).Infof("Creating image %s for source %v", imageName, volKey)
-	diskID, err := common.KeyToVolumeID(volKey, project)
-	if err != nil {
-		return nil, err
-	}
-	image := &computev1.Image{
-		SourceDisk:       diskID,
-		Family:           snapshotParams.ImageFamily,
-		Name:             imageName,
-		StorageLocations: snapshotParams.StorageLocations,
-	}
-
-	_, err = cloud.service.Images.Insert(project, image).Context(ctx).Do()
-	if err != nil {
-		return nil, err
-	}
-
-	return cloud.waitForImageCreation(ctx, project, imageName)
-}
-
-func (cloud *CloudProvider) waitForImageCreation(ctx context.Context, project, imageName string) (*computev1.Image, error) {
-	ticker := time.NewTicker(time.Second)
-	defer ticker.Stop()
-	timer := time.NewTimer(waitForImageCreationTimeOut)
-	defer timer.Stop()
-
-	for {
-		select {
-		case <-ticker.C:
-			klog.V(6).Infof("Checking GCE Image %s.", imageName)
-			image, err := cloud.GetImage(ctx, project, imageName)
-			if err != nil {
-				klog.Warningf("Error in getting image %s, %v", imageName, err)
-			} else if image != nil {
-				if image.Status != "PENDING" {
-					klog.V(6).Infof("Image %s status is %s", imageName, image.Status)
-					return image, nil
-				} else {
-					klog.V(6).Infof("Image %s is still pending", imageName)
-				}
-			}
-		case <-timer.C:
-			return nil, fmt.Errorf("timeout waiting for image %s to be created", imageName)
-		}
-	}
-}
-
-func (cloud *CloudProvider) GetImage(ctx context.Context, project, imageName string) (*computev1.Image, error) {
-	klog.V(5).Infof("Getting image %v", imageName)
-	image, err := cloud.service.Images.Get(project, imageName).Context(ctx).Do()
-	if err != nil {
-		return nil, err
-	}
-	return image, nil
-}
-
-func (cloud *CloudProvider) ListImages(ctx context.Context, filter string) ([]*computev1.Image, string, error) {
-	klog.V(5).Infof("Listing images with filter: %s", filter)
-	var items []*computev1.Image
-	lCall := cloud.service.Images.List(cloud.project).Context(ctx).Filter(filter)
-	nextPageToken := "pageToken"
-	for nextPageToken != "" {
-		imageList, err := lCall.Do()
-		if err != nil {
-			return nil, "", err
-		}
-		items = append(items, imageList.Items...)
-	}
-	return items, "", nil
-}
-
-func (cloud *CloudProvider) DeleteImage(ctx context.Context, project, imageName string) error {
-	klog.V(5).Infof("Deleting image %v", imageName)
-	op, err := cloud.service.Images.Delete(cloud.project, imageName).Context(ctx).Do()
-	if err != nil {
-		if IsGCEError(err, "notFound") {
-			return nil
-		}
-		return err
-	}
-	err = cloud.waitForGlobalOp(ctx, project, op.Name)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
 // ResizeDisk takes in the requested disk size in bytes and returns the resized
 // size in Gi
 // TODO(#461) The whole driver could benefit from standardized usage of the
diff --git a/pkg/gce-pd-csi-driver/controller.go b/pkg/gce-pd-csi-driver/controller.go
index 705ac41e..2ffa96e8 100644
--- a/pkg/gce-pd-csi-driver/controller.go
+++ b/pkg/gce-pd-csi-driver/controller.go
@@ -25,7 +25,6 @@ import (
 	"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
 	csi "github.com/container-storage-interface/spec/lib/go/csi"
 	"github.com/golang/protobuf/ptypes"
-	"github.com/golang/protobuf/ptypes/timestamp"
 	compute "google.golang.org/api/compute/v1"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -46,9 +45,6 @@ type GCEControllerServer struct {
 	disks []*compute.Disk
 	seen  map[string]int
 
-	snapshots      []*csi.ListSnapshotsResponse_Entry
-	snapshotTokens map[string]int
-
 	// A map storing all volumes with ongoing operations so that additional
 	// operations for that same volume (as defined by Volume Key) return an
 	// Aborted error
@@ -811,46 +807,19 @@ func (gceCS *GCEControllerServer) CreateSnapshot(ctx context.Context, req *csi.C
 		return nil, status.Error(codes.Internal, fmt.Sprintf("CreateSnapshot unknown get disk error: %v", err))
 	}
 
-	snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(req.GetParameters())
-	if err != nil {
-		return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid snapshot parameters: %v", err))
-	}
-
-	var snapshot *csi.Snapshot
-	switch snapshotParams.SnapshotType {
-	case common.DiskSnapshotType:
-		snapshot, err = gceCS.createPDSnapshot(ctx, project, volKey, req.Name, snapshotParams)
-		if err != nil {
-			return nil, err
-		}
-	case common.DiskImageType:
-		snapshot, err = gceCS.createImage(ctx, project, volKey, req.Name, snapshotParams)
-		if err != nil {
-			return nil, err
-		}
-	default:
-		return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid snapshot type: %s", snapshotParams.SnapshotType))
-	}
-
-	klog.V(4).Infof("CreateSnapshot succeeded for snapshot %s on volume %s", snapshot.SnapshotId, volumeID)
-	return &csi.CreateSnapshotResponse{Snapshot: snapshot}, nil
-}
-
-func (gceCS *GCEControllerServer) createPDSnapshot(ctx context.Context, project string, volKey *meta.Key, snapshotName string, snapshotParams common.SnapshotParameters) (*csi.Snapshot, error) {
-	volumeID, err := common.KeyToVolumeID(volKey, project)
-	if err != nil {
-		return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid volume key: %v", volKey))
-	}
-
-	// Check if PD snapshot already exists
+	// Check if snapshot already exists
 	var snapshot *compute.Snapshot
-	snapshot, err = gceCS.CloudProvider.GetSnapshot(ctx, project, snapshotName)
+	snapshot, err = gceCS.CloudProvider.GetSnapshot(ctx, project, req.Name)
 	if err != nil {
 		if !gce.IsGCEError(err, "notFound") {
 			return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown get snapshot error: %v", err))
 		}
 		// If we could not find the snapshot, we create a new one
-		snapshot, err = gceCS.CloudProvider.CreateSnapshot(ctx, project, volKey, snapshotName, snapshotParams)
+		snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(req.GetParameters())
+		if err != nil {
+			return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid snapshot parameters: %v", err))
+		}
+		snapshot, err = gceCS.CloudProvider.CreateSnapshot(ctx, project, volKey, req.Name, snapshotParams)
 		if err != nil {
 			if gce.IsGCEError(err, "notFound") {
 				return nil, status.Error(codes.NotFound, fmt.Sprintf("Could not find volume with ID %v: %v", volKey.String(), err))
@@ -863,122 +832,32 @@ func (gceCS *GCEControllerServer) createPDSnapshot(ctx context.Context, project
 	if err != nil {
 		return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Error in creating snapshot: %v", err))
 	}
-
-	timestamp, err := parseTimestamp(snapshot.CreationTimestamp)
+	t, err := time.Parse(time.RFC3339, snapshot.CreationTimestamp)
 	if err != nil {
 		return nil, status.Error(codes.Internal, fmt.Sprintf("Failed to covert creation timestamp: %v", err))
 	}
 
-	ready, err := isCSISnapshotReady(snapshot.Status)
-	if err != nil {
-		return nil, status.Error(codes.Internal, fmt.Sprintf("Snapshot had error checking ready status: %v", err))
-	}
-
-	return &csi.Snapshot{
-		SizeBytes:      common.GbToBytes(snapshot.DiskSizeGb),
-		SnapshotId:     cleanSelfLink(snapshot.SelfLink),
-		SourceVolumeId: volumeID,
-		CreationTime:   timestamp,
-		ReadyToUse:     ready,
-	}, nil
-}
-
-func (gceCS *GCEControllerServer) createImage(ctx context.Context, project string, volKey *meta.Key, imageName string, snapshotParams common.SnapshotParameters) (*csi.Snapshot, error) {
-	volumeID, err := common.KeyToVolumeID(volKey, project)
-	if err != nil {
-		return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid volume key: %v", volKey))
-	}
-
-	// Check if image already exists
-	var image *compute.Image
-	image, err = gceCS.CloudProvider.GetImage(ctx, project, imageName)
-	if err != nil {
-		if !gce.IsGCEError(err, "notFound") {
-			return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown get image error: %v", err))
-		}
-		// create a new image
-		image, err = gceCS.CloudProvider.CreateImage(ctx, project, volKey, imageName, snapshotParams)
-		if err != nil {
-			if gce.IsGCEError(err, "notFound") {
-				return nil, status.Error(codes.NotFound, fmt.Sprintf("Could not find volume with ID %v: %v", volKey.String(), err))
-			}
-			return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown create image error: %v", err))
-		}
-	}
-
-	err = gceCS.validateExistingImage(image, volKey)
-	if err != nil {
-		return nil, status.Errorf(codes.AlreadyExists, fmt.Sprintf("Error in creating snapshot: %v", err))
-	}
-
-	timestamp, err := parseTimestamp(image.CreationTimestamp)
+	tp, err := ptypes.TimestampProto(t)
 	if err != nil {
 		return nil, status.Error(codes.Internal, fmt.Sprintf("Failed to covert creation timestamp: %v", err))
 	}
 
-	ready, err := isImageReady(image.Status)
-	if err != nil {
-		return nil, status.Errorf(codes.Internal, fmt.Sprintf("Failed to check image status: %v", err))
-	}
-
-	return &csi.Snapshot{
-		SizeBytes:      common.GbToBytes(image.DiskSizeGb),
-		SnapshotId:     cleanSelfLink(image.SelfLink),
-		SourceVolumeId: volumeID,
-		CreationTime:   timestamp,
-		ReadyToUse:     ready,
-	}, nil
-}
-
-func (gceCS *GCEControllerServer) validateExistingImage(image *compute.Image, volKey *meta.Key) error {
-	if image == nil {
-		return fmt.Errorf("disk does not exist")
-	}
-
-	_, sourceKey, err := common.VolumeIDToKey(cleanSelfLink(image.SourceDisk))
-	if err != nil {
-		return fmt.Errorf("fail to get source disk key %s, %v", image.SourceDisk, err)
-	}
-
-	if sourceKey.String() != volKey.String() {
-		return fmt.Errorf("image already exists with same name but with a different disk source %s, expected disk source %s", sourceKey.String(), volKey.String())
-	}
-
-	klog.V(5).Infof("Compatible image %s exists with source disk %s.", image.Name, image.SourceDisk)
-	return nil
-}
-
-func parseTimestamp(creationTimestamp string) (*timestamp.Timestamp, error) {
-	t, err := time.Parse(time.RFC3339, creationTimestamp)
+	ready, err := isCSISnapshotReady(snapshot.Status)
 	if err != nil {
-		return nil, err
+		return nil, status.Error(codes.Internal, fmt.Sprintf("Snapshot had error checking ready status: %v", err))
 	}
 
-	timestamp, err := ptypes.TimestampProto(t)
-	if err != nil {
-		return nil, err
-	}
-	return timestamp, nil
-}
-func isImageReady(status string) (bool, error) {
-	// Possible status:
-	//   "DELETING"
-	//   "FAILED"
-	//   "PENDING"
-	//   "READY"
-	switch status {
-	case "DELETING":
-		klog.V(4).Infof("image status is DELETING")
-		return true, nil
-	case "FAILED":
-		return false, fmt.Errorf("image status is FAILED")
-	case "PENDING":
-		return false, nil
-	case "READY":
-		return true, nil
-	default:
-		return false, fmt.Errorf("unknown image status %s", status)
+	createResp := &csi.CreateSnapshotResponse{
+		Snapshot: &csi.Snapshot{
+			SizeBytes:      common.GbToBytes(snapshot.DiskSizeGb),
+			SnapshotId:     cleanSelfLink(snapshot.SelfLink),
+			SourceVolumeId: volumeID,
+			CreationTime:   tp,
+			ReadyToUse:     ready,
+		},
 	}
+	klog.V(4).Infof("CreateSnapshot succeeded for snapshot %s on volume %s", cleanSelfLink(snapshot.SelfLink), volumeID)
+	return createResp, nil
 }
 
 func (gceCS *GCEControllerServer) validateExistingSnapshot(snapshot *compute.Snapshot, volKey *meta.Key) error {
@@ -1020,7 +899,7 @@ func (gceCS *GCEControllerServer) DeleteSnapshot(ctx context.Context, req *csi.D
 		return nil, status.Error(codes.InvalidArgument, "DeleteSnapshot Snapshot ID must be provided")
 	}
 
-	project, snapshotType, key, err := common.SnapshotIDToProjectKey(snapshotID)
+	project, key, err := common.SnapshotIDToProjectKey(snapshotID)
 	if err != nil {
 		// Cannot get snapshot ID from the passing request
 		// This is a success according to the spec
@@ -1028,19 +907,9 @@ func (gceCS *GCEControllerServer) DeleteSnapshot(ctx context.Context, req *csi.D
 		return &csi.DeleteSnapshotResponse{}, nil
 	}
 
-	switch snapshotType {
-	case common.DiskSnapshotType:
-		err = gceCS.CloudProvider.DeleteSnapshot(ctx, project, key)
-		if err != nil {
-			return nil, status.Error(codes.Internal, fmt.Sprintf("unknown Delete snapshot error: %v", err))
-		}
-	case common.DiskImageType:
-		err = gceCS.CloudProvider.DeleteImage(ctx, project, key)
-		if err != nil {
-			return nil, status.Error(codes.Internal, fmt.Sprintf("unknown Delete image error: %v", err))
-		}
-	default:
-		return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("unknown snapshot type %s", snapshotType))
+	err = gceCS.CloudProvider.DeleteSnapshot(ctx, project, key)
+	if err != nil {
+		return nil, status.Error(codes.Internal, fmt.Sprintf("unknown Delete snapshot error: %v", err))
 	}
 
 	return &csi.DeleteSnapshotResponse{}, nil
@@ -1053,48 +922,7 @@ func (gceCS *GCEControllerServer) ListSnapshots(ctx context.Context, req *csi.Li
 	}
 
 	// case 2: no SnapshotId is set, so we return all the snapshots that satify the reqeust.
-	var maxEntries int = int(req.MaxEntries)
-	if maxEntries < 0 {
-		return nil, status.Error(codes.InvalidArgument, fmt.Sprintf(
-			"ListSnapshots got max entries request %v. GCE only supports values >0", maxEntries))
-	}
-
-	var offset int
-	var length int
-	var ok bool
-	var nextToken string
-	if req.StartingToken == "" {
-		snapshotList, err := gceCS.getSnapshots(ctx, req)
-		if err != nil {
-			if gce.IsGCEInvalidError(err) {
-				return nil, status.Error(codes.Aborted, fmt.Sprintf("ListSnapshots error with invalid request: %v", err))
-			}
-			return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown list snapshots error: %v", err))
-		}
-		gceCS.snapshots = snapshotList
-		gceCS.snapshotTokens = map[string]int{}
-	} else {
-		offset, ok = gceCS.snapshotTokens[req.StartingToken]
-		if !ok {
-			return nil, status.Error(codes.Aborted, fmt.Sprintf("ListSnapshots error with invalid startingToken: %s", req.StartingToken))
-		}
-	}
-
-	if maxEntries == 0 {
-		maxEntries = len(gceCS.snapshots)
-	}
-	if maxEntries < len(gceCS.snapshots)-offset {
-		length = maxEntries
-		nextToken = string(uuid.NewUUID())
-		gceCS.snapshotTokens[nextToken] = length + offset
-	} else {
-		length = len(gceCS.snapshots) - offset
-	}
-
-	return &csi.ListSnapshotsResponse{
-		Entries:   gceCS.snapshots[offset : offset+length],
-		NextToken: nextToken,
-	}, nil
+	return gceCS.getSnapshots(ctx, req)
 }
 
 func (gceCS *GCEControllerServer) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) {
@@ -1133,90 +961,59 @@ func (gceCS *GCEControllerServer) ControllerExpandVolume(ctx context.Context, re
 	}, nil
 }
 
-func (gceCS *GCEControllerServer) getSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) ([]*csi.ListSnapshotsResponse_Entry, error) {
+func (gceCS *GCEControllerServer) getSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
 	var snapshots []*compute.Snapshot
-	var images []*compute.Image
-	var filter string
+	var nextToken string
 	var err error
 	if len(req.GetSourceVolumeId()) != 0 {
-		filter = fmt.Sprintf("sourceDisk eq .*%s$", req.SourceVolumeId)
+		snapshots, nextToken, err = gceCS.CloudProvider.ListSnapshots(ctx, fmt.Sprintf("sourceDisk eq .*%s$", req.SourceVolumeId), int64(req.MaxEntries), req.StartingToken)
+	} else {
+		snapshots, nextToken, err = gceCS.CloudProvider.ListSnapshots(ctx, "", int64(req.MaxEntries), req.StartingToken)
 	}
-	snapshots, _, err = gceCS.CloudProvider.ListSnapshots(ctx, filter)
 	if err != nil {
 		if gce.IsGCEError(err, "invalid") {
 			return nil, status.Error(codes.Aborted, fmt.Sprintf("Invalid error: %v", err))
 		}
 		return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown list snapshot error: %v", err))
 	}
-
-	images, _, err = gceCS.CloudProvider.ListImages(ctx, filter)
-	if err != nil {
-		if gce.IsGCEError(err, "invalid") {
-			return nil, status.Error(codes.Aborted, fmt.Sprintf("Invalid error: %v", err))
-		}
-		return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown list image error: %v", err))
-	}
-
 	entries := []*csi.ListSnapshotsResponse_Entry{}
 
 	for _, snapshot := range snapshots {
-		entry, err := generateDiskSnapshotEntry(snapshot)
+		entry, err := generateSnapshotEntry(snapshot)
 		if err != nil {
 			return nil, fmt.Errorf("failed to generate snapshot entry: %v", err)
 		}
 		entries = append(entries, entry)
 	}
-
-	for _, image := range images {
-		entry, err := generateDiskImageEntry(image)
-		if err != nil {
-			return nil, fmt.Errorf("failed to generate image entry: %v", err)
-		}
-		entries = append(entries, entry)
+	listSnapshotResp := &csi.ListSnapshotsResponse{
+		Entries:   entries,
+		NextToken: nextToken,
 	}
-
-	return entries, nil
+	return listSnapshotResp, nil
 }
 
 func (gceCS *GCEControllerServer) getSnapshotByID(ctx context.Context, snapshotID string) (*csi.ListSnapshotsResponse, error) {
-	project, snapshotType, key, err := common.SnapshotIDToProjectKey(snapshotID)
+	project, key, err := common.SnapshotIDToProjectKey(snapshotID)
 	if err != nil {
 		// Cannot get snapshot ID from the passing request
 		klog.Warningf("invalid snapshot id format %s", snapshotID)
 		return &csi.ListSnapshotsResponse{}, nil
 	}
 
-	var entries []*csi.ListSnapshotsResponse_Entry
-	switch snapshotType {
-	case common.DiskSnapshotType:
-		snapshot, err := gceCS.CloudProvider.GetSnapshot(ctx, project, key)
-		if err != nil {
-			if gce.IsGCEError(err, "notFound") {
-				// return empty list if no snapshot is found
-				return &csi.ListSnapshotsResponse{}, nil
-			}
-			return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown list snapshot error: %v", err))
-		}
-		e, err := generateDiskSnapshotEntry(snapshot)
-		if err != nil {
-			return nil, fmt.Errorf("failed to generate snapshot entry: %v", err)
-		}
-		entries = []*csi.ListSnapshotsResponse_Entry{e}
-	case common.DiskImageType:
-		image, err := gceCS.CloudProvider.GetImage(ctx, project, key)
-		if err != nil {
-			if gce.IsGCEError(err, "notFound") {
-				// return empty list if no snapshot is found
-				return &csi.ListSnapshotsResponse{}, nil
-			}
-		}
-		e, err := generateImageEntry(image)
-		if err != nil {
-			return nil, fmt.Errorf("failed to generate image entry: %v", err)
+	snapshot, err := gceCS.CloudProvider.GetSnapshot(ctx, project, key)
+	if err != nil {
+		if gce.IsGCEError(err, "notFound") {
+			// return empty list if no snapshot is found
+			return &csi.ListSnapshotsResponse{}, nil
 		}
-		entries = []*csi.ListSnapshotsResponse_Entry{e}
+		return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown list snapshot error: %v", err))
+	}
+	e, err := generateSnapshotEntry(snapshot)
+	if err != nil {
+		return nil, fmt.Errorf("failed to generate snapshot entry: %v", err)
 	}
 
+	entries := []*csi.ListSnapshotsResponse_Entry{e}
 	//entries[0] = entry
 	listSnapshotResp := &csi.ListSnapshotsResponse{
 		Entries: entries,
@@ -1224,7 +1021,7 @@ func (gceCS *GCEControllerServer) getSnapshotByID(ctx context.Context, snapshotI
 	return listSnapshotResp, nil
 }
 
-func generateDiskSnapshotEntry(snapshot *compute.Snapshot) (*csi.ListSnapshotsResponse_Entry, error) {
+func generateSnapshotEntry(snapshot *compute.Snapshot) (*csi.ListSnapshotsResponse_Entry, error) {
 	t, _ := time.Parse(time.RFC3339, snapshot.CreationTimestamp)
 
 	tp, err := ptypes.TimestampProto(t)
@@ -1249,49 +1046,6 @@ func generateDiskSnapshotEntry(snapshot *compute.Snapshot) (*csi.ListSnapshotsRe
 	return entry, nil
 }
 
-func generateDiskImageEntry(image *compute.Image) (*csi.ListSnapshotsResponse_Entry, error) {
-	t, _ := time.Parse(time.RFC3339, image.CreationTimestamp)
-
-	tp, err := ptypes.TimestampProto(t)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to covert creation timestamp: %v", err)
-	}
-
-	ready, _ := isImageReady(image.Status)
-
-	entry := &csi.ListSnapshotsResponse_Entry{
-		Snapshot: &csi.Snapshot{
-			SizeBytes:      common.GbToBytes(image.DiskSizeGb),
-			SnapshotId:     cleanSelfLink(image.SelfLink),
-			SourceVolumeId: cleanSelfLink(image.SourceDisk),
-			CreationTime:   tp,
-			ReadyToUse:     ready,
-		},
-	}
-	return entry, nil
-}
-
-func generateImageEntry(image *compute.Image) (*csi.ListSnapshotsResponse_Entry, error) {
-	timestamp, err := parseTimestamp(image.CreationTimestamp)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to covert creation timestamp: %v", err)
-	}
-
-	// ignore the error intentionally here since we are just listing images
-	ready, _ := isImageReady(image.Status)
-
-	entry := &csi.ListSnapshotsResponse_Entry{
-		Snapshot: &csi.Snapshot{
-			SizeBytes:      common.GbToBytes(image.DiskSizeGb),
-			SnapshotId:     cleanSelfLink(image.SelfLink),
-			SourceVolumeId: cleanSelfLink(image.SourceDisk),
-			CreationTime:   timestamp,
-			ReadyToUse:     ready,
-		},
-	}
-	return entry, nil
-}
-
 func getRequestCapacity(capRange *csi.CapacityRange) (int64, error) {
 	var capBytes int64
 	// Default case where nothing is set
diff --git a/pkg/mount-manager/device-utils.go b/pkg/mount-manager/device-utils.go
index 1ea1ebed..60ff099b 100644
--- a/pkg/mount-manager/device-utils.go
+++ b/pkg/mount-manager/device-utils.go
@@ -36,6 +36,8 @@ const (
 	diskPartitionSuffix  = "-part"
 	diskSDPath           = "/dev/sd"
 	diskSDPattern        = "/dev/sd*"
+	diskNvmePath         = "/dev/nvme"
+	diskNvmePattern      = "/dev/nvme*"
 	// How many times to retry for a consistent read of /proc/mounts.
 	maxListTries = 3
 	// Number of fields per line in /proc/mounts as per the fstab man page.
@@ -52,11 +54,20 @@ const (
 	// scsi_id output should be in the form of:
 	// 0Google PersistentDisk <disk name>
 	scsiPattern = `^0Google\s+PersistentDisk\s+([\S]+)\s*$`
+	// google_nvme_id output should be in the form of:
+	// ID_SERIAL_SHORT=<disk name>
+	// Note: The google_nvme_id tool prints out multiple lines, hence we don't
+	// use '^' and '$' to wrap nvmePattern as is done in scsiPattern.
+	nvmePattern = `ID_SERIAL_SHORT=([\S]+)\s*`
+	scsiIdPath  = "/lib/udev_containerized/scsi_id"
+	nvmeIdPath  = "/lib/udev_containerized/google_nvme_id"
 )
 
 var (
 	// regex to parse scsi_id output and extract the serial
 	scsiRegex = regexp.MustCompile(scsiPattern)
+	// regex to parse google_nvme_id output and extract the serial
+	nvmeRegex = regexp.MustCompile(nvmePattern)
 )
 
 // DeviceUtils are a collection of methods that act on the devices attached
@@ -107,13 +118,13 @@ func existingDevicePath(devicePaths []string) (string, error) {
 	return "", nil
 }
 
-// getScsiSerial assumes that /lib/udev/scsi_id exists and will error if it
+// getScsiSerial assumes that scsiIdPath exists and will error if it
 // doesnt. It is the callers responsibility to verify the existence of this
 // tool. Calls scsi_id on the given devicePath to get the serial number reported
 // by that device.
 func getScsiSerial(devicePath string) (string, error) {
 	out, err := exec.Command(
-		"/lib/udev_containerized/scsi_id",
+		scsiIdPath,
 		"--page=0x83",
 		"--whitelisted",
 		fmt.Sprintf("--device=%v", devicePath)).CombinedOutput()
@@ -134,9 +145,58 @@ func parseScsiSerial(output string) (string, error) {
 	return substrings[1], nil
 }
 
+// getNvmeSerial calls google_nvme_id on the given devicePath to get the serial
+// number reported by that device.
+// NOTE: getNvmeSerial assumes that nvmeIdPath exists and will error if it
+// doesn't. It is the caller's responsibility to verify the existence of this
+// tool.
+func getNvmeSerial(devicePath string) (string, error) {
+	out, err := exec.Command(
+		nvmeIdPath,
+		fmt.Sprintf("-d%s", devicePath)).CombinedOutput()
+	if err != nil {
+		return "", fmt.Errorf("google_nvme_id failed for device %q with output %v: %v", devicePath, out, err)
+	}
+
+	return parseNvmeSerial(string(out))
+}
+
+// Parse the output returned by google_nvme_id and extract the serial number
+func parseNvmeSerial(output string) (string, error) {
+	substrings := nvmeRegex.FindStringSubmatch(output)
+	if substrings == nil {
+		return "", fmt.Errorf("google_nvme_id output cannot be parsed: %q", output)
+	}
+
+	return substrings[1], nil
+}
+
+func ensureUdevToolExists(toolPath string) error {
+	exists, err := pathutils.Exists(pathutils.CheckFollowSymlink, toolPath)
+	if err != nil {
+		return fmt.Errorf("failed to check existence of %q: %v", toolPath, err)
+	}
+	if !exists {
+		// The driver should be containerized with the tool so maybe something is
+		// wrong with the build process
+		return fmt.Errorf("could not find tool at %q, unable to verify device paths", nvmeIdPath)
+	}
+	return nil
+}
+
+func ensureUdevToolsExist() error {
+	if err := ensureUdevToolExists(scsiIdPath); err != nil {
+		return err
+	}
+	if err := ensureUdevToolExists(nvmeIdPath); err != nil {
+		return err
+	}
+	return nil
+}
+
 // VerifyDevicePath returns the first devicePath that maps to a real disk in the
-// candidate devicePaths or an empty string if none is found. If
-// /lib/udev_containerized/scsi_id exists it will attempt to fix any issues
+// candidate devicePaths or an empty string if none is found.
+// If the device is not found, it will attempt to fix any issues
 // caused by missing paths or mismatched devices by running a udevadm --trigger.
 func (m *deviceUtils) VerifyDevicePath(devicePaths []string, deviceName string) (string, error) {
 	var devicePath string
@@ -146,15 +206,10 @@ func (m *deviceUtils) VerifyDevicePath(devicePaths []string, deviceName string)
 		pollTimeout  = 3 * time.Second
 	)
 
-	scsiIDPath := "/lib/udev_containerized/scsi_id"
-	exists, err := pathutils.Exists(pathutils.CheckFollowSymlink, scsiIDPath)
+	// Ensure tools in /lib/udev_containerized directory exist
+	err = ensureUdevToolsExist()
 	if err != nil {
-		return "", fmt.Errorf("failed to check scsi_id existence: %v", err)
-	}
-	if !exists {
-		// No SCSI ID tool, the driver should be containerized with the tool so
-		// maybe something is wrong with the build process
-		return "", fmt.Errorf("could not find scsi_id tool at %s, unable to verify device paths", scsiIDPath)
+		return "", err
 	}
 
 	err = wait.Poll(pollInterval, pollTimeout, func() (bool, error) {
@@ -166,40 +221,41 @@ func (m *deviceUtils) VerifyDevicePath(devicePaths []string, deviceName string)
 		}
 
 		if len(devicePath) == 0 {
-			// Couldn't find the path so we need to find a /dev/sdx with the SCSI
-			// serial that matches deviceName. Then we run udevadm trigger on that
-			// device to get the device to show up in /dev/by-id/
+			// Couldn't find a /dev/disk/by-id path for this deviceName, so we need to
+			// find a /dev/* with a serial that matches deviceName. Then we attempt
+			// to repair the symlink.
 			innerErr := udevadmTriggerForDiskIfExists(deviceName)
 			if innerErr != nil {
-				return false, fmt.Errorf("failed to trigger udevadm fix: %v", innerErr)
+				return false, fmt.Errorf("failed to trigger udevadm fix of non existent disk for %q: %v", deviceName, innerErr)
 			}
 			// Go to next retry loop to get the deviceName again after
 			// potentially fixing it with the udev command
 			return false, nil
 		}
 
-		// If there exists a devicePath we make sure disk at /dev/sdx matches the
-		// expected disk at devicePath by matching SCSI Serial to the disk name
-		devSDX, innerErr := filepath.EvalSymlinks(devicePath)
+		// If there exists a devicePath we make sure disk at /dev/* matches the
+		// expected disk at devicePath by matching device Serial to the disk name
+		devFsPath, innerErr := filepath.EvalSymlinks(devicePath)
 		if innerErr != nil {
 			return false, fmt.Errorf("filepath.EvalSymlinks(%q) failed with %v", devicePath, innerErr)
 		}
-		// Check to make sure device path maps to the correct disk
-		if strings.Contains(devSDX, diskSDPath) {
-			scsiSerial, innerErr := getScsiSerial(devSDX)
-			if innerErr != nil {
-				return false, fmt.Errorf("couldn't get SCSI serial number for disk %s: %v", deviceName, innerErr)
-			}
-			// SUCCESS! devicePath points to a /dev/sdx that has a SCSI serial
-			// equivalent to our disk name
-			if scsiSerial == deviceName {
-				return true, nil
-			}
+
+		devFsSerial, innerErr := getDevFsSerial(devFsPath)
+		if innerErr != nil {
+			return false, fmt.Errorf("couldn't get serial number for disk %s at path %s: %v", deviceName, devFsPath, innerErr)
+		}
+		// SUCCESS! devicePath points to a /dev/* path that has a serial
+		// equivalent to our disk name
+		if len(devFsSerial) != 0 && devFsSerial == deviceName {
+			return true, nil
 		}
-		// The devicePath is not mapped to the correct disk
+
+		// A /dev/* path exists, but is either not a recognized /dev prefix type
+		// (/dev/nvme* or /dev/sd*) or devicePath is not mapped to the correct disk.
+		// Attempt a repair
 		innerErr = udevadmTriggerForDiskIfExists(deviceName)
 		if innerErr != nil {
-			return false, fmt.Errorf("failed to trigger udevadm fix: %v", innerErr)
+			return false, fmt.Errorf("failed to trigger udevadm fix of misconfigured disk for %q: %v", deviceName, innerErr)
 		}
 		// Go to next retry loop to get the deviceName again after
 		// potentially fixing it with the udev command
@@ -213,49 +269,78 @@ func (m *deviceUtils) VerifyDevicePath(devicePaths []string, deviceName string)
 	return devicePath, nil
 }
 
+// getDevFsSerial returns the serial number of the /dev/* path at devFsPath.
+// If devFsPath does not start with a known prefix, returns the empty string.
+func getDevFsSerial(devFsPath string) (string, error) {
+	switch {
+	case strings.HasPrefix(devFsPath, diskSDPath):
+		return getScsiSerial(devFsPath)
+	case strings.HasPrefix(devFsPath, diskNvmePath):
+		return getNvmeSerial(devFsPath)
+	default:
+		return "", nil
+	}
+}
+
+func findAvailableDevFsPaths() ([]string, error) {
+	diskSDPaths, err := filepath.Glob(diskSDPattern)
+	if err != nil {
+		return nil, fmt.Errorf("failed to filepath.Glob(\"%s\"): %v", diskSDPattern, err)
+	}
+	diskNvmePaths, err := filepath.Glob(diskNvmePattern)
+	if err != nil {
+		return nil, fmt.Errorf("failed to filepath.Glob(\"%s\"): %v", diskNvmePattern, err)
+	}
+	return append(diskSDPaths, diskNvmePaths...), nil
+}
+
 func udevadmTriggerForDiskIfExists(deviceName string) error {
-	devToSCSI := map[string]string{}
-	sds, err := filepath.Glob(diskSDPattern)
+	devFsPathToSerial := map[string]string{}
+	devFsPaths, err := findAvailableDevFsPaths()
 	if err != nil {
-		return fmt.Errorf("failed to filepath.Glob(\"%s\"): %v", diskSDPattern, err)
+		return err
 	}
-	for _, devSDX := range sds {
-		scsiSerial, err := getScsiSerial(devSDX)
-		if err != nil {
-			return fmt.Errorf("failed to get SCSI Serial num: %v", err)
+	for _, devFsPath := range devFsPaths {
+		devFsSerial, err := getDevFsSerial(devFsPath)
+		if err != nil || len(devFsSerial) == 0 {
+			// If we get an error, ignore. Either this isn't a block device, or it
+			// isn't something we can get a serial number from
+			klog.V(7).Infof("failed to get Serial num for disk %s at path %s: %v", deviceName, devFsPath, err)
+			continue
 		}
-		devToSCSI[devSDX] = scsiSerial
-		if scsiSerial == deviceName {
+		devFsPathToSerial[devFsPath] = devFsSerial
+		if devFsSerial == deviceName {
 			// Found the disk that we're looking for so run a trigger on it
 			// to resolve its /dev/by-id/ path
-			klog.Warningf("udevadm --trigger running to fix disk at path %s which has SCSI ID %s", devSDX, scsiSerial)
-			err := udevadmChangeToDrive(devSDX)
+			klog.Warningf("udevadm --trigger running to fix disk at path %s which has serial numberID %s", devFsPath, devFsSerial)
+			err := udevadmChangeToDrive(devFsPath)
 			if err != nil {
-				return fmt.Errorf("failed to fix disk which has SCSI ID %s: %v", scsiSerial, err)
+				return fmt.Errorf("failed to fix disk which has serial numberID %s: %v", devFsSerial, err)
 			}
 			return nil
 		}
 	}
-	klog.Warningf("udevadm --trigger requested to fix disk %s but no such disk was found in %v", deviceName, devToSCSI)
+	klog.Warningf("udevadm --trigger requested to fix disk %s but no such disk was found in %v", deviceName, devFsPathToSerial)
 	return fmt.Errorf("udevadm --trigger requested to fix disk %s but no such disk was found", deviceName)
 }
 
 // Calls "udevadm trigger --action=change" on the specified drive. drivePath
-// must be the block device path to trigger on, in the format "/dev/sd*", or a
-// symlink to it. This is workaround for Issue #7972. Once the underlying issue
-// has been resolved, this may be removed.
+// must be the block device path to trigger on, in the format "/dev/*", or a
+// symlink to it. This is workaround for Issue #7972
+// (https://github.com/kubernetes/kubernetes/issues/7972). Once the underlying
+// issue has been resolved, this may be removed.
 // udevadm takes a little bit to work its magic in the background so any callers
 // should not expect the trigger to complete instantly and may need to poll for
 // the change
-func udevadmChangeToDrive(devSDX string) error {
-	// Call "udevadm trigger --action=change --property-match=DEVNAME=/dev/sd..."
+func udevadmChangeToDrive(devFsPath string) error {
+	// Call "udevadm trigger --action=change --property-match=DEVNAME=/dev/..."
 	out, err := exec.Command(
 		"udevadm",
 		"trigger",
 		"--action=change",
-		fmt.Sprintf("--property-match=DEVNAME=%s", devSDX)).CombinedOutput()
+		fmt.Sprintf("--property-match=DEVNAME=%s", devFsPath)).CombinedOutput()
 	if err != nil {
-		return fmt.Errorf("udevadmChangeToDrive: udevadm trigger failed for drive %q with output %s: %v.", devSDX, string(out), err)
+		return fmt.Errorf("udevadmChangeToDrive: udevadm trigger failed for drive %q with output %s: %v.", devFsPath, string(out), err)
 	}
 	return nil
 }


Test patch:
diff --git a/pkg/common/parameters_test.go b/pkg/common/parameters_test.go
index 5f7eff78..d0fb8f8e 100644
--- a/pkg/common/parameters_test.go
+++ b/pkg/common/parameters_test.go
@@ -165,50 +165,37 @@ func TestExtractAndDefaultParameters(t *testing.T) {
 	}
 }
 
-// Currently the storage-locations parameter is tested in utils_test/TestSnapshotStorageLocations.
-// Here we just test other parameters.
+// Currently the only parameter is storage-locations, which is already tested
+// in utils_test/TestSnapshotStorageLocations. Here we just test the case where
+// no parameter is set in the snapshot class.
 func TestSnapshotParameters(t *testing.T) {
 	tests := []struct {
 		desc                    string
 		parameters              map[string]string
 		expectedSnapshotParames SnapshotParameters
-		expectError             bool
 	}{
 		{
 			desc:       "valid parameter",
-			parameters: map[string]string{ParameterKeyStorageLocations: "ASIA ", ParameterKeySnapshotType: "images", ParameterKeyImageFamily: "test-family"},
+			parameters: map[string]string{ParameterKeyStorageLocations: "ASIA "},
 			expectedSnapshotParames: SnapshotParameters{
 				StorageLocations: []string{"asia"},
-				SnapshotType:     DiskImageType,
-				ImageFamily:      "test-family",
 			},
-			expectError: false,
 		},
 		{
 			desc:       "nil parameter",
 			parameters: nil,
 			expectedSnapshotParames: SnapshotParameters{
 				StorageLocations: []string{},
-				SnapshotType:     DiskSnapshotType,
 			},
-			expectError: false,
-		},
-		{
-			desc:        "invalid snapshot type",
-			parameters:  map[string]string{ParameterKeySnapshotType: "invalid-type"},
-			expectError: true,
 		},
 	}
 	for _, tc := range tests {
 		t.Run(tc.desc, func(t *testing.T) {
 			p, err := ExtractAndDefaultSnapshotParameters(tc.parameters)
-			if err != nil && !tc.expectError {
-				t.Errorf("Got error %v; expect no error", err)
-			}
-			if err == nil && tc.expectError {
-				t.Error("Got no error; expect an error")
+			if err != nil {
+				t.Errorf("Got error processing snapshot parameters: %v; expect no error", err)
 			}
-			if err == nil && !reflect.DeepEqual(p, tc.expectedSnapshotParames) {
+			if !reflect.DeepEqual(p, tc.expectedSnapshotParames) {
 				t.Errorf("Got ExtractAndDefaultSnapshotParameters(%+v) = %+v; expect %+v", tc.parameters, p, tc.expectedSnapshotParames)
 			}
 		})
diff --git a/pkg/gce-pd-csi-driver/controller_test.go b/pkg/gce-pd-csi-driver/controller_test.go
index 5ac0215f..14f20361 100644
--- a/pkg/gce-pd-csi-driver/controller_test.go
+++ b/pkg/gce-pd-csi-driver/controller_test.go
@@ -64,7 +64,6 @@ var (
 	region, _      = common.GetRegionFromZones([]string{zone})
 	testRegionalID = fmt.Sprintf("projects/%s/regions/%s/disks/%s", project, region, name)
 	testSnapshotID = fmt.Sprintf("projects/%s/global/snapshots/%s", project, name)
-	testImageID    = fmt.Sprintf("projects/%s/global/images/%s", project, name)
 	testNodeID     = fmt.Sprintf("projects/%s/zones/%s/instances/%s", project, zone, node)
 )
 
@@ -100,24 +99,6 @@ func TestCreateSnapshotArguments(t *testing.T) {
 				ReadyToUse:     false,
 			},
 		},
-		{
-			name: "success disk image of zonal disk",
-			req: &csi.CreateSnapshotRequest{
-				Name:           name,
-				SourceVolumeId: testVolumeID,
-				Parameters:     map[string]string{common.ParameterKeyStorageLocations: " US-WEST2", common.ParameterKeySnapshotType: "images"},
-			},
-			seedDisks: []*gce.CloudDisk{
-				createZonalCloudDisk(name),
-			},
-			expSnapshot: &csi.Snapshot{
-				SnapshotId:     testImageID,
-				SourceVolumeId: testVolumeID,
-				CreationTime:   tp,
-				SizeBytes:      common.GbToBytes(gce.DiskSizeGb),
-				ReadyToUse:     false,
-			},
-		},
 		{
 			name: "fail no name",
 			req: &csi.CreateSnapshotRequest{
@@ -218,17 +199,11 @@ func TestDeleteSnapshot(t *testing.T) {
 		expErrCode codes.Code
 	}{
 		{
-			name: "valid snapshot delete",
+			name: "valid",
 			req: &csi.DeleteSnapshotRequest{
 				SnapshotId: testSnapshotID,
 			},
 		},
-		{
-			name: "valid image delete",
-			req: &csi.DeleteSnapshotRequest{
-				SnapshotId: testImageID,
-			},
-		},
 		{
 			name: "invalid id",
 			req: &csi.DeleteSnapshotRequest{
@@ -271,62 +246,31 @@ func TestDeleteSnapshot(t *testing.T) {
 func TestListSnapshotsArguments(t *testing.T) {
 	// Define test cases
 	testCases := []struct {
-		name          string
-		req           *csi.ListSnapshotsRequest
-		numSnapshots  int
-		numImages     int
-		expectedCount int
-		expErrCode    codes.Code
+		name         string
+		req          *csi.ListSnapshotsRequest
+		numSnapshots int
+		expErrCode   codes.Code
 	}{
 		{
 			name: "valid",
 			req: &csi.ListSnapshotsRequest{
 				SnapshotId: testSnapshotID + "0",
 			},
-			numSnapshots:  3,
-			numImages:     2,
-			expectedCount: 1,
+			numSnapshots: 1,
 		},
 		{
 			name: "invalid id",
 			req: &csi.ListSnapshotsRequest{
 				SnapshotId: testSnapshotID + "/foo",
 			},
-			expectedCount: 0,
+			numSnapshots: 0,
 		},
 		{
 			name: "no id",
 			req: &csi.ListSnapshotsRequest{
 				SnapshotId: "",
 			},
-			numSnapshots:  2,
-			numImages:     3,
-			expectedCount: 5,
-		},
-		{
-			name: "with invalid token",
-			req: &csi.ListSnapshotsRequest{
-				StartingToken: "invalid",
-			},
-			expectedCount: 0,
-			expErrCode:    codes.Aborted,
-		},
-		{
-			name: "negative entries",
-			req: &csi.ListSnapshotsRequest{
-				MaxEntries: -1,
-			},
-
-			expErrCode: codes.InvalidArgument,
-		},
-		{
-			name: "max enries",
-			req: &csi.ListSnapshotsRequest{
-				MaxEntries: 4,
-			},
-			numSnapshots:  2,
-			numImages:     3,
-			expectedCount: 4,
+			numSnapshots: 5,
 		},
 	}
 
@@ -334,7 +278,7 @@ func TestListSnapshotsArguments(t *testing.T) {
 		t.Logf("test case: %s", tc.name)
 
 		disks := []*gce.CloudDisk{}
-		for i := 0; i < tc.numSnapshots+tc.numImages; i++ {
+		for i := 0; i < tc.numSnapshots; i++ {
 			sname := fmt.Sprintf("%s%d", name, i)
 			disks = append(disks, createZonalCloudDisk(sname))
 		}
@@ -348,21 +292,6 @@ func TestListSnapshotsArguments(t *testing.T) {
 			createReq := &csi.CreateSnapshotRequest{
 				Name:           nameID,
 				SourceVolumeId: volumeID,
-				Parameters:     map[string]string{common.ParameterKeySnapshotType: common.DiskSnapshotType},
-			}
-			_, err := gceDriver.cs.CreateSnapshot(context.Background(), createReq)
-			if err != nil {
-				t.Errorf("error %v", err)
-			}
-		}
-
-		for i := 0; i < tc.numImages; i++ {
-			volumeID := fmt.Sprintf("%s%d", testVolumeID, i)
-			nameID := fmt.Sprintf("%s%d", name, i)
-			createReq := &csi.CreateSnapshotRequest{
-				Name:           nameID,
-				SourceVolumeId: volumeID,
-				Parameters:     map[string]string{common.ParameterKeySnapshotType: common.DiskImageType},
 			}
 			_, err := gceDriver.cs.CreateSnapshot(context.Background(), createReq)
 			if err != nil {
@@ -398,8 +327,8 @@ func TestListSnapshotsArguments(t *testing.T) {
 			// If one is nil or empty but not both
 			t.Fatalf("Expected snapshots number %v, got no snapshot", tc.numSnapshots)
 		}
-		if len(snapshots) != tc.expectedCount {
-			errStr := fmt.Sprintf("Expected snapshot number to equal: %v", tc.numSnapshots)
+		if len(snapshots) != tc.numSnapshots {
+			errStr := fmt.Sprintf("Expected snapshot: %#v\n to equal snapshot: %#v\n", snapshots[0].Snapshot, tc.numSnapshots)
 			t.Errorf(errStr)
 		}
 	}
@@ -898,7 +827,6 @@ func TestCreateVolumeWithVolumeSourceFromSnapshot(t *testing.T) {
 		name            string
 		project         string
 		volKey          *meta.Key
-		snapshotType    string
 		snapshotOnCloud bool
 		expErrCode      codes.Code
 	}{
@@ -906,29 +834,12 @@ func TestCreateVolumeWithVolumeSourceFromSnapshot(t *testing.T) {
 			name:            "success with data source of snapshot type",
 			project:         "test-project",
 			volKey:          meta.ZonalKey("my-disk", zone),
-			snapshotType:    common.DiskSnapshotType,
 			snapshotOnCloud: true,
 		},
 		{
 			name:            "fail with data source of snapshot type that doesn't exist",
 			project:         "test-project",
 			volKey:          meta.ZonalKey("my-disk", zone),
-			snapshotType:    common.DiskSnapshotType,
-			snapshotOnCloud: false,
-			expErrCode:      codes.NotFound,
-		},
-		{
-			name:            "success with data source of snapshot type",
-			project:         "test-project",
-			volKey:          meta.ZonalKey("my-disk", zone),
-			snapshotType:    common.DiskImageType,
-			snapshotOnCloud: true,
-		},
-		{
-			name:            "fail with data source of snapshot type that doesn't exist",
-			project:         "test-project",
-			volKey:          meta.ZonalKey("my-disk", zone),
-			snapshotType:    common.DiskImageType,
 			snapshotOnCloud: false,
 			expErrCode:      codes.NotFound,
 		},
@@ -940,28 +851,7 @@ func TestCreateVolumeWithVolumeSourceFromSnapshot(t *testing.T) {
 		// Setup new driver each time so no interference
 		gceDriver := initGCEDriver(t, nil)
 
-		snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(nil)
-		if err != nil {
-			t.Errorf("Got error extracting snapshot parameters: %v", err)
-		}
-
 		// Start Test
-		var snapshotID string
-		switch tc.snapshotType {
-		case common.DiskSnapshotType:
-			snapshotID = testSnapshotID
-			if tc.snapshotOnCloud {
-				gceDriver.cs.CloudProvider.CreateSnapshot(context.Background(), tc.project, tc.volKey, name, snapshotParams)
-			}
-		case common.DiskImageType:
-			snapshotID = testImageID
-			if tc.snapshotOnCloud {
-				gceDriver.cs.CloudProvider.CreateImage(context.Background(), tc.project, tc.volKey, name, snapshotParams)
-			}
-		default:
-			t.Errorf("Unknown snapshot type: %v", tc.snapshotType)
-		}
-
 		req := &csi.CreateVolumeRequest{
 			Name:               "test-name",
 			CapacityRange:      stdCapRange,
@@ -969,12 +859,19 @@ func TestCreateVolumeWithVolumeSourceFromSnapshot(t *testing.T) {
 			VolumeContentSource: &csi.VolumeContentSource{
 				Type: &csi.VolumeContentSource_Snapshot{
 					Snapshot: &csi.VolumeContentSource_SnapshotSource{
-						SnapshotId: snapshotID,
+						SnapshotId: testSnapshotID,
 					},
 				},
 			},
 		}
 
+		if tc.snapshotOnCloud {
+			snapshotParams, err := common.ExtractAndDefaultSnapshotParameters(req.GetParameters())
+			if err != nil {
+				t.Errorf("Got error extracting snapshot parameters: %v", err)
+			}
+			gceDriver.cs.CloudProvider.CreateSnapshot(context.Background(), tc.project, tc.volKey, name, snapshotParams)
+		}
 		resp, err := gceDriver.cs.CreateVolume(context.Background(), req)
 		//check response
 		if err != nil {
@@ -1820,7 +1717,6 @@ func TestVolumeOperationConcurrency(t *testing.T) {
 		response := make(chan error)
 		go func() {
 			_, err := cs.CreateSnapshot(context.Background(), req)
-			t.Log(err)
 			response <- err
 		}()
 		return response
diff --git a/pkg/mount-manager/device-utils_test.go b/pkg/mount-manager/device-utils_test.go
new file mode 100644
index 00000000..dd3d22b0
--- /dev/null
+++ b/pkg/mount-manager/device-utils_test.go
@@ -0,0 +1,47 @@
+package mountmanager
+
+import (
+	"testing"
+)
+
+func TestParseNvmeSerial(t *testing.T) {
+	testCases := []struct {
+		name   string
+		output string
+		serial string
+		expErr bool
+	}{
+		{
+			name:   "valid google_nvme_id response",
+			output: "line 58: warning: command substitution: ignored null byte in input\nID_SERIAL_SHORT=pvc-8ee0cf44-6acd-456e-9f3b-95ccd65065b9\nID_SERIAL=Google_PersistentDisk_pvc-8ee0cf44-6acd-456e-9f3b-95ccd65065b9",
+			serial: "pvc-8ee0cf44-6acd-456e-9f3b-95ccd65065b9",
+			expErr: false,
+		},
+		{
+			name:   "valid google_nvme_id boot disk response",
+			output: "line 58: warning: command substitution: ignored null byte in input\nID_SERIAL_SHORT=persistent-disk-0\nID_SERIAL=Google_PersistentDisk_persistent-disk-0",
+			serial: "persistent-disk-0",
+			expErr: false,
+		},
+		{
+			name:   "invalid google_nvme_id response",
+			output: "Error: requesting namespace-id from non-block device\nNVMe Status:INVALID_NS: The namespace or the format of that namespace is invalid(b) NSID:0\nxxd: sorry cannot seek.\n[2022-03-12T04:17:17+0000]: NVMe Vendor Extension disk information not present",
+			serial: "",
+			expErr: true,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Logf("Running test: %v", tc.name)
+		actualSerial, err := parseNvmeSerial(tc.output)
+		if tc.expErr && err == nil {
+			t.Fatalf("Expected error but didn't get any")
+		}
+		if !tc.expErr && err != nil {
+			t.Fatalf("Got unexpected error: %s", err)
+		}
+		if actualSerial != tc.serial {
+			t.Fatalf("Expected '%s' but got '%s'", tc.serial, actualSerial)
+		}
+	}
+}
diff --git a/test/e2e/tests/setup_e2e_test.go b/test/e2e/tests/setup_e2e_test.go
index ce15319f..06c3d454 100644
--- a/test/e2e/tests/setup_e2e_test.go
+++ b/test/e2e/tests/setup_e2e_test.go
@@ -104,6 +104,11 @@ var _ = BeforeSuite(func() {
 				klog.Fatalf("could not copy scsi_id to containerized directory: %v", err)
 			}
 
+			err = testutils.CopyFile(i, "/lib/udev/google_nvme_id", "/lib/udev_containerized/google_nvme_id")
+			if err != nil {
+				klog.Fatalf("could not copy google_nvme_id to containerized directory: %v", err)
+			}
+
 			klog.Infof("Creating new driver and client for node %s\n", i.GetName())
 			// Create new driver and client
 			testContext, err := testutils.GCEClientAndDriverSetup(i)
diff --git a/test/e2e/tests/single_zone_e2e_test.go b/test/e2e/tests/single_zone_e2e_test.go
index 0e7041fd..89c56098 100644
--- a/test/e2e/tests/single_zone_e2e_test.go
+++ b/test/e2e/tests/single_zone_e2e_test.go
@@ -87,15 +87,13 @@ var _ = Describe("GCE PD CSI Driver", func() {
 		Expect(err).To(BeNil(), "Failed to go through volume lifecycle")
 	})
 
-	It("Should automatically fix symlink errors between /dev/sdx and /dev/by-id if disk is not found", func() {
+	It("Should automatically fix the symlink between /dev/* and /dev/by-id if the disk does not match", func() {
 		testContext := getRandomTestContext()
 
 		p, z, _ := testContext.Instance.GetIdentity()
 		client := testContext.Client
 		instance := testContext.Instance
 
-		// Set-up instance to have scsi_id where we expect it
-
 		// Create Disk
 		volName, volID := createAndValidateUniqueZonalDisk(client, p, z)
 
@@ -124,6 +122,78 @@ var _ = Describe("GCE PD CSI Driver", func() {
 
 		// MESS UP THE symlink
 		devicePaths := mountmanager.NewDeviceUtils().GetDiskByIdPaths(volName, "")
+		for _, devicePath := range devicePaths {
+			err = testutils.RmAll(instance, devicePath)
+			Expect(err).To(BeNil(), "failed to remove /dev/by-id folder")
+			err = testutils.Symlink(instance, "/dev/null", devicePath)
+			Expect(err).To(BeNil(), "failed to add invalid symlink /dev/by-id folder")
+		}
+
+		// Stage Disk
+		stageDir := filepath.Join("/tmp/", volName, "stage")
+		err = client.NodeStageExt4Volume(volID, stageDir)
+		Expect(err).To(BeNil(), "failed to repair /dev/by-id symlink and stage volume")
+
+		// Validate that the link is correct
+		var validated bool
+		for _, devicePath := range devicePaths {
+			validated, err = testutils.ValidateLogicalLinkIsDisk(instance, devicePath, volName)
+			Expect(err).To(BeNil(), "failed to validate link %s is disk %s: %v", stageDir, volName, err)
+			if validated {
+				break
+			}
+		}
+		Expect(validated).To(BeTrue(), "could not find device in %v that links to volume %s", devicePaths, volName)
+
+		defer func() {
+			// Unstage Disk
+			err = client.NodeUnstageVolume(volID, stageDir)
+			if err != nil {
+				klog.Errorf("Failed to unstage volume: %v", err)
+			}
+			fp := filepath.Join("/tmp/", volName)
+			err = testutils.RmAll(instance, fp)
+			if err != nil {
+				klog.Errorf("Failed to rm file path %s: %v", fp, err)
+			}
+		}()
+	})
+
+	It("Should automatically add a symlink between /dev/* and /dev/by-id if disk is not found", func() {
+		testContext := getRandomTestContext()
+
+		p, z, _ := testContext.Instance.GetIdentity()
+		client := testContext.Client
+		instance := testContext.Instance
+
+		// Create Disk
+		volName, volID := createAndValidateUniqueZonalDisk(client, p, z)
+
+		defer func() {
+			// Delete Disk
+			err := client.DeleteVolume(volID)
+			Expect(err).To(BeNil(), "DeleteVolume failed")
+
+			// Validate Disk Deleted
+			_, err = computeService.Disks.Get(p, z, volName).Do()
+			Expect(gce.IsGCEError(err, "notFound")).To(BeTrue(), "Expected disk to not be found")
+		}()
+
+		// Attach Disk
+		err := client.ControllerPublishVolume(volID, instance.GetNodeID())
+		Expect(err).To(BeNil(), "ControllerPublishVolume failed with error for disk %v on node %v: %v", volID, instance.GetNodeID())
+
+		defer func() {
+			// Detach Disk
+			err = client.ControllerUnpublishVolume(volID, instance.GetNodeID())
+			if err != nil {
+				klog.Errorf("Failed to detach disk: %v", err)
+			}
+
+		}()
+
+		// DELETE THE symlink
+		devicePaths := mountmanager.NewDeviceUtils().GetDiskByIdPaths(volName, "")
 		for _, devicePath := range devicePaths {
 			err = testutils.RmAll(instance, devicePath)
 			Expect(err).To(BeNil(), "failed to remove /dev/by-id folder")
diff --git a/test/e2e/utils/utils.go b/test/e2e/utils/utils.go
index 6074de51..a3068ebe 100644
--- a/test/e2e/utils/utils.go
+++ b/test/e2e/utils/utils.go
@@ -251,36 +251,57 @@ func CopyFile(instance *remote.InstanceInfo, src, dest string) error {
 }
 
 // ValidateLogicalLinkIsDisk takes a symlink location at "link" and finds the
-// link location - it then finds the backing PD using scsi_id and validates that
-// it is the same as diskName
+// link location - it then finds the backing PD using either scsi_id or
+// google_nvme_id (depending on the /dev path) and validates that it is the
+// same as diskName
 func ValidateLogicalLinkIsDisk(instance *remote.InstanceInfo, link, diskName string) (bool, error) {
 	const (
-		scsiPattern = `^0Google\s+PersistentDisk\s+([\S]+)\s*$`
-		sdPattern   = "sd\\w"
+		scsiPattern       = `^0Google\s+PersistentDisk\s+([\S]+)\s*$`
+		sdPattern         = `sd\w+`
+		nvmeSerialPattern = `ID_SERIAL_SHORT=([\S]+)\s*`
+		nvmeDevPattern    = `nvme\w+`
 	)
 	// regex to parse scsi_id output and extract the serial
 	scsiRegex := regexp.MustCompile(scsiPattern)
 	sdRegex := regexp.MustCompile(sdPattern)
+	nvmeSerialRegex := regexp.MustCompile(nvmeSerialPattern)
+	nvmeDevRegex := regexp.MustCompile(nvmeDevPattern)
 
-	devSDX, err := instance.SSH("find", link, "-printf", "'%l'")
+	devFsPath, err := instance.SSH("find", link, "-printf", "'%l'")
 	if err != nil {
-		return false, fmt.Errorf("failed to find %s's symbolic link. Output: %v, errror: %v", link, devSDX, err)
+		return false, fmt.Errorf("failed to find symbolic link for %s. Output: %v, errror: %v", link, devFsPath, err)
 	}
-	if len(devSDX) == 0 {
+	if len(devFsPath) == 0 {
 		return false, nil
 	}
-	sdx := sdRegex.Find([]byte(devSDX))
-	fullDevPath := path.Join("/dev/", string(sdx))
-	scsiIDOut, err := instance.SSH("/lib/udev_containerized/scsi_id", "--page=0x83", "--whitelisted", fmt.Sprintf("--device=%v", fullDevPath))
-	if err != nil {
-		return false, fmt.Errorf("failed to find %s's SCSI ID. Output: %v, errror: %v", devSDX, scsiIDOut, err)
-	}
-	scsiID := scsiRegex.FindStringSubmatch(scsiIDOut)
-	if len(scsiID) == 0 {
-		return false, fmt.Errorf("scsi_id output cannot be parsed: %s", scsiID)
-	}
-	if scsiID[1] != diskName {
-		return false, fmt.Errorf("scsiID %s did not match expected diskName %s", scsiID, diskName)
+	if sdx := sdRegex.FindString(devFsPath); len(sdx) != 0 {
+		fullDevPath := path.Join("/dev/", string(sdx))
+		scsiIDOut, err := instance.SSH("/lib/udev_containerized/scsi_id", "--page=0x83", "--whitelisted", fmt.Sprintf("--device=%v", fullDevPath))
+		if err != nil {
+			return false, fmt.Errorf("failed to find %s's SCSI ID. Output: %v, errror: %v", devFsPath, scsiIDOut, err)
+		}
+		scsiID := scsiRegex.FindStringSubmatch(scsiIDOut)
+		if len(scsiID) == 0 {
+			return false, fmt.Errorf("scsi_id output cannot be parsed: %s. Output: %v", scsiID, scsiIDOut)
+		}
+		if scsiID[1] != diskName {
+			return false, fmt.Errorf("scsiID %s did not match expected diskName %s", scsiID, diskName)
+		}
+		return true, nil
+	} else if nvmex := nvmeDevRegex.FindString(devFsPath); len(nvmex) != 0 {
+		fullDevPath := path.Join("/dev/", string(nvmex))
+		nvmeIDOut, err := instance.SSH("/lib/udev_containerized/google_nvme_id", fmt.Sprintf("-d%v", fullDevPath))
+		if err != nil {
+			return false, fmt.Errorf("failed to find %s's NVME ID. Output: %v, errror: %v", devFsPath, nvmeIDOut, err)
+		}
+		nvmeID := nvmeSerialRegex.FindStringSubmatch(nvmeIDOut)
+		if len(nvmeID) == 0 {
+			return false, fmt.Errorf("google_nvme_id output cannot be parsed: %s. Output: %v", nvmeID, nvmeIDOut)
+		}
+		if nvmeID[1] != diskName {
+			return false, fmt.Errorf("nvmeID %s did not match expected diskName %s", nvmeID, diskName)
+		}
+		return true, nil
 	}
-	return true, nil
+	return false, fmt.Errorf("symlinked disk %s for diskName %s does not match a supported /dev/sd* or /dev/nvme* path", devFsPath, diskName)
 }
diff --git a/test/remote/instance.go b/test/remote/instance.go
index af4f0eea..1c912cb2 100644
--- a/test/remote/instance.go
+++ b/test/remote/instance.go
@@ -91,7 +91,7 @@ func (i *InstanceInfo) CreateOrGetInstance(serviceAccount string) error {
 		return fmt.Errorf("Failed to create firewall rule: %v", err)
 	}
 
-	imageURL := "projects/debian-cloud/global/images/family/debian-9"
+	imageURL := "projects/debian-cloud/global/images/family/debian-11"
 	inst := &compute.Instance{
 		Name:        i.name,
 		MachineType: machineType(i.zone, ""),
diff --git a/test/run-k8s-integration-local.sh b/test/run-k8s-integration-local.sh
index fe620cef..aa9ae87a 100755
--- a/test/run-k8s-integration-local.sh
+++ b/test/run-k8s-integration-local.sh
@@ -49,7 +49,7 @@ make -C "${PKGDIR}" test-k8s-integration
 # snapshot tests for the PD CSI driver.
 #${PKGDIR}/bin/k8s-integration-test --run-in-prow=false \
 #--staging-image=${GCE_PD_CSI_STAGING_IMAGE} --service-account-file=${GCE_PD_SA_DIR}/cloud-sa.json \
-#--deploy-overlay-name=prow-canary-sidecar --bringup-cluster=false --teardown-cluster=false --test-focus="External.*Storage.*snapshot" --local-k8s-dir=$KTOP \
+#--deploy-overlay-name=prow-gke-release-staging-head --bringup-cluster=false --teardown-cluster=false --test-focus="External.*Storage.*snapshot" --local-k8s-dir=$KTOP \
 #--storageclass-files=sc-standard.yaml,sc-balanced.yaml,sc-ssd.yaml --snapshotclass-file=pd-volumesnapshotclass.yaml --do-driver-build=true \
 #--gce-zone="us-central1-b" --num-nodes=${NUM_NODES:-3}
 
@@ -96,4 +96,4 @@ make -C "${PKGDIR}" test-k8s-integration
 # --staging-image="${GCE_PD_CSI_STAGING_IMAGE}" --service-account-file="${GCE_PD_SA_DIR}/cloud-sa.json" \
 # --deploy-overlay-name=dev --bringup-cluster=false --teardown-cluster=false --local-k8s-dir="$KTOP" \
 # --storageclass-files=sc-standard.yaml --do-driver-build=false --test-focus='External.Storage' \
-# --gce-zone="us-central1-b" --num-nodes="${NUM_NODES:-3}"
\ No newline at end of file
+# --gce-zone="us-central1-b" --num-nodes="${NUM_NODES:-3}"