Repository: kubernetes-sigs/gcp-compute-persistent-disk-csi-driver
Pull request #2072 (2025-05-01 17:34:22)

Adjust Attach Limits for Gen3 Machines + Add Labels Override
**What type of PR is this?**
/kind feature

**What this PR does / why we need it**:
For gen3 machines, we lower the attach limit to hyperdisk limit, so that workloads will not fail for attach limit exceeding errors. Users can override the value with node labels.

**Which issue(s) this PR fixes**:
Fixes #

**Special notes for your reviewer**:
Tested on GCE clusters via adding logs in branch [attachLimitLocalTest](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/compare/master...sunnylovestiramisu:gcp-compute-persistent-disk-csi-driver:attachLimitLocalTest).
1. Start the cluster for a c3 machine
```NODE_SIZE="c3-standard-4" MASTER_SIZE="c3-standard-4" NODE_DISK_TYPE="hyperdisk-balanced" kubetest --up```
2. Deploy the driver
3. Check the initial attach limit(15), and then set the node labels for new limit(20) and then restart the DaemonSet:
```
k logs -n gce-pd-csi-driver csi-gce-pd-node-fzk2r gce-pd-driver
...
I0501 18:18:14.239797      12 utils.go:82] /csi.v1.Node/NodeGetInfo called with request: 
I0501 18:18:14.242445      12 cache.go:297] Successfully retrieved node info e2e-test-songsunny-minion-group-thng
I0501 18:18:14.242504      12 node.go:582] "========== volumeLimits %s ==========" %!s(int64=15)="(MISSING)"
I0501 18:18:14.242629      12 utils.go:91] /csi.v1.Node/NodeGetInfo returned with response: node_id:"projects/songsunny-joonix/zones/us-central1-b/instances/e2e-test-songsunny-minion-group-thng"  max_volumes_per_node:15  accessible_topology:{segments:{key:"topology.gke.io/zone"  value:"us-central1-b"}}

// Label the nodes by:
kubectl label nodes e2e-test-songsunny-minion-group-0s5v node-restriction.kubernetes.io/gke-volume-attach-limit-override=20

// Confirm the labels are added:
kubectl get nodes --show-labels

// Restart the DaemonSet
kubectl rollout restart ds csi-gce-pd-node -n gce-pd-csi-driver

// Look at the logs after restart
k logs -n gce-pd-csi-driver csi-gce-pd-node-bqpwz gce-pd-driver
...
I0501 18:30:35.733576      12 cache.go:297] Successfully retrieved node info e2e-test-songsunny-minion-group-thng
I0501 18:30:35.733593      12 node.go:832] attach limit override for the node: 20
I0501 18:30:35.733608      12 node.go:756] "========== attachLimitOverride %s ==========" %!s(int64=20)="(MISSING)"
I0501 18:30:35.733616      12 node.go:582] "========== volumeLimits %s ==========" %!s(int64=20)="(MISSING)"
I0501 18:30:35.733753      12 utils.go:91] /csi.v1.Node/NodeGetInfo returned with response: node_id:"projects/songsunny-joonix/zones/us-central1-b/instances/e2e-test-songsunny-minion-group-thng"  max_volumes_per_node:20  accessible_topology:{segments:{key:"topology.gke.io/zone"  value:"us-central1-b"}}
...

```
4. Tested setting the label to 200 which is out of bound, and it will fall back to set the limit as 15:
```
...
I0501 18:57:14.562667      12 node.go:832] attach limit override for the node: 200
I0501 18:57:14.562713      12 node.go:582] "========== volumeLimits %s ==========" %!s(int64=15)="(MISSING)"
```

**Does this PR introduce a user-facing change?**:
```release-note
Adjust Attach Limits for Gen3 Machines + Add Labels Override
```


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

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/pull/2072#" title="Author self-approved">sunnylovestiramisu</a>*

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).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
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)~~ [sunnylovestiramisu]

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":[]} -->
sunnylovestiramisu: /assign @mattcary 
k8s-ci-robot: @sunnylovestiramisu: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022 | 5cf83e14618dd5e67b234da03cfd6ed4239a8741 | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022/1917996038757552128) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-compute-persistent-disk-csi-driver&pr=2072). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Asunnylovestiramisu). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @sunnylovestiramisu: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022 | 5cf83e14618dd5e67b234da03cfd6ed4239a8741 | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022/1917996038757552128) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022`
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019 | 5cf83e14618dd5e67b234da03cfd6ed4239a8741 | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019/1917996038682054656) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019`
pull-gcp-compute-persistent-disk-csi-driver-unit | e015964979468cda98a684dd49ee5ed3f0037a1d | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-unit/1918345611564814336) | true | `/test pull-gcp-compute-persistent-disk-csi-driver-unit`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-compute-persistent-disk-csi-driver&pr=2072). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Asunnylovestiramisu). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
sunnylovestiramisu: Hmm weird, test/run-unit.sh succeeded locally. Retry:

/test pull-gcp-compute-persistent-disk-csi-driver-unit
sunnylovestiramisu: /test pull-gcp-compute-persistent-disk-csi-driver-e2e
k8s-ci-robot: @sunnylovestiramisu: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022 | 5cf83e14618dd5e67b234da03cfd6ed4239a8741 | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022/1917996038757552128) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022`
pull-gcp-compute-persistent-disk-csi-driver-e2e | e015964979468cda98a684dd49ee5ed3f0037a1d | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e/1918345611422208000) | true | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e`
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019 | e015964979468cda98a684dd49ee5ed3f0037a1d | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019/1918345611753558016) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-compute-persistent-disk-csi-driver&pr=2072). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Asunnylovestiramisu). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @sunnylovestiramisu: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022 | 5cf83e14618dd5e67b234da03cfd6ed4239a8741 | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022/1917996038757552128) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2022`
pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019 | e015964979468cda98a684dd49ee5ed3f0037a1d | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019/1918345611753558016) | false | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e-windows-2019`
pull-gcp-compute-persistent-disk-csi-driver-e2e | e015964979468cda98a684dd49ee5ed3f0037a1d | [link](https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/kubernetes-sigs_gcp-compute-persistent-disk-csi-driver/2072/pull-gcp-compute-persistent-disk-csi-driver-e2e/1918349802576285696) | true | `/test pull-gcp-compute-persistent-disk-csi-driver-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-compute-persistent-disk-csi-driver&pr=2072). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Asunnylovestiramisu). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/pkg/common/constants.go b/pkg/common/constants.go
index 94c7f5a6..46a6d57b 100644
--- a/pkg/common/constants.go
+++ b/pkg/common/constants.go
@@ -60,6 +60,9 @@ const (
 	// Node label for Data Cache (only applicable to GKE nodes)
 	NodeLabelPrefix         = "cloud.google.com/%s"
 	DataCacheLssdCountLabel = "gke-data-cache-disk"
+	// Node label for attach limit override
+	NodeRestrictionLabelPrefix = "node-restriction.kubernetes.io/%s"
+	AttachLimitOverrideLabel   = "gke-volume-attach-limit-override"
 )
 
 // doc https://cloud.google.com/compute/docs/disks/hyperdisks#max-total-disks-per-vm
diff --git a/pkg/common/utils.go b/pkg/common/utils.go
index b15181b3..81ba65f0 100644
--- a/pkg/common/utils.go
+++ b/pkg/common/utils.go
@@ -24,6 +24,7 @@ import (
 	"net/http"
 	"regexp"
 	"slices"
+	"strconv"
 	"strings"
 	"time"
 
@@ -772,6 +773,25 @@ func MapNumber(num int64) int64 {
 	return 0
 }
 
+func ExtractCPUFromMachineType(input string) (int64, error) {
+	// Regex to find the number at the end of the string,
+	// it allows optional -lssd suffix.
+	re := regexp.MustCompile(`(\d+)(?:-lssd|-metal)?$`)
+
+	match := re.FindStringSubmatch(input)
+	if len(match) < 2 {
+		return 0, fmt.Errorf("no number found at the end of the input string: %s", input)
+	}
+
+	numberStr := match[1]
+	number, err := strconv.ParseInt(numberStr, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("failed to convert string '%s' to integer: %w", numberStr, err)
+	}
+
+	return number, nil
+}
+
 func DiskTypeLabelKey(diskType string) string {
 	return fmt.Sprintf("%s/%s", DiskTypeKeyPrefix, diskType)
 }
diff --git a/pkg/gce-pd-csi-driver/node.go b/pkg/gce-pd-csi-driver/node.go
index 3194c478..54950b48 100644
--- a/pkg/gce-pd-csi-driver/node.go
+++ b/pkg/gce-pd-csi-driver/node.go
@@ -31,6 +31,8 @@ import (
 
 	csi "github.com/container-storage-interface/spec/lib/go/csi"
 
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
 	"k8s.io/klog/v2"
 	"k8s.io/mount-utils"
 
@@ -101,7 +103,12 @@ const (
 	// doc https://cloud.google.com/compute/docs/memory-optimized-machines#x4_disks
 	x4HyperdiskLimit int64 = 39
 	// doc https://cloud.google.com/compute/docs/accelerator-optimized-machines#a4-disks
-	a4HyperdiskLimit     int64 = 127
+	a4HyperdiskLimit int64 = 127
+	// doc https://cloud.google.com/compute/docs/storage-optimized-machines#z3_disks
+	// doc https://cloud.google.com/compute/docs/accelerator-optimized-machines#a3-disks
+	gen3HyperdiskLimit int64 = 31
+	// doc https://cloud.google.com/compute/docs/compute-optimized-machines#h3_disks
+	h3HyperdiskLimit     int64 = 7 // Use limit for Hyperdisk Balanced
 	defaultLinuxFsType         = "ext4"
 	defaultWindowsFsType       = "ntfs"
 	fsTypeExt3                 = "ext3"
@@ -571,7 +578,7 @@ func (ns *GCENodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRe
 
 	nodeID := common.CreateNodeID(ns.MetadataService.GetProject(), ns.MetadataService.GetZone(), ns.MetadataService.GetName())
 
-	volumeLimits, err := ns.GetVolumeLimits()
+	volumeLimits, err := ns.GetVolumeLimits(ctx)
 	if err != nil {
 		klog.Errorf("GetVolumeLimits failed: %v", err.Error())
 	}
@@ -731,7 +738,7 @@ func (ns *GCENodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpa
 	}, nil
 }
 
-func (ns *GCENodeServer) GetVolumeLimits() (int64, error) {
+func (ns *GCENodeServer) GetVolumeLimits(ctx context.Context) (int64, error) {
 	// Machine-type format: n1-type-CPUS or custom-CPUS-RAM or f1/g1-type
 	machineType := ns.MetadataService.GetMachineType()
 
@@ -741,6 +748,22 @@ func (ns *GCENodeServer) GetVolumeLimits() (int64, error) {
 			return volumeLimitSmall, nil
 		}
 	}
+
+	// Get attach limit override from label
+	attachLimitOverride, err := GetAttachLimitsOverrideFromNodeLabel(ctx, ns.MetadataService.GetName())
+	if err == nil && attachLimitOverride > 0 && attachLimitOverride < 128 {
+		return attachLimitOverride, nil
+	} else {
+		// If there is an error or the range is not valid, still proceed to get defaults for the machine type
+		if err != nil {
+			klog.Warningf("using default value due to err getting node-restriction.kubernetes.io/gke-volume-attach-limit-override: %v", err)
+		}
+		if attachLimitOverride != 0 {
+			klog.Warningf("using default value due to invalid node-restriction.kubernetes.io/gke-volume-attach-limit-override: %d", attachLimitOverride)
+		}
+	}
+
+	// Process gen4 machine attach limits
 	gen4MachineTypesPrefix := []string{"c4a-", "c4-", "n4-"}
 	for _, gen4Prefix := range gen4MachineTypesPrefix {
 		if strings.HasPrefix(machineType, gen4Prefix) {
@@ -760,5 +783,59 @@ func (ns *GCENodeServer) GetVolumeLimits() (int64, error) {
 		}
 	}
 
+	// Process gen3 machine attach limits
+	gen3MachineTypesPrefix := []string{"c3-", "c3d-"}
+	for _, gen3Prefix := range gen3MachineTypesPrefix {
+		if strings.HasPrefix(machineType, gen3Prefix) {
+			cpus, err := common.ExtractCPUFromMachineType(machineType)
+			if err != nil {
+				return volumeLimitSmall, err
+			}
+			if cpus <= 8 || strings.Contains(machineType, "metal") {
+				return volumeLimitSmall, nil
+			}
+			return gen3HyperdiskLimit, nil
+
+		}
+		if strings.HasPrefix(machineType, "z3-") {
+			return gen3HyperdiskLimit, nil
+		}
+		if strings.HasPrefix(machineType, "h3-") {
+			return h3HyperdiskLimit, nil
+		}
+		if strings.HasPrefix(machineType, "a3-") {
+			if machineType == "a3-ultragpu-8g" {
+				return volumeLimitBig, nil
+			} else {
+				return gen3HyperdiskLimit, nil
+			}
+		}
+
+	}
+
 	return volumeLimitBig, nil
 }
+
+func GetAttachLimitsOverrideFromNodeLabel(ctx context.Context, nodeName string) (int64, error) {
+	cfg, err := rest.InClusterConfig()
+	if err != nil {
+		return 0, err
+	}
+	kubeClient, err := kubernetes.NewForConfig(cfg)
+	if err != nil {
+		return 0, err
+	}
+	node, err := getNodeWithRetry(ctx, kubeClient, nodeName)
+	if err != nil {
+		return 0, err
+	}
+	if val, found := node.GetLabels()[fmt.Sprintf(common.NodeRestrictionLabelPrefix, common.AttachLimitOverrideLabel)]; found {
+		attachLimitOverrideForNode, err := strconv.ParseInt(val, 10, 64)
+		if err != nil {
+			return 0, fmt.Errorf("error getting attach limit override from node label: %v", err)
+		}
+		klog.V(4).Infof("attach limit override for the node: %v", attachLimitOverrideForNode)
+		return attachLimitOverrideForNode, nil
+	}
+	return 0, nil
+}


Test patch:
diff --git a/pkg/common/utils_test.go b/pkg/common/utils_test.go
index 1d4cef0e..71bf0a77 100644
--- a/pkg/common/utils_test.go
+++ b/pkg/common/utils_test.go
@@ -2149,3 +2149,47 @@ func TestGetMinIopsThroughput(t *testing.T) {
 		})
 	}
 }
+
+func TestExtractCPUFromMachineType(t *testing.T) {
+	testcases := []struct {
+		name         string
+		input        string
+		expectOutput int64
+		expectErr    bool
+	}{
+		{
+			name:         "c3-highmem-176",
+			input:        "c3-highmem-176",
+			expectOutput: 176,
+		},
+		{
+			name:         "c3-standard-8-lssd",
+			input:        "c3-standard-8-lssd",
+			expectOutput: 8,
+		},
+		{
+			name:         "c3-standard-192-metal",
+			input:        "c3-standard-192-metal",
+			expectOutput: 192,
+		},
+		{
+			name:         "invalid input",
+			input:        "something-not-valid",
+			expectOutput: 0,
+			expectErr:    true,
+		},
+	}
+
+	for _, tc := range testcases {
+		t.Run(tc.name, func(t *testing.T) {
+			output, err := ExtractCPUFromMachineType(tc.input)
+			if output != tc.expectOutput {
+				t.Errorf("ExtractCPUFromMachineType: got %v, want %v", output, tc.expectOutput)
+			}
+
+			if gotErr := err != nil; gotErr != tc.expectErr {
+				t.Fatalf("ExtractCPUFromMachineType(%+v) = %v; expectedErr: %v", tc.input, err, tc.expectErr)
+			}
+		})
+	}
+}
diff --git a/pkg/gce-pd-csi-driver/node_test.go b/pkg/gce-pd-csi-driver/node_test.go
index 63add2b0..f4ada1d8 100644
--- a/pkg/gce-pd-csi-driver/node_test.go
+++ b/pkg/gce-pd-csi-driver/node_test.go
@@ -309,6 +309,41 @@ func TestNodeGetVolumeLimits(t *testing.T) {
 			machineType:    "a4-highgpu-8g",
 			expVolumeLimit: a4HyperdiskLimit,
 		},
+		{
+			name:           "z3-highmem-176",
+			machineType:    "z3-highmem-176",
+			expVolumeLimit: gen3HyperdiskLimit,
+		},
+		{
+			name:           "h3-standard-88",
+			machineType:    "h3-standard-88",
+			expVolumeLimit: h3HyperdiskLimit,
+		},
+		{
+			name:           "a3-ultragpu-8g",
+			machineType:    "a3-ultragpu-8g",
+			expVolumeLimit: volumeLimitBig,
+		},
+		{
+			name:           "a3-megagpu-8g",
+			machineType:    "a3-megagpu-8g",
+			expVolumeLimit: gen3HyperdiskLimit, // 31
+		},
+		{
+			name:           "c3d-highmem-8-lssd",
+			machineType:    "c3d-highmem-8-lssd",
+			expVolumeLimit: volumeLimitSmall, // 15
+		},
+		{
+			name:           "c3-standard-192-metal",
+			machineType:    "c3-standard-192-metal",
+			expVolumeLimit: volumeLimitSmall, // 15
+		},
+		{
+			name:           "c3-standard-176",
+			machineType:    "c3-standard-176",
+			expVolumeLimit: gen3HyperdiskLimit, // 31
+		},
 	}
 
 	for _, tc := range testCases {