From 6ec1d8f50404beed69e3ed3b319d4d5bf573169c Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 25 Feb 2026 16:10:29 +0100 Subject: [PATCH] Support hyperdisk-balanced options on gke-nodepool module (#3767) --- modules/gke-nodepool/README.md | 47 ++++++++++++++----- modules/gke-nodepool/main.tf | 36 ++++++++------ modules/gke-nodepool/variables.tf | 13 +++-- tests/fast/stages/s3_gke_dev/hardened.yaml | 3 +- tests/fast/stages/s3_gke_dev/simple.yaml | 3 +- tests/modules/gke_nodepool/examples/dws.yaml | 5 +- .../examples/guest-accelerator.yaml | 5 +- .../gke_nodepool/examples/hyperdisk.yaml | 30 ++++++++++++ 8 files changed, 108 insertions(+), 34 deletions(-) create mode 100644 tests/modules/gke_nodepool/examples/hyperdisk.yaml diff --git a/modules/gke-nodepool/README.md b/modules/gke-nodepool/README.md index 665b1555f..632332e2a 100644 --- a/modules/gke-nodepool/README.md +++ b/modules/gke-nodepool/README.md @@ -187,6 +187,31 @@ module "cluster-1-nodepool-dws" { } # tftest modules=1 resources=2 inventory=dws.yaml ``` +### Hyperdisk Balanced + +This example shows how to configure Hyperdisk Balanced with provisioned IOPS and throughput. + +```hcl +module "cluster-1-nodepool-hyperdisk" { + source = "./fabric/modules/gke-nodepool" + project_id = "myproject" + cluster_name = "cluster-1" + location = "europe-west4-a" + name = "nodepool-hyperdisk" + node_config = { + machine_type = "c3-standard-4" + boot_disk = { + image_type = "COS_CONTAINERD" + type = "hyperdisk-balanced" + size_gb = 100 + provisioned_iops = 3000 + provisioned_throughput = 140 + } + } +} +# tftest modules=1 resources=1 inventory=hyperdisk.yaml +``` + ## Variables @@ -194,7 +219,7 @@ module "cluster-1-nodepool-dws" { |---|---|:---:|:---:|:---:| | [cluster_name](variables.tf#L23) | Cluster name. | string | ✓ | | | [location](variables.tf#L48) | Cluster location. | string | ✓ | | -| [project_id](variables.tf#L216) | Cluster project id. | string | ✓ | | +| [project_id](variables.tf#L223) | Cluster project id. | string | ✓ | | | [cluster_id](variables.tf#L17) | Cluster id. Optional, but providing cluster_id is recommended to prevent cluster misconfiguration in some of the edge cases. | string | | null | | [gke_version](variables.tf#L28) | Kubernetes nodes version. Ignored if auto_upgrade is set in management_config. | string | | null | | [k8s_labels](variables.tf#L34) | Kubernetes labels applied to each node. | map(string) | | {} | @@ -202,16 +227,16 @@ module "cluster-1-nodepool-dws" { | [max_pods_per_node](variables.tf#L53) | Maximum number of pods per node. | number | | null | | [name](variables.tf#L59) | Optional nodepool name. | string | | null | | [network_config](variables.tf#L65) | Network configuration. | object({…}) | | null | -| [node_config](variables.tf#L89) | Node-level configuration. | object({…}) | | {} | -| [node_count](variables.tf#L162) | Number of nodes per instance group. Initial value can only be changed by recreation, current is ignored when autoscaling is used. | object({…}) | | {…} | -| [node_locations](variables.tf#L174) | Node locations. | list(string) | | null | -| [nodepool_config](variables.tf#L180) | Nodepool-level configuration. | object({…}) | | null | -| [reservation_affinity](variables.tf#L221) | Configuration of the desired reservation which instances could take capacity from. | object({…}) | | null | -| [resource_manager_tags](variables.tf#L231) | A map of resource manager tag keys and values to be attached to the nodes for managing Compute Engine firewalls using Network Firewall Policies. | map(string) | | null | -| [service_account](variables.tf#L237) | Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used. | object({…}) | | {} | -| [sole_tenant_nodegroup](variables.tf#L249) | Sole tenant node group. | string | | null | -| [tags](variables.tf#L255) | Network tags applied to nodes. | list(string) | | null | -| [taints](variables.tf#L261) | Kubernetes taints applied to all nodes. | map(object({…})) | | {} | +| [node_config](variables.tf#L89) | Node-level configuration. | object({…}) | | {} | +| [node_count](variables.tf#L169) | Number of nodes per instance group. Initial value can only be changed by recreation, current is ignored when autoscaling is used. | object({…}) | | {…} | +| [node_locations](variables.tf#L181) | Node locations. | list(string) | | null | +| [nodepool_config](variables.tf#L187) | Nodepool-level configuration. | object({…}) | | null | +| [reservation_affinity](variables.tf#L228) | Configuration of the desired reservation which instances could take capacity from. | object({…}) | | null | +| [resource_manager_tags](variables.tf#L238) | A map of resource manager tag keys and values to be attached to the nodes for managing Compute Engine firewalls using Network Firewall Policies. | map(string) | | null | +| [service_account](variables.tf#L244) | Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used. | object({…}) | | {} | +| [sole_tenant_nodegroup](variables.tf#L256) | Sole tenant node group. | string | | null | +| [tags](variables.tf#L262) | Network tags applied to nodes. | list(string) | | null | +| [taints](variables.tf#L268) | Kubernetes taints applied to all nodes. | map(object({…})) | | {} | ## Outputs diff --git a/modules/gke-nodepool/main.tf b/modules/gke-nodepool/main.tf index b2ab2021a..19c167547 100644 --- a/modules/gke-nodepool/main.tf +++ b/modules/gke-nodepool/main.tf @@ -192,20 +192,28 @@ resource "google_container_node_pool" "nodepool" { } node_config { - boot_disk_kms_key = var.node_config.boot_disk_kms_key - disk_size_gb = var.node_config.disk_size_gb - disk_type = var.node_config.disk_type - image_type = var.node_config.image_type - labels = var.k8s_labels - resource_labels = var.labels - local_ssd_count = var.node_config.local_ssd_count - machine_type = var.node_config.machine_type - metadata = local.node_metadata - min_cpu_platform = var.node_config.min_cpu_platform - node_group = var.sole_tenant_nodegroup - oauth_scopes = local.service_account_scopes - preemptible = var.node_config.preemptible - service_account = local.service_account_email + boot_disk_kms_key = try(var.node_config.boot_disk.kms_key, var.node_config.boot_disk_kms_key) + boot_disk { + size_gb = try(var.node_config.boot_disk.size_gb, var.node_config.disk_size_gb) + disk_type = try(var.node_config.boot_disk.type, var.node_config.disk_type) + provisioned_iops = try( + var.node_config.boot_disk.provisioned_iops, null + ) + provisioned_throughput = try( + var.node_config.boot_disk.provisioned_throughput, null + ) + } + image_type = var.node_config.image_type + labels = var.k8s_labels + resource_labels = var.labels + local_ssd_count = var.node_config.local_ssd_count + machine_type = var.node_config.machine_type + metadata = local.node_metadata + min_cpu_platform = var.node_config.min_cpu_platform + node_group = var.sole_tenant_nodegroup + oauth_scopes = local.service_account_scopes + preemptible = var.node_config.preemptible + service_account = local.service_account_email spot = ( var.node_config.spot == true && var.node_config.preemptible != true ) diff --git a/modules/gke-nodepool/variables.tf b/modules/gke-nodepool/variables.tf index afdd6cab2..08ca1d09a 100644 --- a/modules/gke-nodepool/variables.tf +++ b/modules/gke-nodepool/variables.tf @@ -89,9 +89,16 @@ variable "network_config" { variable "node_config" { description = "Node-level configuration." type = object({ - boot_disk_kms_key = optional(string) - disk_size_gb = optional(number) - disk_type = optional(string, "pd-balanced") + boot_disk = optional(object({ + kms_key = optional(string) + size_gb = optional(number) + type = optional(string) + provisioned_iops = optional(number) + provisioned_throughput = optional(number) + })) + boot_disk_kms_key = optional(string) # usage of this is discouraged + disk_size_gb = optional(number) # usage of this is discouraged + disk_type = optional(string, "pd-balanced") # usage of this is discouraged ephemeral_ssd_count = optional(number) gcfs = optional(bool, false) guest_accelerator = optional(object({ diff --git a/tests/fast/stages/s3_gke_dev/hardened.yaml b/tests/fast/stages/s3_gke_dev/hardened.yaml index 4ad059e05..3d0b3106e 100644 --- a/tests/fast/stages/s3_gke_dev/hardened.yaml +++ b/tests/fast/stages/s3_gke_dev/hardened.yaml @@ -245,8 +245,9 @@ values: name: mynodepool node_config: - advanced_machine_features: [] + boot_disk: + - disk_type: pd-balanced boot_disk_kms_key: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke - disk_type: pd-balanced enable_confidential_storage: null ephemeral_storage_config: [] ephemeral_storage_local_ssd_config: [] diff --git a/tests/fast/stages/s3_gke_dev/simple.yaml b/tests/fast/stages/s3_gke_dev/simple.yaml index 0c7a5e2ab..8954dddfb 100644 --- a/tests/fast/stages/s3_gke_dev/simple.yaml +++ b/tests/fast/stages/s3_gke_dev/simple.yaml @@ -203,8 +203,9 @@ values: name: mynodepool node_config: - advanced_machine_features: [] + boot_disk: + - disk_type: pd-balanced boot_disk_kms_key: null - disk_type: pd-balanced enable_confidential_storage: null ephemeral_storage_config: [] ephemeral_storage_local_ssd_config: [] diff --git a/tests/modules/gke_nodepool/examples/dws.yaml b/tests/modules/gke_nodepool/examples/dws.yaml index 07a770c3e..680c4b39b 100644 --- a/tests/modules/gke_nodepool/examples/dws.yaml +++ b/tests/modules/gke_nodepool/examples/dws.yaml @@ -19,8 +19,9 @@ values: name: nodepool-dws node_config: - boot_disk_kms_key: null - disk_size_gb: 50 - disk_type: pd-ssd + boot_disk: + - size_gb: 50 + disk_type: pd-ssd ephemeral_storage_config: - local_ssd_count: 1 ephemeral_storage_local_ssd_config: [] diff --git a/tests/modules/gke_nodepool/examples/guest-accelerator.yaml b/tests/modules/gke_nodepool/examples/guest-accelerator.yaml index ea63d37bf..78f2e062d 100644 --- a/tests/modules/gke_nodepool/examples/guest-accelerator.yaml +++ b/tests/modules/gke_nodepool/examples/guest-accelerator.yaml @@ -19,8 +19,9 @@ values: name: nodepool-gpu-1 node_config: - boot_disk_kms_key: null - disk_size_gb: 50 - disk_type: pd-ssd + boot_disk: + - size_gb: 50 + disk_type: pd-ssd ephemeral_storage_config: - local_ssd_count: 1 ephemeral_storage_local_ssd_config: [] diff --git a/tests/modules/gke_nodepool/examples/hyperdisk.yaml b/tests/modules/gke_nodepool/examples/hyperdisk.yaml new file mode 100644 index 000000000..07ed33001 --- /dev/null +++ b/tests/modules/gke_nodepool/examples/hyperdisk.yaml @@ -0,0 +1,30 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.cluster-1-nodepool-hyperdisk.google_container_node_pool.nodepool: + cluster: cluster-1 + location: europe-west4-a + name: nodepool-hyperdisk + project: myproject + node_config: + - machine_type: c3-standard-4 + boot_disk: + - disk_type: hyperdisk-balanced + size_gb: 100 + provisioned_iops: 3000 + provisioned_throughput: 140 + +counts: + google_container_node_pool: 1