Skip to content

Deploy with Terraform

Note

You will need to have Terraform installed on the machine that will be executing the commands. Follow the Install Terraform link from the official documentation. We also highly recommend that you use Application Credentials to do any automation

Please make sure you have download the clouds.yaml file for your application credentials and its sitting in the directory ~/.config/openstack/

Generating Application Credentials is covered here

Normally creating a folder space for Terraform projects can be a good thing as this ensures the Terraform state file doesn't clash with another.

Once you are in an empty folder, example terraform-example-flexihpc, we will need to create a file called main.tf

Inside this file we will need to define the provider

provider "openstack" {
  cloud = "NAME_IN_CLOUDS_YAML"
}

Replace the placeholder NAME_IN_CLOUDS_YAML with the name of your openstack section in the clouds.yaml file. An example clouds.yaml with multiple entries looks like the following:

clouds:
  openstack-entry-1:
    auth:
      auth_url: https://keystone.akl-1.cloud.nesi.org.nz
      application_credential_id: "APP_CREDS_ID"
      application_credential_secret: "APP_CREDS_SECRET"
    interface: "public"
    identity_api_version: 3
    auth_type: "v3applicationcredential"
    verify: false
  openstack-entry-2:
    auth:
      auth_url: https://keystone.akl-1.cloud.nesi.org.nz
      application_credential_id: "APP_CREDS_ID"
      application_credential_secret: "APP_CREDS_SECRET"
    region_name: "akl-1"
    interface: "public"
    identity_api_version: 3
    auth_type: "v3applicationcredential"
    verify: false
You will want to be using the name openstack-entry-X as your the value in NAME_IN_CLOUDS_YAML

Then within the same file we want to define the compute instance

resource "openstack_compute_instance_v2" "compute_instance" {
  name            = "compute-instance-0"
  flavor_id       = "FLEXIHPC_FLAVOR_ID"
  image_id        = "FLEXIHPC_IMAGE_ID"
  key_pair        = "FLEXIHPC_KEY_PAIR_NAME"
  security_groups = ["FLEXIHPC_SECURITY_GROUP_NAME"]

  network {
    name = "FLEXIHPC_NETWORK_NAME"
  }
}

Replace the placeholders FLEXIHPC_FLAVOR_ID, FLEXIHPC_IMAGE_ID, FLEXIHPC_KEY_PAIR_NAME, FLEXIHPC_SECURITY_GROUP_NAME, and FLEXIHPC_NETWORK_NAME with appropriate values from your OpenStack environment.

The network name is normally the same as your FlexiHPC project name.

Then we want to apply a floating IP to the instance so we can connect from outside the FlexiHPC platform

resource "openstack_networking_floatingip_v2" "floating_ip" {
  pool = "external"
}

resource "openstack_compute_floatingip_associate_v2" "floating_ip_association" {
  floating_ip = openstack_networking_floatingip_v2.floating_ip.address
  instance_id = openstack_compute_instance_v2.compute_instance.id
}

The floating IP pool is external within the FlexiHPC platform.

Once all the above is filled in then you only need to run the standard terraform commands

terraform init

This will initialize the terraform directory with all the required modules

Then we run the command to create our resources

terraform apply

Terraform will prompt you to confirm the changes. Type "yes" to proceed with the creation of the compute instance and the floating IP association.

Terraform will then provision the compute instance and associate the floating IP to it.

Remember that this is a basic example, and you might need to adapt it to your specific FlexiHPC environment and configurations.

The full main.tf file for completeness

main.tf
terraform {
required_version = ">= 0.14.0"
  required_providers {
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      version = "~> 1.51.1"
    }
  }
}

provider "openstack" {
  cloud = "NAME_IN_CLOUDS_YAML"
}

resource "openstack_compute_instance_v2" "compute_instance" {
  name            = "compute-instance-0"
  flavor_id       = "FLEXIHPC_FLAVOR_ID"
  image_id        = "FLEXIHPC_IMAGE_ID"
  key_pair        = "FLEXIHPC_KEY_PAIR_NAME"
  security_groups = ["FLEXIHPC_SECURITY_GROUP_NAME"]

  network {
    name = "FLEXIHPC_NETWORK_NAME"
  }
}

resource "openstack_networking_floatingip_v2" "floating_ip" {
  pool = "external"
}

resource "openstack_compute_floatingip_associate_v2" "floating_ip_association" {
  floating_ip = openstack_networking_floatingip_v2.floating_ip.address
  instance_id = openstack_compute_instance_v2.compute_instance.id
}

Using FlexiHPC object storage to store the Terraform state file

Should you wish to not include the terraform state file within the git repo then you will want to update the above with a the backend that you wish to store that file

Within the first chunk of the file you want to add the following so it looks like this

terraform {
required_version = ">= 0.14.0"
  required_providers {
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      version = "~> 1.51.1"
    }
  }

  backend "s3" {
    bucket = "<CONTAINER_NAME>"
    key    = "state/terraform.tfstate"
    endpoint   = "https://object.akl-1.cloud.nesi.org.nz/"
    sts_endpoint = "https://object.akl-1.cloud.nesi.org.nz/"
    access_key = "<EC2 User Access Token>"
    secret_key = "<EC2 User Secret Token>"
    #region = "us-east-1"
    force_path_style = "true"
    skip_credentials_validation = "true"
  }
}

We have added the backend "s3" chunk to the terraform block

<CONTAINER_NAME>
The container name within FlexiHPC object storage. You can create this either via the dashboard or CLI

You will need to update the following after generating EC2 Credentials

<EC2 User Access Token>
The EC2 Credentials Access Token
<EC2 User Secret Token>
The EC2 Credentials User Secret

Save that file and run

terraform init -reconfigure

This will reconfigure the backend to store the state file on FlexiHPC, you can also pass -migrate-state instead of -reconfigure should you have a state file that you want to move there from a previous run.

Your terraform state file should now be configured and stored on FlexiHPC object storage