Adopt a cluster built by the legacy CNQ modules¶
When you finish, a cluster built by aws-terraform-cnq, azure-terraform-cnq, or qumulo-terraform-gcp is managed by this provider, and later scales and node replacements join it in the right networking mode.
Before you start¶
- The legacy module's workspace, or the cloud console, to read its outputs and resource names
- Everything listed under Before you start in Import an existing cluster
- On AWS, the extra actions in AWS import permissions
1. Find the legacy unique name¶
Run this in the aws-terraform-cnq workspace.
The output is the compute module's unique name, such as "my-cluster-abc12345678". The import uses this compute name, not the persistent storage module's.
Without the workspace, read the Qumulo-Cluster tag on the cluster's EC2 instances.
The provider finds the storage module's buckets through their Qumulo-Cluster tag, and for buckets that do not carry it yet, through the list the module's provisioner wrote to the SSM parameter /qumulo/<deployment_unique_name>/bucket-names. That parameter exists for clusters built with aws-terraform-cnq v4.0 or later. For an older cluster, tag the buckets before importing, with aws resourcegroupstaggingapi tag-resources rather than s3api put-bucket-tagging, which replaces every existing tag.
aws resourcegroupstaggingapi tag-resources --resource-arn-list <bucket-arns> --tags Qumulo-Cluster=<deployment_unique_name>
terraform plan and terraform import never tag buckets. The first terraform apply does.
The unique name is the prefix of the cluster's VM names, written with the exact casing Azure shows.
Each node prints as <deployment_unique_name>-node-<id>, and the legacy module's suffix is seven characters, such as mycluster-ABC1234.
You now hold the suffixed unique name for the import ID, and the bare deployment_name in front of the suffix for HCL.
2. Find the legacy settings¶
Read q_persistent_storage_type from the legacy workspace's variables, and look up the matching pair.
q_persistent_storage_type |
cluster_product_type |
storage_class |
|---|---|---|
hot_s3_std |
HOT |
STANDARD |
hot_s3_int (the module default) |
HOT |
INTELLIGENT_TIERING |
cold_s3_ia |
COLD |
STANDARD_IA |
cold_s3_gir |
COLD |
GLACIER_IR |
Without the variable, read the class off a bucket as in step 2 of Import an existing cluster.
Find the legacy Key Vault. It lives in the persistent storage resource group when storage was deployed separately, or in the cluster resource group otherwise, and is named after the storage deployment's own unique name, such as mycluster-abcde, rather than the cluster's.
The right vault lists the cluster's storage accounts. Note its resource ID from az keyvault show --name mycluster-abcde --query id -o tsv.
There is nothing to look up. Every qumulo-terraform-gcp cluster runs in the host_managed networking mode, this provider's default.
You now know the storage class on AWS, or the Key Vault ID on Azure.
3. Write the configuration¶
Save the configuration for your cloud as main.tf, with the bare deployment_name and the values from steps 1 and 2.
resource "qumulo_filesystem_aws" "cluster" {
cluster_name = "my-cluster" # <-- Replace with the running cluster's name
deployment_name = "my-cluster" # <-- Replace with the bare name, without the suffix
region = "us-east-2" # <-- Replace with the cluster's region
subnet_ids = ["subnet-0123456789abcdef0"] # <-- Replace with the cluster's subnet IDs
node_count = 5 # <-- Replace with the current node count
instance_type = "m6idn.2xlarge" # <-- Replace with the nodes' instance type
cluster_product_type = "HOT" # <-- Replace with the value from step 2
storage_class = "INTELLIGENT_TIERING" # <-- Replace with the value from step 2
soft_capacity_limit_tb = 500 # <-- Replace with the current soft capacity limit
admin_password = "YourSecurePassword123!" # <-- Replace with the current admin password
allow_cidrs = ["10.0.0.0/8"] # <-- Replace with the security group's ingress CIDRs
networking_mode = "qumulo_managed"
floating_ip_count = 0
}
Qumulo Core manages the floating IPs of these clusters, so floating_ip_count stays 0. They still appear in the read-only floating_ips attribute.
resource "qumulo_filesystem_azure" "cluster" {
cluster_name = "mycluster" # <-- Replace with the running cluster's name
deployment_name = "mycluster" # <-- Replace with the bare name, without the suffix
resource_group_name = "mycluster-ABC1234" # <-- Replace with the cluster resource group
location = "eastus" # <-- Replace with the cluster's region
subnet_id = "/subscriptions/.../subnets/your-subnet" # <-- Replace with the subnet resource ID
node_count = 5 # <-- Replace with the current node count
vm_type = "Standard_L16s_v3" # <-- Replace with the nodes' VM size
admin_password = "YourSecurePassword123!" # <-- Replace with the current admin password
allow_cidrs = ["10.0.0.0/8"] # <-- Replace with the NSG's inbound CIDRs
networking_mode = "qumulo_managed"
key_vault_id = "/subscriptions/.../vaults/mycluster-abcde" # <-- Replace with the vault ID from step 2
persistent_storage_resource_group = "mycluster-ABC1234-persistent-storage" # <-- Replace, or delete when storage shares the cluster resource group
}
If the legacy deployment set cluster_node_identity, leave cluster_node_identity_id out. The import recovers it from the node VMs. If it set provisioner_node_identity, add provisioner_identity_id with that identity's resource ID.
If the legacy deployment set customer_managed_key_vault_key_id, leave key_vault_key_id out. The import recovers it without the key version. To declare it anyway, use the legacy value with the version removed, so the value ends in /keys/<key-name>.
resource "qumulo_filesystem_gcp" "cluster" {
cluster_name = "mycluster" # <-- Replace with the running cluster's name
deployment_name = "mycluster" # <-- Replace with the bare name, without the suffix
project_id = "my-project" # <-- Replace with the cluster's project
region = "us-west1" # <-- Replace with the cluster's region
subnetwork = "my-subnet" # <-- Replace with the cluster's subnetwork name
node_count = 3 # <-- Replace with the current node count
instance_type = "n2-highmem-8" # <-- Replace with the nodes' machine type
soft_capacity_limit_tb = 200 # <-- Replace with the current soft capacity limit
admin_password = "YourSecurePassword123!" # <-- Replace with the current admin password
allow_cidrs = ["10.0.0.0/8"] # <-- Replace with the firewall rule's source ranges
networking_mode = "host_managed"
}
Warning
networking_mode cannot change after import. A wrong mode makes every later node add or replacement fail with node_add_mixed_networking_mode_error, so use qumulo_managed on AWS and Azure and host_managed on GCP.
terraform init -upgrade followed by terraform validate prints Success! The configuration is valid.
4. Import and apply¶
terraform import qumulo_filesystem_azure.cluster "<subscription_id>/mycluster-ABC1234/mycluster-ABC1234"
Leave storage_replication_type unset. The first apply reads it from the cluster's storage accounts through key_vault_id. If the cluster has resource locks, set deletion_protection = true in main.tf. Otherwise the first plan after the first apply offers to remove them.
The import recovers key_vault_key_id only when the cluster's disks use the cluster's own disk encryption set, <deployment_unique_name>-disk-encryption-set. The provider then reuses that set and the storage identity the cluster's storage accounts already use, so scale-outs, node replacements, and new storage accounts stay on the key. The legacy module names that identity after the persistent storage deployment, not the cluster. The provider reads it from the storage accounts' encryption settings instead of deriving it from a name. Nothing is recreated. The key cannot change after adoption, so a different key_vault_key_id in main.tf is rejected at plan time.
A value that differs from the recovered one only in letter case is accepted, since Azure resource IDs are case-insensitive. The plan then shows one in-place update to key_vault_key_id that changes no Azure resource. Copy the value from terraform state show qumulo_filesystem_azure.cluster into main.tf for a fully quiet plan.
When the provider cannot yet see the cluster's storage accounts, the first read after the import cannot find or verify the storage identity. The provider finds and verifies it at the next update that creates nodes, runs the provisioner, or creates storage accounts. It stops before it creates anything if the identity is missing, if the storage accounts use different identities, or if none of them uses one.
If an earlier provider version already scaled the cluster, a refresh warns about the disks and storage accounts that are not on the key. See After the first apply for what the warning means.
The import ends with Import successful! Then fix the plan and apply exactly as in steps 4 and 5 of Import an existing cluster, until terraform plan reports No changes. Your infrastructure matches the configuration.
Re-adopt an AWS cluster from an older provider version¶
A cluster created by this provider before the Qumulo-Cluster tag existed reads as missing after an upgrade, since discovery finds neither its EC2 instances nor its S3 buckets. Remove it from state, tag it, and import it again.
terraform state rm qumulo_filesystem_aws.cluster
aws resourcegroupstaggingapi tag-resources --resource-arn-list <instance-and-bucket-arns> --tags Qumulo-Cluster=<deployment_unique_name>
terraform import qumulo_filesystem_aws.cluster "<region>/<deployment_unique_name>"
The import ends with Import successful!, and the next plan finds the cluster again.
Clean up after destroy¶
Destroying an adopted cluster through this provider behaves differently on each cloud.
- AWS deletes the module's SSM parameters under
/qumulo/<deployment_unique_name>/and schedules the/qumulo/<deployment_unique_name>-cluster-secretssecret for deletion. Remove the/qumulo/<deployment_unique_name>-audit-loglog group, CloudWatch dashboards, NLB resources, and Route53 resolver resources by hand. - Azure removes its managed storage account registrations and SAS definitions from the legacy vault and leaves the vault in place. On a cluster encrypted with a customer-managed key, it also deletes the disk encryption set and removes the set's role assignments from the key's vault. The legacy module's storage identity keeps its name from the persistent storage deployment, and destroy deletes only an identity the provider created. The legacy identity and its role assignment on the vault stay in place. Remove them by hand once no storage account uses the identity. When the provider cannot read the disk encryption set, or cannot remove a role assignment, the provider logs a warning and leaves that set or role assignment for you to remove by hand, as After the first apply describes.
- GCP finds the module's
<random>-<deployment_unique_name>-qps-<N>buckets by name and deletes them, so nothing is left to remove.
Next¶
The cluster now scales and replaces nodes through this provider like one it built. Import IDs and attributes lists every attribute the first plan checks.