Run your own scripts during cluster boot¶
When you finish, your own shell runs inside the cluster's boot scripts, and every node and provisioner run picks up your proxy, CA, agent, or notification. The node_hooks and provisioner_hooks attributes work the same way on qumulo_filesystem_aws, qumulo_filesystem_azure, and qumulo_filesystem_gcp.
Before you start¶
- A cluster configuration from Deploy a basic AWS cluster, Deploy a basic Azure cluster, or Deploy a basic GCP cluster
- The shell you want to run, and
shellcheckto lint it - A way onto a node from SSH Access, to check the result
1. Pick the anchor¶
- To prepare each node before it touches the network (proxy, CA, package mirror), use
node_hooks.pre_run. - To add software to each node after qumulo-core is installed (monitoring agent), use
node_hooks.post_run. - To prepare the provisioner before it touches the network (proxy, mirror), use
provisioner_hooks.pre_run. - To act once the cluster is formed and configured (notification, CMDB record), use
provisioner_hooks.post_run.
You now know which of the four fields each script belongs in.
2. Write the hook¶
Check every hook against this list.
- Make each command succeed, or end it in
|| truewhere failure is acceptable. - Keep secrets out. Fetch credentials from the instance's IAM role, managed identity, service account, or a cloud secret store.
- Make a second run harmless.
- Run
shellcheckon the script. - Use only the image's stock commands in
pre_run, and move anything that needs the cloud CLI orjqtopost_run.
The hook passes all five, and shellcheck prints nothing. The shell variables a hook can read are listed in Shell variables available to boot hooks.
3. Add it to the configuration¶
This AWS configuration wires all four hooks inline. Each field is a plain string, so file("${path.module}/hooks/notify.sh") works in place of any heredoc.
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" {
aws {}
}
resource "qumulo_filesystem_aws" "cluster" {
cluster_name = "qumulo"
deployment_name = "qumulo"
region = "us-east-1" # <-- Replace with your region
subnet_ids = ["subnet-0123456789abcdef0"] # <-- Replace with your subnet ID
node_count = 3
instance_type = "m6idn.2xlarge"
cluster_product_type = "HOT"
admin_password = "YourSecurePassword123!" # <-- Replace with your admin password
allow_cidrs = ["10.0.0.0/8"] # <-- Replace with your client networks
deletion_protection = true
node_hooks = {
pre_run = <<-EOT
export http_proxy="http://proxy.corp.example.com:3128" # <-- Replace with your proxy
export https_proxy="$http_proxy"
echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/95corp-proxy
cp /opt/corp/ca/corp-root.crt /usr/local/share/ca-certificates/ && update-ca-certificates
EOT
post_run = <<-EOT
curl -fsSL "https://agent.corp.example.com/install.sh" | bash # <-- Replace with your agent installer
EOT
}
provisioner_hooks = {
pre_run = <<-EOT
export https_proxy="http://proxy.corp.example.com:3128" # <-- Replace with your proxy
export no_proxy="169.254.169.254,localhost,127.0.0.1"
EOT
post_run = <<-EOT
curl -fsS -X POST "https://cmdb.corp.example.com/api/clusters" \
-H "Content-Type: application/json" \
-d "{\"deployment\":\"$deployment_name\",\"status\":\"ready\"}" # <-- Replace with your tracker
EOT
}
timeouts {
create = "90m"
}
}
output "endpoint_ips" {
value = qumulo_filesystem_aws.cluster.endpoint_ips
}
Replace the values marked <-- Replace. Inside a heredoc, write shell variables as $name, since Terraform claims ${...} for its own interpolation.
On Azure or GCP, copy the node_hooks and provisioner_hooks blocks into your qumulo_filesystem_azure or qumulo_filesystem_gcp resource. terraform validate prints Success! The configuration is valid.
4. Apply¶
For a new cluster the plan ends with Plan: 1 to add, 0 to change, 0 to destroy., and every hook runs during the create. On an existing cluster the plan shows Plan: 0 to add, 1 to change, 0 to destroy., and the new hooks run at the next provisioner launch (scaling, node replacement, storage updates) or the next new node's first boot, never on running instances.
5. Check the hook ran¶
Every hook line is traced into the boot log with a leading +. Sign in to a node and search that log for a command from your hook.
The search prints your hook's lines, and /var/lib/qumulo-node/bootstrap-complete exists once the node script has finished, post_run included. Provisioner hooks log to CloudWatch Logs under /qumulo/<deployment>/provisioner on AWS, to cloud-init output on Azure, and to Cloud Logging and the serial console on GCP.
Warning
A failing provisioner_hooks.pre_run on AWS or Azure cannot report itself, and terraform apply waits out its full timeout. Read the provisioner's boot log instead of waiting.
Next¶
Every variable a hook can read is listed in Shell variables available to boot hooks. To confirm a hook ran on a node, see SSH to a node.