GCS State Backend Example¶
This example demonstrates using Google Cloud Storage (GCS) for Terraform state management when deploying Qumulo clusters on GCP.
GCS provides native state locking via object generation numbers, so no separate locking infrastructure (e.g., DynamoDB) is required.
Point Terraform at the bucket with a backend "gcs" block:
terraform {
backend "gcs" {
bucket = "my-terraform-state-bucket" # <-- Your GCS bucket name
prefix = "qumulo/gcp/prod" # <-- Path within bucket
}
}
Prerequisites¶
- GCP project with billing enabled
- IAM permissions for
storage.buckets.createandstorage.objects.*on the state bucket - Existing VPC network and subnetwork
- Terraform >= 1.0
Creating the Backend Bucket¶
Before running terraform init -upgrade, create the GCS bucket:
gcloud storage buckets create gs://my-terraform-state-bucket \
--project=my-tfstate-project \
--location=us-central1 \
--uniform-bucket-level-access
# Enable object versioning so prior state revisions are recoverable
gcloud storage buckets update gs://my-terraform-state-bucket --versioning
Usage¶
- Edit
main.tf: - Update the
backend "gcs"block with your bucket details -
Update provider and resource values (look for
<-- Replacecomments) -
Authenticate to GCP (one of):
-
Initialize and deploy:
Backend Configuration Options¶
Options for the backend "gcs" block:
prefix: Path within the bucket. Each workspace stores its state at<prefix>/<workspace>.tfstate.encryption_key: Customer-supplied AES-256 key (base64) for client-side encryption of state.kms_encryption_key: Cloud KMS key resource name for server-side encryption of state.impersonate_service_account: Run state operations as another service account.credentials: Path to a service account JSON key (defaults to Application Default Credentials).
Best Practices¶
- Enable object versioning so previous state revisions can be recovered
- Use a dedicated project or bucket for Terraform state, separate from workload resources
- Restrict bucket access using IAM (
roles/storage.objectAdminfor operators, nothing wider) - Add a lifecycle rule to age out non-current versions after a retention window
- For sensitive environments, encrypt state with a Cloud KMS key (
kms_encryption_key)
Outputs¶
The full configuration below defines these outputs:
cluster_name: The name of your clusterendpoint_ips: IP addresses for client connectionsendpoints: Pre-formatted connection strings for web UI, API, NFS, and SMB
Full Configuration¶
# Example: Using GCS as Terraform State Backend
# This example shows how to configure remote state with Google Cloud Storage
# while deploying a Qumulo cluster on GCP.
# Edit the values below directly, then run: terraform init -upgrade && terraform apply
#
# PREREQUISITES:
# The GCS bucket must exist before running terraform init -upgrade.
# Create it with:
# gcloud storage buckets create gs://my-terraform-state-bucket \
# --project=my-tfstate-project \
# --location=us-central1 \
# --uniform-bucket-level-access
# gcloud storage buckets update gs://my-terraform-state-bucket --versioning
#
# State locking is native to GCS (no extra resources required).
terraform {
required_version = ">= 1.0"
# GCS backend configuration
backend "gcs" {
bucket = "my-terraform-state-bucket" # <-- Your GCS bucket name
prefix = "qumulo/gcp/prod" # <-- Path within bucket
# Optional: Impersonate a service account for state operations
# impersonate_service_account = "tfstate@my-tfstate-project.iam.gserviceaccount.com"
# Optional: Server-side encryption with a Cloud KMS key
# kms_encryption_key = "projects/PROJECT/locations/LOCATION/keyRings/RING/cryptoKeys/KEY"
}
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" # <-- GCP project for the cluster
region = "us-central1" # <-- GCP region
}
}
# Qumulo cluster on GCP (state stored in GCS)
resource "qumulo_filesystem_gcp" "cluster" {
provider = qumulo
# =============================================================================
# All attributes (alphabetical order)
# Uncomment any attribute to use it. Required attributes are not commented.
# =============================================================================
# Administrator password for cluster access (8-128 characters).
admin_password = "YourSecurePassword123!"
# CIDR blocks allowed to access the cluster via firewall rules (required, at least one).
# Example: ["10.0.0.0/8", "172.16.0.0/12"]
allow_cidrs = ["0.0.0.0/0"]
# # Availability zones for node placement.
# # Defaults to [region + "-b"] if omitted.
# # Example: ["us-central1-a", "us-central1-b", "us-central1-c"]
# availability_zones = ["us-central1-a", "us-central1-b", "us-central1-c"]
# # Qumulo software version (optional, defaults to latest available).
# # Immutable after creation - use Qumulo UI or CLI to upgrade.
# cluster_version = "7.8.0"
# # Number of floating IPs for client access. The provider reserves the
# # addresses and reports them in floating_ips; endpoint_ips returns them
# # instead of node IPs.
# floating_ip_count = 3
# GCP machine type for cluster nodes (e.g., n2-standard-8).
instance_type = "n2-standard-8"
# # Cloud KMS key for CMEK encryption of cluster disks.
# # Format: projects/PROJECT/locations/LOCATION/keyRings/RING/cryptoKeys/KEY
# # Immutable after creation.
# kms_key_name = "projects/your-project/locations/us-central1/keyRings/qumulo/cryptoKeys/cluster"
# qfsd cluster name, shown in the Qumulo UI (2-15 chars, case preserved).
cluster_name = "qumulogcs"
# Prefix for the GCP resources this cluster creates (2-15 lowercase chars).
deployment_name = "qumulogcs"
# # Boot disk size for cluster nodes in GB. Defaults to 50.
# node_boot_disk_size_gb = 50
# Number of nodes in the cluster.
# Valid values: 1, or 3-24 (2 is not valid; 4 nodes: single-zone only).
node_count = 3
# GCP image family for cluster nodes (Qumulo-published).
node_image_family = "qumulo-cluster-prod" # <-- Replace with your Qumulo image family
# GCP project hosting the cluster node image family.
node_image_project = "qumulo-prod" # <-- Replace with the Qumulo image project
# # GCP project ID. Defaults to the provider gcp { project_id } value.
# project_id = "your-gcp-project-id"
# GCP image family for the provisioner VM.
provisioner_image_family = "qumulo-provisioner-prod" # <-- Replace with your provisioner image family
# GCP project hosting the provisioner image family.
provisioner_image_project = "qumulo-prod" # <-- Replace with the provisioner image project
# # Machine type for the provisioner VM. Defaults to e2-standard-4.
# provisioner_machine_type = "e2-standard-4"
# # GCP region. Defaults to the provider gcp { region } value.
# region = "us-central1"
# # Pre-existing service account email for cluster nodes.
# # If omitted, a service account is created automatically.
# service_account_email = "qumulo-nodes@your-project.iam.gserviceaccount.com"
# Usable storage capacity in TB. Determines GCS bucket count.
# Can be increased to add storage, but cannot be decreased.
soft_capacity_limit_tb = 100
# Subnetwork name or self-link for cluster nodes.
subnetwork = "projects/your-project/regions/us-central1/subnetworks/qumulo-subnet" # <-- Replace
# # Labels applied to GCP resources created for this cluster.
# # Keys/values: lowercase letters, digits, hyphens, underscores. Max 64 labels.
# tags = {
# environment = "production"
# managed-by = "terraform"
# }
deletion_protection = true # recommended: guard the cluster's node instances
timeouts {
create = "90m"
delete = "90m"
}
}
output "cluster_name" {
description = "Name of the Qumulo cluster"
value = qumulo_filesystem_gcp.cluster.cluster_name
}
output "endpoint_ips" {
description = "Endpoint IP addresses for client connections"
value = qumulo_filesystem_gcp.cluster.endpoint_ips
}
output "endpoints" {
description = "Connection endpoints for various protocols"
value = {
web_ui = "https://${try(qumulo_filesystem_gcp.cluster.endpoint_ips[0], "pending")}"
api = "https://${try(qumulo_filesystem_gcp.cluster.endpoint_ips[0], "pending")}:8000"
nfs = "${try(qumulo_filesystem_gcp.cluster.endpoint_ips[0], "pending")}:/"
smb = "\\\\${try(qumulo_filesystem_gcp.cluster.endpoint_ips[0], "pending")}\\share"
}
}