Basic AWS Qumulo Cluster Example¶
This example demonstrates the minimal configuration required to deploy a Qumulo cluster on AWS in a single availability zone.
Prerequisites¶
- AWS account with permissions to create IAM roles, EC2 instances, S3 buckets, and security groups
- Existing VPC and subnet
- Terraform >= 1.0
ec2:ModifyInstanceAttributeands3:GetBucketPolicyon the deploying credentials, for every cluster: the provider lifts deletion protection from an instance or bucket immediately before terminating or deleting it, whether or notdeletion_protectionwas ever set- Using
deletion_protectionadditionally requiresec2:DescribeInstanceAttribute, so refresh can report the live protection state (s3:PutBucketPolicyis already required)
VPC Prerequisites
Your VPC must meet two requirements before deploying a cluster:
- S3 gateway VPC endpoint: Attach an S3 gateway endpoint to the route table serving the subnet. The provider does not create this (cross-account VPCs may lack permission), and deployment will fail without it.
- Outbound internet access: Cluster nodes and the provisioner instance must reach the public internet for image downloads and cluster registration. Use a NAT Gateway in a private subnet (recommended). An Internet Gateway in a public subnet also works but reduces network isolation.
Deploying into a VPC owned by another AWS account?
For RAM-shared subnets (where the VPC lives in a different AWS account than the one running Terraform), see AWS Cross-Account VPC for the additional setup and the cluster_security_group_id / provisioner_security_group_id Bring-your-own pattern.
Usage¶
-
Edit
main.tfwith your values (look for<-- Replacecomments in the Full Configuration below) -
Initialize and deploy:
Configuration¶
This example creates:
- A 3-node Qumulo cluster in a single AZ
m6idn.2xlargestorage-optimized instances- HOT storage tier
- Basic security group created by the provider (all outbound + internode + allow_cidrs ingress)
Node Count¶
Valid node counts are:
- 1 (single node for testing)
- 3-24 (cluster mode)
Note: 2-node clusters are not supported because they cannot form a majority quorum. 4-node clusters are supported only in single-AZ deployments (a single subnet).
Single-AZ vs Multi-AZ¶
This example uses a single subnet (single-AZ). The subnet_ids count decides the deployment shape:
- Single-AZ: 1 subnet (this example).
- Multi-AZ: 3 or more subnets, each in a distinct availability zone.
- 2 subnets is not supported because it cannot form a majority quorum.
- Floating IPs (
floating_ip_count) andnode_count = 4are single-AZ only.
Floating IPs¶
floating_ip_count requests ENI secondary private IPv4 addresses. floating_ip_count_ipv6 instead gives the cluster an IPv6 floating pool on the node ENIs:
resource "qumulo_filesystem_aws" "cluster" {
# ... core attributes ...
cluster_version = "7.9.2.1"
floating_ip_count = 0 # IPv4 pool disabled
floating_ip_count_ipv6 = 6 # subnet must be dualstack
allow_cidrs = ["10.0.0.0/16", "2600:1f14:abc::/56"]
}
floating_ip_count_ipv6 requires cluster_version 7.9.2.1 or later and an IPv6-enabled (dualstack) subnet. Nodes keep their IPv4 primary addresses regardless of the floating pool's address family. Core builds before 7.9.2.1 accept IPv6 floating ranges in network config, but their AWS floating-IP mover only handles IPv4, so v6 floats never fail over between nodes.
The two pools are mutually exclusive: Qumulo Core does not yet support simultaneous IPv4 and IPv6 floating IPs on AWS, so exactly one of the counts may be non-zero. A cluster's pool also cannot be migrated from one family to the other in place (that would drop every client on the current pool) — pick the family at create time. Resizing the pool the cluster already has, including clearing it to 0, is fully supported.
Outputs¶
After deployment, you'll get:
cluster_name: Name of the Qumulo clustercluster_uuid: UUID of the Qumulo clusterdeployment_unique_name: Unique deployment identifierendpoint_ips: Client-facing IPs. Floating IPs if configured, otherwise primary IPs.primary_ips: Per-node primary IPs. Use these directly when no floating IPs are configured, or for per-node access.endpoints: Connection endpoints for various protocols (web UI, API, NFS, SMB)
Supported Instance Types¶
The provider accepts a curated allow list of EC2 instance types. Set instance_type to any of the values below:
| Family | Supported sizes |
|---|---|
m6idn |
xlarge, 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge, 24xlarge, 32xlarge |
m6i |
xlarge, 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge |
m7i |
xlarge, 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge, 24xlarge, 48xlarge |
i3en |
xlarge, 2xlarge, 3xlarge, 6xlarge, 12xlarge, 24xlarge |
i4i |
xlarge, 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge, 24xlarge, 32xlarge |
i7i |
xlarge, 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge, 24xlarge |
i7ie |
xlarge, 2xlarge, 3xlarge, 6xlarge, 12xlarge, 18xlarge, 24xlarge, 48xlarge |
Any type outside this list fails plan validation.
EBS read cache (m6i and m7i): These families have no local NVMe storage, so the provider provisions the read cache as EBS volumes — one 1 TiB gp3 volume per read-cache slot (1 on the smallest sizes, up to 24 on
m7i.48xlarge) at 12,500 IOPS and 525 MB/s each, alongside the usual write-cache and DKV volumes. This requires Qumulo Core 7.4.3 or later; oldercluster_versionvalues fail at plan time. Budget for the extra EBS cost: roughly $145/month per read-cache volume at these provisioned rates.
Troubleshooting¶
- S3 gateway endpoint missing: Cluster creation fails early if the subnet's route table has no S3 gateway endpoint. Add one in the VPC console under Endpoints > Create endpoint > com.amazonaws.
.s3 (type: Gateway), and associate it with the subnet's route table. - Outbound unreachable: If the subnet has no internet route (NAT Gateway preferred, or Internet Gateway), the provisioner cannot download the installer. Check the route table and confirm a
0.0.0.0/0route to an internet-capable target. - Invalid instance type: The provider accepts a specific allow list of instance families (including
m6idn,m6i,m7i,i3en,i4i,i7i,i7ie). Families outside the allow list will fail validation. See Supported Instance Types for the full list. - Two-subnet deployment rejected: Use 1 subnet (single-AZ) or 3+ subnets (multi-AZ). 2 is never valid.
- GovCloud or ISO regions: Set
region = "us-gov-west-1"(or any other GovCloud or ISO region). The provider automatically derives the partition from the region prefix:us-gov-*maps toaws-us-gov,us-isob-*toaws-iso-b,us-iso-*toaws-iso, everything else toaws. No separatepartitionattribute is needed. - Debug logs: Run
TF_LOG=DEBUG terraform applyfor detailed output.
Full Configuration¶
# Example: Basic AWS Qumulo Cluster (single-AZ)
# Edit the values below directly, then run: terraform init -upgrade && terraform apply
terraform {
required_version = ">= 1.0"
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
provider "qumulo" {
aws {
# Standard AWS credential chain applies (env vars, shared config, SSO,
# instance profile). No credentials block is required here.
# profile = "my-profile" # optional, overrides AWS_PROFILE
}
}
resource "qumulo_filesystem_aws" "cluster" {
provider = qumulo
# =============================================================================
# All attributes (alphabetical order).
# Uncomment any attribute to use it. Required attributes are not commented.
# =============================================================================
# # Additional security group IDs to attach to cluster nodes.
# # Use for adding custom ingress rules beyond those the provider creates.
# additional_security_group_ids = ["sg-abc123"]
# Administrator password for cluster access (8-128 characters).
# Sensitive and write-only -- not stored in Terraform state.
admin_password = "YourSecurePassword123!" # <-- Replace
# CIDR blocks allowed to access the cluster (required, at least one).
# Example: ["10.0.0.0/8", "172.16.0.0/12"]
allow_cidrs = ["0.0.0.0/0"]
# # AMI ID for cluster nodes. If omitted, the default Qumulo AMI (Ubuntu 24.04) is used.
# # Supports Ubuntu and RHEL 8, 9, and 10 AMIs.
# ami_id = "ami-0123456789abcdef0"
# Cluster storage product type (immutable after creation).
# HOT: Optimized for frequently accessed data.
# COLD: Optimized for archival/infrequently accessed data.
cluster_product_type = "HOT"
# # S3 storage class backing persistent storage (immutable after creation).
# # HOT: STANDARD or INTELLIGENT_TIERING (default).
# # COLD: STANDARD_IA or GLACIER_IR (default).
# storage_class = "STANDARD"
# # Qumulo software version. Defaults to latest. Immutable after creation.
# cluster_version = "7.5.0"
# # EC2 key pair name for SSH access to cluster nodes.
# ec2_key_pair = "my-keypair"
# # Number of floating IPs. Must be 0, or between 3 and 100.
# # Requires networking_mode = "host_managed" AND single-AZ deployment.
# floating_ip_count = 3
# EC2 instance type for cluster nodes.
# Supported families include m6idn, m6i, i3en, i4i, i7i, i7ie. Families outside the allow list fail validation.
# See the "Supported Instance Types" section of this page for the full list.
instance_type = "m6idn.2xlarge"
# # KMS key ID for encrypting cluster data (immutable after creation).
# kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/abcd-ef01-..."
# qfsd cluster name, shown in the Qumulo UI (2-15 chars, case preserved).
cluster_name = "qumulo"
# Prefix for the AWS resources this cluster creates (2-15 lowercase chars).
deployment_name = "qumulo"
# # Networking mode. Default "host_managed" preserves EC2 IPs across reboots.
# # Use "qumulo_managed" only when instructed by Qumulo support.
# networking_mode = "host_managed"
# # Qumulo Nexus registration key for remote support.
# # Obtain from https://nexus.qumulo.com/user/registration-key
# nexus_registration_key = "your-nexus-key"
# Number of nodes in the cluster.
# Valid values: 1 (single node), or 3-24 (4 nodes: single-AZ only).
# Note: 2 is not a valid node count.
node_count = 3
# # IAM permissions boundary ARN applied to cluster roles.
# permissions_boundary_arn = "arn:aws:iam::123456789012:policy/boundary"
# # AMI ID for the provisioner instance. Defaults to the Qumulo provisioner AMI.
# provisioner_ami_id = "ami-0123456789abcdef0"
# # EC2 instance type for the provisioner VM (used during deploy operations).
# provisioner_instance_type = "t3.medium"
# AWS region for deployment.
region = "us-east-1" # <-- Replace with your region
# # Soft capacity limit in TB (50 to 50000).
# # Can be increased to add storage, but cannot be decreased.
# soft_capacity_limit_tb = 1000
# Subnet IDs for cluster nodes.
# Use 1 subnet for single-AZ (this example) or 3+ subnets (one per AZ) for multi-AZ.
# 2 subnets is not valid (cannot form a majority quorum).
subnet_ids = ["subnet-0123456789abcdef0"] # <-- Replace with your subnet ID
# # Tags to apply to all AWS resources created for this cluster.
# tags = {
# Environment = "Development"
# ManagedBy = "Terraform"
# }
# # VPC ID. Derived from subnet_ids if omitted.
# vpc_id = "vpc-0123456789abcdef0"
deletion_protection = true # recommended: guard the cluster's EC2 instances and S3 buckets
timeouts {
create = "90m"
delete = "30m"
}
}
output "cluster_name" {
description = "Name of the Qumulo cluster"
value = qumulo_filesystem_aws.cluster.cluster_name
}
output "cluster_uuid" {
description = "UUID of the Qumulo cluster"
value = qumulo_filesystem_aws.cluster.cluster_uuid
}
output "deployment_unique_name" {
description = "Unique deployment identifier"
value = qumulo_filesystem_aws.cluster.deployment_unique_name
}
output "endpoint_ips" {
description = "Client-facing IPs. Floating IPs if configured, otherwise primary IPs."
value = qumulo_filesystem_aws.cluster.endpoint_ips
}
output "primary_ips" {
description = "Per-node primary IPs. Use these directly when no floating IPs are configured, or for per-node access."
value = qumulo_filesystem_aws.cluster.primary_ips
}
output "endpoints" {
description = "Connection endpoints for various protocols"
value = {
web_ui = "https://${try(qumulo_filesystem_aws.cluster.endpoint_ips[0], "pending")}"
api = "https://${try(qumulo_filesystem_aws.cluster.endpoint_ips[0], "pending")}:8000"
nfs = "${try(qumulo_filesystem_aws.cluster.endpoint_ips[0], "pending")}:/"
smb = "\\\\${try(qumulo_filesystem_aws.cluster.endpoint_ips[0], "pending")}\\share"
}
}