Cluster Replication Example¶
This example demonstrates how to set up data replication between Qumulo clusters and to S3-compatible object storage. Replication provides disaster recovery, data distribution, and archival capabilities.
Features¶
Four replication patterns are demonstrated:
- Source Relationship - Initiates replication FROM this cluster to a target
- Target Relationship - Authorizes replication TO this cluster from a source
- Blackout Windows - Schedules replication around business hours
- Object Storage - Replicates to/from S3-compatible storage (backup/archive)
Architecture¶
Cluster-to-Cluster Replication¶
┌─────────────────────────────────────────────────────────────────────────────┐
│ REPLICATION FLOW │
└─────────────────────────────────────────────────────────────────────────────┘
SOURCE CLUSTER TARGET CLUSTER
┌───────────────────────┐ ┌───────────────────────┐
│ │ │ │
│ /data ───────────────┼─── Port 3712 ──────────►│ /replica │
│ (source_root_path) │ │ (target_root_path) │
│ │ 1. Create source │ │
│ qumulo_ │ relationship │ qumulo_ │
│ replication_source_ │ │ replication_target_ │
│ relationship │ 2. Authorize on │ relationship │
│ │ target │ │
│ │ │ │
│ Terraform applies │ 3. Data flows │ Terraform applies │
│ via REST API :8000 │ continuously │ via REST API :8000 │
│ │ │ │
└───────────────────────┘ └───────────────────────┘
▲ ▲
│ │
│ │
┌─────┴─────┐ ┌─────┴─────┐
│ Terraform │ │ Terraform │
│ Host │ │ (same) │
└───────────┘ └───────────┘
Object Storage Replication¶
┌─────────────────────────────────────────────────────────────────────────────┐
│ OBJECT STORAGE REPLICATION │
└─────────────────────────────────────────────────────────────────────────────┘
QUMULO CLUSTER S3-COMPATIBLE STORAGE
┌───────────────────────┐ ┌───────────────────────┐
│ │ │ │
│ /data/backup ────────┼─── COPY_TO_OBJECT ─►│ bucket/qumulo-backup │
│ │ (archive) │ │
│ │ │ │
│ /data/restored ◄─────┼── COPY_FROM_OBJECT─┼──bucket/qumulo-archive│
│ │ (restore) │ │
│ │ │ │
│ qumulo_ │ HTTPS :443 │ AWS S3, MinIO, │
│ replication_object_ │ │ Wasabi, etc. │
│ relationship │ │ │
│ │ │ │
└───────────────────────┘ └───────────────────────┘
Prerequisites¶
- Qumulo clusters with REST API access (port 8000)
- Network connectivity between clusters on port 3712 (bidirectional)
- Admin credentials for all clusters
- S3 credentials for object storage replication (optional)
Network Requirements¶
| Port | Direction | Purpose |
|---|---|---|
| 3712 | Source -> Target | Replication data transfer |
| 8000 | Terraform -> Clusters | REST API management |
| 443 | Cluster -> S3 | Object storage replication |
Usage¶
- Create a
terraform.tfvarsfile:
source_cluster = {
endpoint = "https://source-cluster.example.com:8000"
username = "admin"
password = "source-admin-password"
}
target_cluster = {
endpoint = "https://target-cluster.example.com:8000"
username = "admin"
password = "target-admin-password"
address = "target-cluster.example.com" # Reachable from source
}
s3_config = {
endpoint = "s3.amazonaws.com"
bucket = "my-qumulo-backup"
region = "us-west-2"
access_key_id = "AKIAIOSFODNN7EXAMPLE"
secret_access_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
- Initialize and apply:
Variables¶
| Name | Description | Type | Default |
|---|---|---|---|
source_cluster |
Source cluster connection details | object |
- |
target_cluster |
Target cluster connection details (includes address) | object |
- |
s3_config |
S3-compatible storage configuration | object |
- |
Cluster Object Structure¶
# Source cluster
{
endpoint = string # REST API URL (e.g., https://cluster:8000)
username = string # Admin username
password = string # Admin password
}
# Target cluster (includes address for replication)
{
endpoint = string # REST API URL
username = string # Admin username
password = string # Admin password
address = string # Hostname/IP reachable from source (port 3712)
}
Outputs¶
| Name | Description |
|---|---|
source_relationship_id |
ID of the source replication relationship |
source_root_id |
File ID of the source directory |
target_relationship_state |
State of the target relationship (ESTABLISHED when ready) |
target_root_path |
Path on target cluster where data is replicated |
object_backup_relationship_id |
ID of the object storage backup relationship |
object_restore_relationship_id |
ID of the object storage restore relationship |
Replication Patterns¶
1. Basic Cluster-to-Cluster¶
# On source cluster: initiate replication
resource "qumulo_replication_source_relationship" "primary" {
connection_profile = "source"
target_address = "target-cluster.example.com"
target_root_path = "/replica"
source_root_path = "/data"
trigger_initial_replication = true
replication_enabled = true
}
# On target cluster: authorize the relationship
resource "qumulo_replication_target_relationship" "replica" {
depends_on = [qumulo_replication_source_relationship.primary]
connection_profile = "target"
id = qumulo_replication_source_relationship.primary.id
allow_fs_path_create = true
}
2. Blackout Windows¶
Pause replication during business hours to preserve bandwidth:
resource "qumulo_replication_source_relationship" "with_blackout" {
connection_profile = "source"
target_address = "target-cluster.example.com"
target_root_path = "/replica-scheduled"
source_root_path = "/data-scheduled"
blackout_window_timezone = "America/Los_Angeles"
blackout_window {
start_hour = 9
start_minute = 0
end_hour = 17
end_minute = 0
on_days = ["MON", "TUE", "WED", "THU", "FRI"]
}
}
3. Snapshot-Based Replication¶
Link replication to a snapshot policy for point-in-time consistency:
resource "qumulo_replication_source_relationship" "snapshot_based" {
connection_profile = "source"
target_address = "target-cluster.example.com"
target_root_path = "/replica-snapshots"
source_root_path = "/data-snapshots"
replication_mode = "REPLICATION_SNAPSHOT_POLICY"
snapshot_policy {
id = 1 # Existing snapshot policy ID
target_expiration = "7days"
}
}
4. Object Storage (Backup/Archive)¶
# Backup TO S3
resource "qumulo_replication_object_relationship" "backup" {
connection_profile = "source"
direction = "COPY_TO_OBJECT"
local_directory_path = "/data/backup"
object_store_address = "s3.amazonaws.com"
bucket = "my-backup-bucket"
region = "us-west-2"
access_key_id = var.s3_access_key
secret_access_key = var.s3_secret_key
bucket_style = "BUCKET_STYLE_PATH"
object_folder = "qumulo-backup"
}
# Restore FROM S3
resource "qumulo_replication_object_relationship" "restore" {
connection_profile = "source"
direction = "COPY_FROM_OBJECT"
local_directory_path = "/data/restored"
object_store_address = "s3.amazonaws.com"
bucket = "my-archive-bucket"
region = "us-west-2"
access_key_id = var.s3_access_key
secret_access_key = var.s3_secret_key
object_folder = "qumulo-archive"
}
Security Considerations¶
-
Credentials: Store cluster and S3 credentials securely:
-
Encryption: Data in transit uses TLS. For object storage, ensure the bucket has server-side encryption enabled.
-
IAM Policies: For S3 replication, use IAM roles with minimal permissions:
Full Configuration¶
# Example: Cluster-to-Cluster and Object Storage Replication
#
# This example demonstrates how to set up replication between Qumulo clusters
# and to S3-compatible object storage using the replication resources.
#
# Three types of replication are shown:
# 1. Source relationship - defines replication FROM this cluster
# 2. Target relationship - authorizes replication TO this cluster
# 3. Object relationship - replicates to/from S3-compatible storage
terraform {
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
variable "source_cluster" {
description = "Source cluster connection details"
type = object({
endpoint = string
username = string
password = string
})
sensitive = true
}
variable "target_cluster" {
description = "Target cluster connection details"
type = object({
endpoint = string
username = string
password = string
address = string # IP/hostname reachable from source cluster
})
sensitive = true
}
variable "s3_config" {
description = "S3-compatible storage configuration for object replication"
type = object({
endpoint = string
bucket = string
region = string
access_key_id = string
secret_access_key = string
})
sensitive = true
}
# Define connection profiles for both clusters
provider "qumulo" {
connection_profiles = [
{
name = "source"
endpoint = var.source_cluster.endpoint
username = var.source_cluster.username
password = var.source_cluster.password
insecure_skip_verify = true # Required for clusters with self-signed certificates
},
{
name = "target"
endpoint = var.target_cluster.endpoint
username = var.target_cluster.username
password = var.target_cluster.password
insecure_skip_verify = true # Required for clusters with self-signed certificates
}
]
}
# =============================================================================
# Cluster-to-Cluster Replication
# =============================================================================
# Step 1: Create the source relationship on the source cluster
# This initiates replication to the target cluster
resource "qumulo_replication_source_relationship" "primary" {
connection_profile = "source"
# Required: Define what to replicate and where
target_address = var.target_cluster.address
target_root_path = "/replica"
source_root_path = "/data"
# Optional: Trigger initial replication after authorization
trigger_initial_replication = true
# Optional: Configure replication behavior
replication_enabled = true
target_port = 3712
}
# Step 2: Authorize the relationship on the target cluster
# IMPORTANT: Use depends_on to ensure source is created first
resource "qumulo_replication_target_relationship" "replica" {
depends_on = [qumulo_replication_source_relationship.primary]
connection_profile = "target"
# The ID comes from the source relationship
id = qumulo_replication_source_relationship.primary.id
# Optional: Allow target directory creation if it doesn't exist
allow_fs_path_create = true
}
# =============================================================================
# Cluster-to-Cluster Replication with Blackout Windows
# =============================================================================
# Replication with scheduled blackout windows (e.g., business hours)
resource "qumulo_replication_source_relationship" "with_blackout" {
connection_profile = "source"
target_address = var.target_cluster.address
target_root_path = "/replica-scheduled"
source_root_path = "/data-scheduled"
# Timezone for blackout windows
blackout_window_timezone = "America/Los_Angeles"
# Pause replication during business hours (9 AM - 5 PM weekdays)
blackout_window {
start_hour = 9
start_minute = 0
end_hour = 17
end_minute = 0
on_days = ["MON", "TUE", "WED", "THU", "FRI"]
}
}
# =============================================================================
# Snapshot Policy Replication
# =============================================================================
# Replication linked to a snapshot policy
resource "qumulo_replication_source_relationship" "snapshot_based" {
connection_profile = "source"
target_address = var.target_cluster.address
target_root_path = "/replica-snapshots"
source_root_path = "/data-snapshots"
# Use snapshot policy mode
replication_mode = "REPLICATION_SNAPSHOT_POLICY"
# Link to an existing snapshot policy (policy ID must exist on cluster)
snapshot_policy {
id = 1 # Replace with actual snapshot policy ID
target_expiration = "7days"
}
}
# =============================================================================
# Object Storage Replication (S3-Compatible)
# =============================================================================
# Copy data TO S3-compatible object storage (backup/archive)
resource "qumulo_replication_object_relationship" "backup_to_s3" {
connection_profile = "source"
# Direction: copy from cluster to object storage
direction = "COPY_TO_OBJECT"
local_directory_path = "/data/backup"
# S3 configuration
object_store_address = var.s3_config.endpoint
bucket = var.s3_config.bucket
region = var.s3_config.region
access_key_id = var.s3_config.access_key_id
secret_access_key = var.s3_config.secret_access_key
# Optional settings
bucket_style = "BUCKET_STYLE_PATH"
object_folder = "qumulo-backup"
port = 443
}
# Copy data FROM S3-compatible object storage (restore)
resource "qumulo_replication_object_relationship" "restore_from_s3" {
connection_profile = "source"
# Direction: copy from object storage to cluster
direction = "COPY_FROM_OBJECT"
local_directory_path = "/data/restored"
# S3 configuration
object_store_address = var.s3_config.endpoint
bucket = var.s3_config.bucket
region = var.s3_config.region
access_key_id = var.s3_config.access_key_id
secret_access_key = var.s3_config.secret_access_key
bucket_style = "BUCKET_STYLE_PATH"
object_folder = "qumulo-archive"
}
# =============================================================================
# Outputs
# =============================================================================
output "source_relationship_id" {
description = "ID of the source replication relationship"
value = qumulo_replication_source_relationship.primary.id
}
output "source_root_id" {
description = "File ID of the source directory"
value = qumulo_replication_source_relationship.primary.source_root_id
}
output "target_relationship_state" {
description = "State of the target relationship (ESTABLISHED when ready)"
value = qumulo_replication_target_relationship.replica.state
}
output "target_root_path" {
description = "Path on target cluster where data is replicated"
value = qumulo_replication_target_relationship.replica.target_root_path
}
output "object_backup_relationship_id" {
description = "ID of the object storage backup relationship"
value = qumulo_replication_object_relationship.backup_to_s3.id
}
output "object_restore_relationship_id" {
description = "ID of the object storage restore relationship"
value = qumulo_replication_object_relationship.restore_from_s3.id
}