Manage a fleet of clusters with hub and spoke portals¶
When you finish, two spoke clusters present the hub cluster's /data directory, and clients mount /data over NFS from whichever cluster is closest.
Before you start¶
- A hub cluster and two spoke clusters, each with a REST API on port 8000 that you can reach from this machine
- An admin account on each cluster for its connection profile
- Port 3713 open in both directions between the hub and every spoke
- The directory to share on the hub,
/datain the example - Terraform 1.11 or later
1. Copy the configuration¶
Save this as main.tf in an empty directory.
terraform {
required_version = ">= 1.11"
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
provider "qumulo" {
connection_profiles = [
{
name = "hub"
endpoint = "https://hub.example.com:8000" # <-- Replace with the hub's REST API endpoint
username = "admin"
password = "HubPassword123!" # <-- Replace with the hub's admin password
insecure_skip_verify = true
},
{
name = "us-west"
endpoint = "https://us-west.example.com:8000" # <-- Replace with this spoke's REST API endpoint
username = "admin"
password = "UsWestPassword123!" # <-- Replace with this spoke's admin password
insecure_skip_verify = true
},
{
name = "eu-west"
endpoint = "https://eu-west.example.com:8000" # <-- Replace with this spoke's REST API endpoint
username = "admin"
password = "EuWestPassword123!" # <-- Replace with this spoke's admin password
insecure_skip_verify = true
},
]
}
locals {
hub_address = "10.0.0.10" # <-- Replace with a hub address the spokes can reach
spoke_addresses = {
us-west = "10.1.0.10" # <-- Replace with an address the hub can reach
eu-west = "10.2.0.10" # <-- Replace with an address the hub can reach
}
}
resource "qumulo_portal" "fleet" {
for_each = local.spoke_addresses
hub_connection_profile = "hub"
spoke_connection_profile = each.key
type = "PORTAL_READ_WRITE"
hub_hosts = [local.hub_address]
spoke_hosts = [each.value]
}
resource "qumulo_portal_root" "fleet" {
for_each = local.spoke_addresses
portal_id = qumulo_portal.fleet[each.key].id
hub_root_path = "/data"
spoke_root_path = "/cache"
}
resource "qumulo_nfs_export" "hub" {
connection_profile = "hub"
export_path = "/data"
fs_path = "/data"
description = "Fleet data (hub)"
}
resource "qumulo_nfs_export" "spokes" {
for_each = local.spoke_addresses
connection_profile = each.key
export_path = "/data"
fs_path = "/cache"
description = "Fleet data (${each.key})"
depends_on = [qumulo_portal_root.fleet]
}
output "portal_states" {
value = {
for name, portal in qumulo_portal.fleet : name => {
hub_state = portal.hub_state
hub_status = portal.hub_status
}
}
}
Replace the nine values marked <-- Replace, and leave the rest as written. The hub address must be reachable from every spoke, and each spoke address from the hub.
Delete each insecure_skip_verify whose cluster has a certificate signed by a CA your machine trusts.
Each spoke shows the hub's /data at /cache, and every cluster exports its copy as /data, so clients see one path everywhere.
- For spokes that should only read, set
type = "PORTAL_READ_ONLY". Read-write spokes send their writes back to the hub. - To serve the same data over SMB, add a
qumulo_smb_sharebeside each export, as in SMB shares.
2. Apply¶
The plan ends with Plan: 7 to add, 0 to change, 0 to destroy. The apply ends with Apply complete! Resources: 7 added, 0 changed, 0 destroyed., followed by the portal_states output.
3. Check the portals¶
The portal_states output shows hub_state = "ACCEPTED" and hub_status = "ACTIVE" for each spoke. A DEGRADED status means the clusters connect only partly, so check port 3713 between them.
4. Add a spoke¶
Add a connection profile for the new cluster, then add an entry with the same name to spoke_addresses.
Run terraform apply. The plan ends with Plan: 3 to add, 0 to change, 0 to destroy., covering the new spoke's portal, root, and export.
5. Remove a spoke¶
Delete the spoke's entry from spoke_addresses and run terraform apply. The plan ends with Plan: 0 to add, 0 to change, 3 to destroy.
After the apply, delete the spoke's connection profile as well. Terraform needs the profile to reach the spoke while it destroys the portal, root, and export.
Next¶
Cloud Data Fabric concepts, including how portal creation works, are in Qumulo's documentation. If a portal stays PENDING, see Troubleshoot cluster configuration, and the qumulo_portal reference lists every attribute.