This section explains how to deploy Cloud Native Qumulo (CNQ) on Azure by creating the persistent storage and the cluster compute and cache resources by using Terraform. It also provides recommendations for Terraform deployments and information about post-deployment actions.
For an overview of CNQ on Azure, its prerequisites, and limits, see How Cloud Native Qumulo Works.
Prerequisites
This section explains the prerequisites to deploying CNQ on Azure.
Qumulo Core
-
Deployment Version: This deployment path requires Qumulo Core 7.9.2 (or higher).
Tip
To deploy the latest release, leave the Qumulo Core version unset. Otherwise, specify 7.9.2 (or higher). -
Metrics: To allow your Qumulo cluster to report metrics to Qumulo, your virtual network must have outbound Internet connectivity through a NAT gateway or a firewall. Your cluster shares no file data during this process.
Important
Connectivity to the following endpoints is required for a successful deployment of a Qumulo instance and quorum formation:api.missionq.qumulo.comapi.nexus.qumulo.com
Azure
-
Virtual Network: You must have an existing virtual network and subnet with the service endpoints
Microsoft.StorageandMicrosoft.KeyVaultenabled on the cluster subnet. The Terraform configuration checks for both endpoints and fails before creating anything if either is missing.Important
Size the subnet for one address per node, one for the Provisioner VM, one per floating IP, and the five addresses Azure reserves in every subnet. -
Region: Your region requires enough vCPU quota in the L-series VM family you select for your node count, plus quota in the Provisioner VM’s family.
Tip
Because a quota shortage looks identical to a capacity shortage, check Usage + quotas before you deploy.
Tools and authentication
- Install the following tools:
- Terraform 1.11 (or higher)
- Git CLI
- Azure CLI
-
Before you configure your Terraform environment, run the
az logincommand.Note
The Qumulo provider doesn’t read the subscription from the Azure CLI context, so you also set the subscription ID explicitly interraform.tfvars.Important
The principal that runs Terraform needs three roles:- Contributor on the subscription or the target resource group
- User Access Administrator on the target resource group
- Key Vault Administrator on the target resource group
Contributor alone is refused by the provider's preflight check, which needs
Microsoft.Authorization/roleAssignments/writefor the Provisioner and node identities. Key Vault Administrator supplies the Key Vault data-plane actions the provider uses to store the admin password (secrets/setSecret) and to register the storage accounts with the vault (storageaccounts/set); no management-plane role, Owner included, carries those. A custom role that combinesMicrosoft.Authorization/roleAssignments/writewith the data actionMicrosoft.KeyVault/vaults/*also works.deletion_protection(on by default) additionally needsMicrosoft.Authorization/locks/*(management locks), andfloating_ip_count(3 by default) needsMicrosoft.Network/virtualNetworks/CheckIPAddressAvailability/actionon the virtual network plusMicrosoft.Authorization/roleDefinitions/writeat subscription scope, because the provider creates a custom subnet-join role for the node identities.To keep the deploying principal at Contributor, create the identities in advance and pass
cluster_node_identity_idandprovisioner_identity_id; the provider then creates no role assignments.
Working with the qumulo-terraform-azure Repository
Qumulo is moving CNQ deployments from the downloadable Terraform bundles to the Qumulo Terraform provider, and the
qumulo-terraform-azure repository, which uses the provider, is the path this section documents. If you deployed CNQ previously with the azure-terraform-cnq-<x.y>.zip provisioning scripts, the provider changes three things:
- One Terraform workspace instead of two: persistent storage and compute deploy together, with no cross-workspace remote state to configure.
- Nothing to download from Qumulo Nexus: no Terraform bundle, and no Qumulo Core installer to stage in a storage account.
- Day-2 operations are one variable change and one apply: node add and remove, capacity increases, and VM size changes need no multi-stage sequences, and cluster replacement needs no second workspace.
The qumulo-terraform-azure repository contains Terraform configurations that let you deploy the resource group, storage accounts, managed identities, and the compute cluster, with 1 or 3–24 nodes. Together these form the CNQ cluster, which has fully elastic compute and capacity.
This Terraform uses the Qumulo Terraform provider, which greatly simplifies Terraform operations by ensuring that:
- Persistent storage and compute deploy together in a single Terraform workspace
- Node add and remove, capacity changes, and VM size changes are single-variable operations with a single
terraform applycommand
For the full list of arguments, see the qumulo_filesystem_azure resource reference in the Qumulo Terraform provider documentation.
Working with the terraform apply Command
This section explains the most common scenarios that cause the terraform init and terraform apply commands to fail.
| Symptom | Potential Resolution |
|---|---|
The terraform init command can't reach the provider registry |
Allow outbound HTTPS to qumulo-terraform-registry.s3.us-east-1.amazonaws.com. |
The plan fails with Subnet ... is missing required service endpoints |
The cluster subnet lacks the Microsoft.Storage or Microsoft.KeyVault service endpoint. Enable both and rerun. |
The apply is refused for a missing roleAssignments/write permission, or fails a few minutes in with a 403 ForbiddenByRbac on setSecret or storageaccounts/set |
The principal lacks one of the three roles in Prerequisites. Add it on the resource group and rerun; the partial deployment is already removed. |
The apply warns Unable to ensure subnet-join custom role, or the terraform destroy command ends with a 403 on roleDefinitions/delete |
User Access Administrator is scoped below the subscription. Grant it there, or clear the leftover state with the terraform state rm command. |
A create is refused with RequestDisallowedByPolicy |
An Azure Policy initiative (commonly required tags) applies. Create the resource group in advance with those tags and pass them in tags. |
| The apply waits a long time on VM capacity | This is normal behavior. For more information, see Create the Necessary Resources. |
For anything else, contact the Qumulo Care Team and include the following items with your request:
- Your deployment's unique name
- The region
- Your Terraform version
- The repository commit
- The Provisioner log from Log Analytics
Working with the Provisioner
The Provisioner is a temporary Azure VM (Standard_B2s by default, Ubuntu 22.04) that configures your Qumulo cluster. Terraform launches it during cluster creation, scaling, and node replacement, and deletes it when the operation completes, so nothing is left running between operations. Cluster node VMs run with managed identities that the provider grants Virtual Machine Contributor and Network Contributor on the resource group. The Provisioner’s admin user is adminuser; cluster node VMs use qumulo. For more information, see SSH Access in the Qumulo Terraform provider documentation.
To monitor the Provisioner’s status, watch the Terraform operations in your terminal, or read the last-run-status key in the App Configuration store named <deployment_unique_name>-deployment. For example:
az appconfig kv show -n <deployment_unique_name>-deployment --key last-run-status --auth-mode key --query value -o tsv
The sequence for a new cluster is:
Initializing create operationBOOTED. Checking connectivity.BOOTED. MQ reachable for metrics.BOOTED. Internet UP.Qumulo Nexus reachable at api.nexus.qumulo.com.Checking quorum state and boot statusForming first quorum and configuring clusterPROVISIONING COMPLETE
Viewing the Provisioner Log
The Provisioner’s full log (/var/log/cloud-init-output.log) is shipped by the Azure Monitor Agent to the Log Analytics workspace <deployment_unique_name>-logs, table QumuloProvisioner_CL, with 30-day retention. Because the Provisioner VM is deleted after each operation, this workspace is the only place the log survives afterward.
The provisioner_log_url output of the terraform apply command is a direct link to the Log Analytics workspace that holds this deployment’s Provisioner log. For example:
https://portal.azure.com/#resource/subscriptions/<subscription_id>/resourceGroups/<resource_group_unique_name>/providers/Microsoft.OperationalInsights/workspaces/<deployment_unique_name>-logs/logs
When
azure_environment is set to usgovernment, the link uses portal.azure.us rather than portal.azure.com.To view the log:
-
Run the
terraform output provisioner_log_urlcommand and open the link, or copy the link from the Terraform output after the apply. -
The Azure portal opens the Logs blade of the workspace. If the Queries hub gallery appears first, this is normal and isn’t an error. To close the gallery, click the X control in the upper right.
-
In the KQL query editor, paste the following query:
QumuloProvisioner_CL | order by TimeGenerated asc | project TimeGenerated, RawData -
Click Run or press Shift+Enter.
The results grid shows one row for each log line. To expand truncated text, click a row. To get the full transcript in one file, click Export > Export to CSV at the top of the grid.
To skip the portal entirely, run
tools/get-provisioner-log.sh (or tools/get-provisioner-log.ps1 on Windows) from the deployment directory. The script runs the same query by using the Azure CLI and writes the result to a local .txt file. This is useful if you would rather not use the portal UI, or for scripted log collection.Part 1: Deploying Your Qumulo Cluster
This section explains how to deploy the storage accounts that act as persistent storage for your Qumulo cluster, together with the cluster’s compute resources, in a single Terraform deployment. Prepare the required files, configure the deployment, and then create the resources.
Step 1: Prepare the Required Files
There is no Terraform configuration to download from Qumulo Nexus and no Qumulo Core installer to stage in a storage account. Terraform downloads the Qumulo Terraform provider from Qumulo’s registry, and the provider installs Qumulo Core on the nodes. By default the nodes and the Provisioner run Ubuntu; set
marketplace_image or custom_image_id to use RHEL or a hardened image instead.-
To clone the
qumulo-terraform-azurerepository and change into it, run the following commands.git clone https://github.com/Qumulo/qumulo-terraform-azure.git cd qumulo-terraform-azure -
To understand the deployment variables, review the
terraform.tfvarsandREADMEfiles. Theexamplesdirectory holds complete configurations for a standard deployment, a hardened production deployment (multi-AZ, restricted client networks, deletion protection, private networking, and a longer create timeout), Azure Government, RHEL images, and Private Link.
Step 2: Configure the Deployment
-
Create a storage account and container for the Terraform state, then edit the
backend.tffile and specify their names. For example:az group create -n my-tfstate-rg -l eastus2 az storage account create -n mytfstatestorage -g my-tfstate-rg -l eastus2 \ --sku Standard_LRS --allow-shared-key-access false az storage container create -n tf-state --account-name mytfstatestorage --auth-mode loginterraform { backend "azurerm" { resource_group_name = "my-tfstate-rg" storage_account_name = "mytfstatestorage" container_name = "tf-state" key = "cnq/terraform.tfstate" use_azuread_auth = true } }For more information, see the azurerm backend documentation.
Important
- We don't recommend making further changes to this part of the configuration.
- We don't recommend storing the Terraform state locally for production deployments. Enable soft delete and blob versioning on the state storage account, and use a storage account dedicated to Terraform state.
- The shipped
backend.tffile authenticates to the container with Microsoft Entra ID (use_azuread_auth = true), so the principal that runs Terraform needs Storage Blob Data Contributor on the container. - To use local state instead, comment out the whole
terraformblock.
-
Run the
terraform initcommand.Terraform prepares the environment, downloads the Qumulo provider from Qumulo’s registry, verifies its GPG-signed checksums, and displays the message
Terraform has been successfully initialized!Note
Theterraform initcommand reports the Qumulo provider as self-signed. This is expected for providers hosted outsideregistry.terraform.ioand doesn’t indicate a security issue; Terraform still performs full signature and checksum verification. For more information, see Installation and Trust in the Qumulo Terraform provider documentation. -
Edit the
terraform.tfvarsfile and specify the values for your deployment. At a minimum:-
Subscription and Environment: Specify the
azure_subscription_id, and setazure_environmenttopublicorusgovernment. -
Basic Details: Specify the
deployment_name(2–15 characters, lowercase letters, digits, and interior hyphens), theresource_group_name, and the correctlocationfor your cluster. The provider creates the resource group if it doesn’t exist.Important
Don’t share the resource group with other VMs. -
Networking: Specify the
subnet_idas the full Azure resource ID of the cluster subnet.-
Multi-AZ (Availability Zones) Deployment: Also set
availability_zones(for example["1", "2", "3"]) andstorage_replication_type = "ZRS". -
Single-Zone Deployment: Omit
availability_zonesand useLRSfor a single-zone deployment or a region without zones.
-
-
Cluster Configuration: Specify the
vm_typeand thenode_count. Valid counts are 1, or 3–24; 2 is never valid. Only L-series storage-optimized sizes are supported, for exampleStandard_L8s_v4.Note
A multi-AZ deployment needs at least 3 nodes and can’t use 4, so setnode_countto 3, or to 5 or more, when you setavailability_zones. -
Floating IP Addresses: Leave
floating_ip_countat 3, the repository default, or set it to a value from 3 to 100 for your client count. To deploy without floating IP addresses, set it to 0. -
Soft Capacity Limit: If you aren’t using the default, set the
soft_capacity_limit_tb(50–10,000). This value specifies the initial capacity limit of your Qumulo cluster (in TB).Note
It is possible to increase this limit at any time, but not to decrease it. -
Cluster / Active Directory Name: Specify a
cluster_name(2–15 characters). This is also the Active Directory machine name. -
Product Type and Storage Class: Set
cluster_product_typetoHOTorCOLD. Leavestorage_classunset for the provider default, or set it toSTANDARDorINTELLIGENT_TIERING(HOTonly). Both are immutable after creation. -
Client Access: Leave
allow_cidrsunset to allow the cluster subnet, or specify the client and management ranges that may reach the cluster. If you need SSH access to the nodes, setssh_public_key_pathto the path of a public key file. -
Qumulo Core Version:
cluster_version-
Specific Release: Specify
7.9.2(or higher) -
Latest Release: Don’t enter a value
-
-
-
Specify the administrator password in
admin_pwd_or_keyvault_secret_id, either as the resource ID of an Azure Key Vault secret (/subscriptions/.../vaults/<vault>/secrets/<secret>) or as plain text. The password must be 8–72 characters and include at least three of: a lowercase letter, an uppercase letter, a number, and a special character.Important
- The system treats the administrator password as sensitive and write-only: It never writes it to the Terraform state.
- Use the Key Vault secret reference rather than a plain-text password, so that your secret store stays the single source of truth. Terraform reads the current version of the secret on every apply and resupplies it to the provider for operations that authenticate to the cluster, such as scaling and VM size changes. If you change the password on the cluster later, update the Key Vault secret to match before the next apply.
Step 3: Create the Necessary Resources
The repository sets a 30-minute timeout for create, update, and delete through
provider_timeout_minutes. When VM capacity for your L-series size is unavailable, the provider keeps retrying in the region and zones you configured; it doesn’t move the deployment to a different zone or region on its own. To relocate, change availability_zones or location and run the apply again, which replaces the cluster. You can also raise provider_create_timeout_minutes and let the provider keep retrying.-
To authenticate to your Azure subscription, use the
az logincommand. -
Run the
terraform applycommand. -
Review the Terraform execution plan and then enter
yes.Terraform creates resources according to the execution plan and displays:
-
Your cluster’s name and UUID
-
Your deployment’s unique name
-
The endpoint IP addresses for your Qumulo cluster (floating IP addresses when configured, otherwise the primary IP addresses)
-
The primary (static) IP addresses
-
The Qumulo Core Web UI endpoint
-
The link to the Provisioner log in Log Analytics
For example:
cluster_name = "CNQ-HOT" cluster_uuid = "12345a6b-7c89-0d12-3456-78fe9012f345" deployment_unique_name = "my-deployment-a1b2c3" endpoint_ips = tolist([ "203.0.113.1", "203.0.113.2", "203.0.113.3", ]) endpoints = { "api" = "https://203.0.113.1:8000" "nfs" = "203.0.113.1:/" "smb" = "\\\\203.0.113.1\\<SMB Share Name>" "web_ui" = "https://203.0.113.1" } primary_ips = tolist([ "203.0.113.5", "203.0.113.6", "203.0.113.7", ]) provisioner_log_url = "https://portal.azure.com/#resource/subscriptions/..." resource_group_unique_name = "rg-qumulo" soft_capacity_limit_tb = 100Note
Terraform escapes backslashes when it prints string values, so the SMB endpoint appears with doubled backslashes. The path clients use is\\<IP address>\<SMB Share Name>. -
Part 2: Mounting the Qumulo File System
-
To log in to your cluster’s Web UI, use the
web_uiendpoint from the Terraform output and the usernameadminwith the password that you have configured.Important
- The administrator password is applied at cluster creation and is never written to the Terraform state.
- If you change the password by using the Qumulo Core Web UI,
qqCLI, or REST API after deployment, update the Key Vault secret (or the value interraform.tfvars) to match. Terraform resupplies the password to the provider on every apply that authenticates to the cluster, and a mismatch fails that apply part-way through.
You can use the Qumulo Core Web UI to create and manage the following:
You can also join your cluster to Active Directory and configure LDAP.
-
Mount your Qumulo file system by using NFS or SMB and your cluster’s DNS name or an IP address from the Terraform output.
Note
Clients must be inside a range listed inallow_cidrs, or inside the cluster subnet whenallow_cidrsis unset.
Part 3: Performing Post-Deployment Actions
This section describes the common actions you can perform on a CNQ cluster after deploying it: adding nodes, removing nodes, increasing the soft capacity limit, changing the VM size, upgrading Qumulo Core, and deleting a cluster. Each action is a variable change followed by a terraform apply command; there are no Terraform workspaces to manage and no multi-stage sequences.
- Leave
cluster_versionat the value you deployed with. The version is immutable after creation, and changing it fails the apply immediately, including after you upgrade Qumulo Core from the Web UI or theqqCLI. - The provider matches the software version your cluster is already running for every node add and node replacement, so no day-2 operation needs the variable updated.
Adding Nodes to an Existing CNQ on Azure Cluster
-
Edit the
terraform.tfvarsfile and setnode_countto a higher value. -
Run the
terraform applycommand. -
Review the Terraform execution plan, confirm that it shows an in-place update, and then enter
yes. -
To check that the cluster is healthy and has the needed number of nodes, log in to the Qumulo Core Web UI.
Terraform adds the nodes to your cluster and displays the additional primary (static) IP addresses.
Removing Nodes from an Existing CNQ on Azure Cluster
Removing nodes is a single Terraform operation. The separate quorum-removal (q_target_node_count) and resource-cleanup steps of the legacy bundle are now handled by the Qumulo Terraform provider.
You can’t choose which node leaves. Lowering
node_count removes the highest-numbered nodes, so taking a 4-node cluster to 3 removes node 4; there is no supported way to remove node 2 and keep node 4. To retire a specific node, replace the cluster instead.-
Edit the
terraform.tfvarsfile and setnode_countto a lower value. -
Run the
terraform applycommand. -
Review the Terraform execution plan and then enter
yes.
Increasing the Soft Capacity Limit for an Existing CNQ on Azure Cluster
- One apply can raise the soft capacity limit by almost 5,000 TB: The increase must be under 5,000 TB, so an increase of 5,000 TB or more has to be applied in steps.
- The ceiling is 10,000 TB.
- It isn't possible to decrease the soft capacity limit.
-
Edit the
terraform.tfvarsfile and setsoft_capacity_limit_tbto a higher value. -
Run the
terraform applycommand. -
Review the Terraform execution plan and then enter
yes.
Terraform adds storage accounts as necessary, updates the role assignments and network rules, and increases the soft capacity limit.
Changing the VM Size of Your CNQ on Azure Cluster
The Qumulo Terraform provider performs the replacement natively within the existing deployment. The cluster replacement procedure no longer requires a new Terraform workspace or the q_replacement_cluster and q_existing_deployment_unique_name variables.
- Changing the VM size, the availability zones, or the node image replaces cluster nodes.
- Don't resize the VMs in the Azure portal.
-
Edit the
terraform.tfvarsfile and specify the newvm_type. To convert a single-AZ cluster to multi-AZ, setavailability_zonesin the same edit. -
Run the
terraform applycommand. -
Review the Terraform execution plan carefully, and then enter
yes.
Upgrading Qumulo Core
Upgrading Qumulo Core isn’t a Terraform operation. The deployed version is immutable in the Terraform configuration after creation. Upgrade from the Qumulo Core Web UI or with the qq CLI by following Performing Upgrades. Don’t change cluster_version after the upgrade; it is immutable, and changing it fails the next apply immediately.
Deleting an Existing CNQ on Azure Cluster
- When you no longer need your cluster, you must back up all important data on the cluster safely before deleting the cluster. Deleting the cluster deletes its compute and cache resources and its persistent storage.
- Until you disable deletion protection and apply this change, the
CanNotDeletemanagement locks refuse deletion from Terraform, the Azure portal, and the Azure CLI alike.
-
After you back up your data safely, edit your
terraform.tfvarsfile and setdeletion_protectiontofalse. -
Run the
terraform applycommand, review the Terraform execution plan, and then enteryes.Terraform removes the
CanNotDeletemanagement locks. -
Run the
terraform destroycommand. -
Review the Terraform execution plan and then enter
yes.Terraform deletes all of your cluster’s resources, including the persistent storage, and displays the
Destroy complete!message with a count of destroyed resources.