Google Cluster Toolkit (gcluster) helps you deploy repeatable AI/ML, EDA, and HPC environments on Google Cloud from composable modules and blueprints. Google Cloud NetApp Volumes provides managed file and block storage with NFS, SMB, iSCSI, snapshots, replication, FlexCache, and tiering.
Cluster Toolkit has always offered two ways to connect NetApp Volumes:
- Provision the storage pool and volume inside the blueprint with
netapp-storage-pool and netapp-volume. - Provision storage separately and attach its NFS export with
pre-existing-network-storage.
The first approach is now the default recommendation for supported NFS deployments. Cluster Toolkit v1.102.0 added first-class Flex Unified provisioning, custom performance, auto-tiering, large-capacity scale-out pools, and volume deletion policies. Cluster Toolkit v1.104.0 completed the large-volume story by integrating private Google Cloud DNS: the toolkit can publish every NFS endpoint IP automatically and give clients one hostname to mount.
The second approach remains fully supported. It is the compatibility path for existing blueprints and the right design when storage has an independent lifecycle, is managed by another team, or uses features outside the native modules.
Recommended: provision and connect NetApp Volumes in one blueprint
The integrated path uses three storage-related modules:
netapp-storage-pool creates a Standard, Premium, Extreme, or Flex Unified storage pool. It supports regional and zonal Flex Unified layouts, custom throughput and IOPS, large-capacity scale-out pools, auto-tiering, and related pool settings.netapp-volume creates an NFSv3 or NFSv4.1 volume in that pool, configures export policy and tiering, and exports the mount information consumed by VM, image-building, and scheduler modules.dns-managed-zone creates a private Google Cloud DNS zone. When dns_config is enabled on netapp-volume, the volume module creates and maintains the A record containing every endpoint IP.
NetApp Volumes also requires Private Service Access (PSA) between the client VPC and the NetApp Volumes service network. A typical blueprint therefore combines vpc, private-service-access, the private DNS zone, the pool, and the volume.
Why this path is now the focus
- One dependency graph — Terraform understands the order: VPC and PSA, pool, volume, Cloud DNS A record, then client mounts.
- Flex Unified is native — Set
service_level: FLEX; the module supports zonal, regional, and large-capacity scale-out pools. - Multi-IP is automatic — For a toolkit-provisioned volume, you do not copy endpoint IPs into a record set.
netapp-volume reads them from the service and maintains the Google Cloud DNS A record. - Client wiring stays simple — Downstream modules continue to declare
use: [homefs]. They receive one private hostname through network_storage.server_ip, whether the volume exposes one endpoint or many. - Lifecycle controls are explicit — Set
deletion_policy: PREVENT to block deletion, or ABANDON to remove a volume from Terraform state without deleting it in Google Cloud. - Blueprint validation fails early — The modules check service-level rules, minimum capacities, Flex naming constraints, DNS-safe record names, and incompatible large-capacity settings during planning.
Example: Flex Unified large capacity with automatic Multi-IP DNS
The following abbreviated example shows the important relationships. The private DNS suffix is only an example; use any private zone visible to the client VPC.
- id: private_service_access
source: modules/network/private-service-access
use: [network]
settings:
service_name: netapp.servicenetworking.goog
prefix_length: 24
deletion_policy: ABANDON
- id: gcnv_dns_zone
source: modules/network/dns-managed-zone
settings:
zone_name: $(vars.deployment_name)-gcnv-dns
dns_name: gcnv.internal.
visibility: private
network_id: $(network.network_id)
- id: netapp_pool
source: modules/file-system/netapp-storage-pool
use: [network, private_service_access]
settings:
pool_name: $(vars.deployment_name)-netapp-pool
service_level: FLEX
region: $(vars.region)
zone: $(vars.zone)
scale_type: SCALE_TYPE_SCALEOUT
capacity_gib: 12288
total_throughput_mibps: 256
total_iops: 4096
- id: homefs
source: modules/file-system/netapp-volume
use: [netapp_pool]
settings:
volume_name: homefs
capacity_gib: 4800
large_capacity_config:
constituent_count: 48
local_mount: /home
protocols: [NFSV3]
deletion_policy: PREVENT
dns_config:
managed_zone_name: $(gcnv_dns_zone.zone_name)
With dns_config, Cluster Toolkit reads all NFS endpoints from the new volume, creates one round-robin A record in Google Cloud DNS, removes the trailing dot from the hostname passed to NFS clients, and waits for the record before exposing mount information downstream.
Any supported VM or scheduler module can then consume homefs through its normal use: relationship. Slurm is a prominent example, but the mechanism is general: VM fleets, EDA farms, AI training environments, and HPC clusters all receive the same hostname-based mount definition.
For a complete walkthrough of Multi-IP behavior, DNS caching, naming, and pre-existing volumes, see Use every NetApp Volumes endpoint with Google Cluster Toolkit.
Protecting data in an integrated deployment
The original version of this post warned that destroying the deployment would always delete a toolkit-provisioned volume. That is no longer the complete picture.
Use both resource-level and blueprint-level safeguards:
- Set
deletion_policy: PREVENT on data that Terraform must not delete. - Use
deletion_policy: ABANDON when you intentionally want to remove the volume from Terraform state while preserving it in Google Cloud. - Keep long-lived storage and short-lived compute in separate deployment groups. You can then destroy the cluster group without targeting the base storage group.
- Continue to use snapshots, backups, and replication according to the recovery requirements of the workload. A Terraform deletion policy is not a backup.
An independently managed volume still provides the strongest lifecycle separation because it is absent from the cluster deployment’s state. The native path now gives teams a deliberate choice instead of making external provisioning the only safe option.
Compatibility path: mount storage that already exists
Before v1.104.0, users who needed all endpoints of a large-capacity volume typically handled the integration themselves:
- Provision the pool and volume outside the Cluster Toolkit deployment.
- Obtain every NFS endpoint IP.
- Publish those addresses under a private Google Cloud DNS hostname.
- Pass that hostname to
pre-existing-network-storage. - Attach that module to VMs or a scheduler through
use:.
That approach still works in v1.104.0 and later. Existing blueprints do not need to migrate merely because the integrated path is now available.
Keep using pre-existing-network-storage when:
- A storage or platform team owns the volume in another Terraform root module or provisioning system.
- The dataset must outlive clusters without sharing their Terraform state.
- You are attaching a pre-existing volume or FlexCache.
- You use an ONTAP-mode pool or volume. The native pool and volume modules manage Default mode only.
- You need a product or protocol feature outside the native modules. The native
netapp-volume module supports NFSv3 and NFSv4.1, not SMB or iSCSI provisioning. - You must preserve a working blueprint on an older Cluster Toolkit release.
For multi-endpoint storage on this path, Google Cloud DNS is still the right client interface, but record management is explicit because netapp-volume does not own the storage:
- id: storage_dns_zone
source: modules/network/dns-managed-zone
settings:
zone_name: $(vars.deployment_name)-storage-dns
dns_name: storage.example.internal.
visibility: private
network_id: $(network.network_id)
recordsets:
- name: homefs
type: A
ttl: 60
rrdatas: $(vars.homefs_server_ips)
- id: homefs
source: modules/file-system/pre-existing-network-storage
settings:
server_ip: homefs.storage.example.internal
remote_mount: /homefs
local_mount: /home
fs_type: nfs
mount_options: "hard,rsize=262144,wsize=262144,vers=3,tcp,mountproto=tcp"
Cloud DNS zone names are fully qualified and end in a dot. The hostname passed to an NFS mount should not end in a dot. The eda-hybrid-cloud blueprint applies this compatibility pattern to pre-existing volumes and FlexCache.
Upgrade an existing native-module blueprint
If your blueprint already creates a large-capacity volume with netapp-volume, you do not need to replace it with pre-existing-network-storage to gain Multi-IP support:
- Upgrade to Cluster Toolkit v1.104.0 or later.
- Add a private
dns-managed-zone visible to the client VPC. - Set
dns_config.managed_zone_name on the existing netapp-volume. - If the Flex volume name contains underscores, set a DNS-safe
record_name using letters, numbers, and hyphens. - Leave downstream
use: relationships unchanged. - Run
gcluster create and review the Terraform plan. The module will add the Cloud DNS A record and change the exported mount server from one IP to the private hostname.
This is an opt-in change. Blueprints without dns_config retain their previous mount behavior, which protects backward compatibility. Existing pre-existing-network-storage blueprints also continue to work unchanged.
Which path should you choose?
Choose native provisioning with netapp-storage-pool and netapp-volume when you want:
- One repeatable blueprint for network, storage, DNS, compute, and scheduling.
- Flex Unified, custom performance, auto-tiering, or large-capacity provisioning from Cluster Toolkit.
- Automatic Multi-IP A-record management.
- Plan-time validation and explicit
PREVENT or ABANDON lifecycle policy.
Choose pre-existing-network-storage when you want:
- Storage ownership and lifecycle isolated from the cluster deployment.
- Compatibility with an existing blueprint or an older release.
- Pre-existing volumes, FlexCache, or ONTAP-mode storage.
- A generic NFS integration for storage provisioned outside the native module’s supported surface.
Both paths use the same downstream Cluster Toolkit abstraction: consumers receive network storage through use: and mount the configured export. The key difference is who owns the storage and its DNS records.
Get started
- Use Cluster Toolkit v1.104.0 or later for native Flex Unified and automatic Multi-IP DNS.
- Start with
examples/netapp-volumes.yaml for a minimal deployment. - Use
examples/netapp-volumes-slurm.yaml for a complete Flex Unified large-capacity and private-DNS example. - Use
community/examples/eda for integrated and hybrid EDA reference architectures. - Review the
netapp-storage-pool, netapp-volume, and pre-existing-network-storage documentation before deployment.
The integrated path is now the shortest route from a blueprint to a scalable NFS mount: Cluster Toolkit provisions the volume, Google Cloud DNS publishes every endpoint, and clients receive one stable hostname. The previous pre-existing-storage pattern remains available for backward compatibility and for environments where storage must stay independent.