qumulo_filesystem_gcp (Resource)¶
Creates and manages a Qumulo filesystem deployment on GCP.
Project Prerequisites
Your GCP project must meet these requirements before deploying a cluster:
- Enabled APIs -- Compute Engine (
compute.googleapis.com), Cloud Storage (storage.googleapis.com), and IAM (iam.googleapis.com) must be enabled. Cloud KMS (cloudkms.googleapis.com) is also required ifkms_key_nameis set. - IAM roles -- The deploying principal needs
roles/compute.admin,roles/storage.admin, and (whenservice_account_emailis omitted)roles/iam.serviceAccountAdmin. Addroles/cloudkms.cryptoKeyEncrypterDecrypteron the KMS key ifkms_key_nameis set. - Network -- An existing VPC and subnetwork in the target region. The subnet must have Private Google Access enabled so cluster nodes without external IPs can reach Cloud Storage.
- Billing -- Billing must be enabled on the project.
See the GCS state backend example for a working IAM and project setup.
Example Usage¶
terraform {
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
provider "qumulo" {
gcp {
project_id = "your-gcp-project-id"
region = "us-central1"
}
}
resource "qumulo_filesystem_gcp" "cluster" {
cluster_name = "mycluster"
deployment_name = "mycluster"
project_id = "my-gcp-project"
region = "us-central1"
subnetwork = "default"
node_count = 5
instance_type = "n2-highmem-8"
admin_password = var.admin_password
allow_cidrs = ["10.0.0.0/8"]
soft_capacity_limit_tb = 100
deletion_protection = true # recommended: guard the cluster's node instances
}
Or pin a specific image (takes precedence over the project + family fields when both are set):
resource "qumulo_filesystem_gcp" "cluster" {
cluster_name = "mycluster"
deployment_name = "mycluster"
project_id = "my-gcp-project"
region = "us-central1"
subnetwork = "default"
node_count = 5
instance_type = "n2-highmem-8"
node_image = "projects/qumulo-cloud/global/images/qumulo-7-1-2-3"
provisioner_image = "projects/qumulo-cloud/global/images/qumulo-provisioner-7-1"
admin_password = var.admin_password
allow_cidrs = ["10.0.0.0/8"]
soft_capacity_limit_tb = 100
deletion_protection = true # recommended: guard the cluster's node instances
}
Image Selection¶
Cluster nodes and the provisioner VM each pick an image one of three ways, in precedence order:
- Pinned image - set
node_image/provisioner_imageto a partial-form path (projects/PROJECT/global/images/IMAGE). A pin wins over the project + family pair for that role. - Project + family - set both
node_image_project+node_image_family(or theprovisioner_image_*equivalents) to resolve the latest image in that family at deploy time. - Default - omit all image fields for the role to use the curated Ubuntu 24.04 LTS image (
ubuntu-os-cloud/ubuntu-2404-lts-amd64).
The node and provisioner roles are configured independently; mixing modes between them is allowed.
Switching modes¶
These attributes are Computed, so deleting a line from your configuration leaves the previously applied value in place rather than clearing it. To move off a pin or a custom family, set the field to an empty string (""):
- Pinned image to project + family: set
node_image = ""and supplynode_image_project+node_image_family. - Project + family to default: set
node_image_project = ""andnode_image_family = "".
Changing a node image field (node_image, node_image_project, or node_image_family) performs an in-service node replacement: new nodes running the requested image join the cluster and the old nodes are retired, preserving the cluster UUID, endpoint IPs, and all data. Expect roughly 10+ minutes per replacement, during which the cluster stays online. Because a pinned node_image takes precedence, editing node_image_project / node_image_family while a pin is set records the new values without replacing nodes. The provisioner VM is ephemeral: changing its image fields does not replace the cluster and takes effect on the next deploy operation.
Schema¶
Required¶
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
admin_password(String, Sensitive, Write-only) Administrator password for the cluster (8-128 characters).allow_cidrs(Set of String) CIDR blocks allowed to access the cluster via firewall rules.instance_type(String) GCP machine type for cluster nodes (e.g., n2-highmem-8). Changing this triggers an in-place cluster replacement (node-by-node swap), preserving cluster identity and data.node_count(Number) Number of nodes in the cluster (1, or 3-24; 2 is not supported, and 4 requires a single zone).subnetwork(String) Subnetwork name or self-link for cluster nodes. Must reference a subnet in the cluster's own project; Shared VPC host-project subnets are not currently supported.
Optional¶
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
availability_zones(List of String) Availability zones for node placement (e.g., ["us-central1-a"]). Defaults to [region + "-b"] if not set. Use 1 zone for single-AZ or 3+ zones for multi-AZ. Changing this list (including single-AZ ↔ multi-AZ) triggers an in-place cluster replacement (node-by-node swap) that preserves cluster identity and data. Node IPs change during the swap.cluster_fqdn(String) Fully qualified domain name for Qumulo Core authoritative DNS. When set, the cluster answers DNS queries for this name with its floating IPs (round-robin). Requires at least one floating IP and cluster_version >= 7.5.0. Remove to disable authoritative DNS. Delegating or forwarding this name to the cluster's floating IPs is your responsibility.cluster_name(String) Name of the Qumulo cluster as it appears in qfsd and the Qumulo UI (2-15 characters; case preserved). When omitted, defaults toname. Not refreshed from the running cluster. Changing it forces a new cluster. Requiresdeployment_name.cluster_uuid(String) UUID of the Qumulo cluster. Set this only when importing an existing cluster whose UUID cannot be recovered automatically; new clusters receive a generated UUID and the value cannot be changed afterward.cluster_version(String) Qumulo cluster version to install. If omitted, the latest available version is used. New clusters must meet the provider's minimum supported version. Immutable after creation.deletion_protection(Boolean) Protects the cluster's node instances from deletion — viaterraform destroy, the GCP console, orgcloud. Whentrue, each cluster node carries the native GCEdeletionProtectionflag and the provider refusesterraform destroy. Deleting a protected cluster is a deliberate two-step: setdeletion_protection = false, runterraform apply, then runterraform destroy. Provider-managed operations (scaling, node replacement) succeed transparently while protection is on. GCS buckets carry no cloud-side protection on GCP (no such mechanism exists); they are covered by theterraform destroygate only. Defaults tofalse.deployment_name(String) Seed for every GCP resource name (instances, buckets, service accounts, firewall rules) (2-16 characters: letters, digits, and interior hyphens; capped at 16 by GCP's 30-char service-account limit). Derived GCP resource names are lowercased, so case is cosmetic: changing only the case of an existingdeployment_namerenames nothing and never replaces the cluster. The provider appends an immutable random suffix on first deploy to formdeployment_unique_name, the actual naming seed. When omitted, defaults to the lowercasedname. Changing it to a different name forces a new cluster. Requirescluster_name.floating_ip_count(Number) Number of floating IPs to assign to the cluster. Must be 0 (disabled) or between 3 and 100. Requires networking_mode 'host_managed'. Resolves to 0 on create, and on the first plan after import, when unset. Once a count has been applied, omitting the attribute keeps the previous value — set it to 0 explicitly to remove floating IPs.kms_key_name(String) Cloud KMS key name for CMEK encryption of cluster disks. Recovered from the cluster's boot disks during import.name(String) Back-compat shortcut that sets BOTH the qfsd cluster name and the deployment infrastructure name (2-15 characters: letters, digits, and interior hyphens; no leading or trailing hyphen). Mutually exclusive withcluster_name/deployment_name. Derived GCP resource names are lowercased.networking_mode(String) Network management mode for cluster nodes. Use 'host_managed' (new clusters default to this) for cloud-driven NIC/IP networking, or 'qumulo_managed' for cluster-driven networking. Immutable after creation. Imported clusters have no mode until you declare one, because no API reports how an existing cluster was deployed.nexus_registration_key(String, Sensitive, Deprecated, Write-only) Single-use Qumulo Nexus onboarding OTP that binds the cluster to a Nexus account on first boot. Whennexus_api_tokenis configured on the provider, this attribute is auto-minted via the Nexus API; any value supplied here is ignored. For deployments withoutnexus_api_token, supply an OTP minted from https://nexus.qumulo.com/user/registration-key. Only applied during cluster creation. This is a write-only attribute: its value is sent to the provider during apply but never persisted to Terraform state, so the single-use OTP cannot leak from the state file. Write-only attributes require Terraform CLI 1.11 or later.node_boot_disk_size_gb(Number) Boot disk size for cluster nodes in GB. Falls back to 50 at deploy time when omitted.node_hooks(Attributes) Customer shell spliced into the node boot script at the pre_run / post_run anchors. Runs as root; must be idempotent; do not embed secrets. See the Customizing Cluster Boot guide for anchor timing, the shell variables in scope, and safety rules. (see below for nested schema)node_image(String) Pinned image for cluster nodes (partial form, e.g. "projects/PROJECT/global/images/IMAGE"). Takes precedence over node_image_project / node_image_family when both are set. Set to an empty string to drop the pin and fall back to the project + family pair (or the default image).node_image_family(String) Image family for cluster nodes. Set to an empty string or omit to fall back to ubuntu-2404-lts-amd64 at deploy time.node_image_project(String) GCP project containing the cluster node image family. Set to an empty string or omit to fall back to ubuntu-os-cloud at deploy time.project_id(String) GCP project ID. Falls back to project_id in the provider gcp {} block if not set.provisioner_hooks(Attributes) Customer shell spliced into the provisioner boot script at the pre_run / post_run anchors. Runs as root; must be idempotent; do not embed secrets. See the Customizing Cluster Boot guide for anchor timing, the shell variables in scope, and safety rules. (see below for nested schema)provisioner_image(String) Pinned image for the provisioner VM (partial form, e.g. "projects/PROJECT/global/images/IMAGE"). Takes precedence over provisioner_image_project / provisioner_image_family when both are set. Set to an empty string to drop the pin and fall back to the project + family pair (or the default image).provisioner_image_family(String) Image family for the provisioner VM. Set to an empty string or omit to fall back to ubuntu-2404-lts-amd64 at deploy time.provisioner_image_project(String) GCP project containing the provisioner VM image family. Set to an empty string or omit to fall back to ubuntu-os-cloud at deploy time.provisioner_machine_type(String) Machine type for the provisioner VM. Falls back to e2-standard-4 at deploy time when omitted.region(String) GCP region for deployment (e.g., us-central1). Falls back to region in the provider gcp {} block if not set.service_account_email(String) Pre-existing service account email for cluster nodes. A service account is created if omitted.soft_capacity_limit_tb(Number) Usable storage capacity in TB (50TB to 10000TB). Determines the number of GCS buckets created. Defaults to 500TB. Can be increased but cannot be decreased. Increases are limited to less than 5000TB per apply; larger changes must be applied in steps.tags(Map of String) Labels to apply to GCP resources created for this cluster. Keys and values may only contain lowercase letters, numbers, hyphens, and underscores. Maximum 64 labels; keys must not start with the reserved "goog-" prefix.timeouts(Block, Optional) (see below for nested schema)
Read-Only¶
cluster_reference(Attributes) Aggregated cluster identity for downstream resources. Equivalent to{ cluster_api_endpoint, cluster_name, cluster_uuid, endpoint_ips, project_id, region, subnet_cidr, subnet_id, uses_floating_ips }— pass directly toqumulo_threat_detection_gcp.cluster_referenceso the customer can wire one reference instead of nine. (see below for nested schema)deployment_unique_name(String) The immutable unique deployment name (<deployment_name>-<random suffix>) used to name and tag every cloud resource, and the Terraform import ID. Stable for the deployment's life.endpoint_ips(List of String) IP addresses for cluster access: the cluster's floating IPs when it has any, otherwise the node IPs.floating_ips(Set of String) Floating IP addresses assigned to the cluster. Empty when floating_ip_count is 0. Refreshed from the nodes' alias IP ranges on every read, so out-of-band changes surface as drift.id(String) Unique identifier for the resource (deployment name).internal_state(String) Internal operational state (JSON). Managed by the provider; do not edit.knowledge_base_url(String) URL to the Qumulo Terraform provider documentation.nexus_organization(String) Operator-visible label for the Nexus organization this cluster was onboarded to at apply time. Rendered asName (organization ID N)when the provider could resolve the org name, otherwiseorganization ID N. Null whennexus_api_tokenis not configured.
Immutable historical record: this value is stamped at create time and preserved across refreshes via UseStateForUnknown. It does NOT change when an operator later edits nexus_account_id on the provider block. The value is resolved at Configure time and written once — the cluster's onboarded organization is fixed at apply time.
- primary_ips (List of String) Primary IP addresses for each cluster node. Can change during scaling operations or instance_type replacement.
- subnet_cidr (String) Primary IPv4 CIDR block of the cluster's subnetwork, resolved during cluster creation. Exposed via cluster_reference so the Threat Detection resource can derive its firewall rules without operator input.
Nested Schema for node_hooks¶
Optional:
post_run(String) Shell run on each node after qumulo-core is installed. Runs as root; must be idempotent; do not embed secrets.pre_run(String) Shell run on each node after distro detection, before the provider's first network operation (connectivity check, package-cache refresh, package download). Runs as root; must be idempotent; do not embed secrets.
Nested Schema for provisioner_hooks¶
Optional:
post_run(String) Shell run on the provisioner after the cluster is formed and configured, before the provisioner signals success. Runs as root; must be idempotent; do not embed secrets.pre_run(String) Shell run on the provisioner after deployment variables are set and error-handling is armed, before any provider network operation or bucket-access validation. Runs as root; must be idempotent; do not embed secrets (logged under set -x, stored in Terraform state). See the Customizing Cluster Boot guide for the exact shell variables in scope.
Nested Schema for timeouts¶
Optional:
create(String) A string that can be parsed as a duration consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).delete(String) A string that can be parsed as a duration consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs.update(String) A string that can be parsed as a duration consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
Nested Schema for cluster_reference¶
Read-Only:
cluster_api_endpoint(String) The single cluster API target downstream resources dial (equals endpoint_ips[0]). Threat Detection keys VM replacement on this stable field rather than the whole endpoint_ips list, so cluster scaling does not needlessly replace the appliance. With floating IPs configured this is a float, which stays constant across scaling and node replacement.cluster_name(String) Resolved qfsd cluster name (cluster_name, ornamewhen the pair is not used; case preserved). Used by downstream resources for operator-recognizable resource naming.cluster_uuid(String) UUID of the Qumulo cluster. Before Nexus pre-registration is enabled, this carries the deployment name rather than the cluster's actual UUID.endpoint_ips(List of String) Endpoint IP addresses for client access.project_id(String) GCP project ID the cluster is deployed in. Mirrors the resource'sproject_idattribute. Used by downstream resources so the operator does not have to retype the project.region(String) GCP region the cluster is deployed in. Mirrors the resource'sregionattribute. Used by downstream resources so the operator does not have to retype the region.subnet_cidr(String) Primary IPv4 CIDR block of the cluster's subnetwork. Resolved once at Create via DescribeSubnetwork. Used by downstream resources (e.g. Threat Detection) as the inbound allow source on their firewall so cluster nodes (and only cluster nodes) can reach the appliance. Empty if DescribeSubnetwork was unavailable.subnet_id(String) Subnetwork name or self-link hosting the cluster.uses_floating_ips(Boolean) True when the cluster has floating IPs configured. Downstream resources use this to pick an HA strategy that matches the cluster's actual network: with floats, endpoint_ips[0] is a float and qfsd handles failover at the network layer; without, endpoint_ips[0] is a node primary and clients need their own discovery to reach the other primaries.