Skip to content

Using Terraform on Breqwatr Cloud

This tutorial shows how to deploy a small highly-available stack on Breqwatr Cloud using Terraform and the OpenStack provider — private network, three compute instances, and a load balancer fronting them.

Prerequisites

  • Terraform installed locally.
  • A clouds.yaml file at ~/.config/openstack/clouds.yaml (or %APPDATA%\openstack\clouds.yaml on Windows) containing an application credential for the project you want to deploy into. The Application credentials page generates one in a click and the same file works for Terraform, Ansible, and the OpenStack CLI.
  • The OpenStack CLI installed locally for verification — strictly optional but worth having.

Steps

1. Point Terraform at the right cloud

The OpenStack provider reads clouds.yaml automatically when you set OS_CLOUD to the entry name. The Application credentials page names the entry breqwatr by default:

export OS_CLOUD=breqwatr

Add this to your shell profile (~/.bashrc, ~/.zshrc, etc.) so new shells pick it up.

Verify it works:

openstack image list

If you see images, your credentials are wired up correctly. If you get an authentication error, check the credential hasn't been revoked from Application credentials.

2. Set up Terraform with the OpenStack provider

Terraform reads all files ending in .tf. Your working directory will look like:

main.tf
networks.tf
instances.tf
loadbalancer.tf

main.tf:

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

# Configure the OpenStack Provider to use Octavia Load Balancer
provider "openstack" {
  use_octavia = true
}

Initialize Terraform:

terraform init

This downloads the OpenStack provider and sets up your workspace.

3. Create a private network and subnet

networks.tf:

resource "openstack_networking_network_v2" "private" {
  name           = "private"
  admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "default_sn" {
  name       = "default_sn"
  cidr       = "192.168.42.0/24"
  ip_version = 4
  network_id = openstack_networking_network_v2.private.id
}

Apply the configuration:

terraform apply

Confirm with yes, then check in OpenStack:

openstack network list

4. Create compute instances

instances.tf:

resource "openstack_compute_instance_v2" "blue" {
  # Number of instances to deploy
  count = 3

  name            = "blue_${count.index}"
  flavor_name     = "v1-c4r8"
  key_pair        = "<your_key_name>"
  security_groups = ["default"]
  # user_data       = file("cloud-init-blue.yaml")

  network {
    name = data.openstack_networking_network_v2.private.name

    # Assign unique IPs for each instance
    fixed_ip_v4 = "192.168.42.${count.index + 10}"
  }
}

Apply again:

terraform apply

Verify:

openstack server list

5. Create a load balancer

loadbalancer.tf:

resource "openstack_lb_loadbalancer_v2" "demo_lb" {
  name           = "demo-loadbalancer"
  vip_network_id = data.openstack_networking_network_v2.external.id
}

resource "openstack_lb_listener_v2" "listener_1" {
  protocol        = "HTTP"
  protocol_port   = 80
  loadbalancer_id = openstack_lb_loadbalancer_v2.demo_lb.id

  insert_headers = {
    X-Forwarded-For = "true"
  }
}

resource "openstack_lb_pool_v2" "main_pool" {
  protocol    = "HTTP"
  lb_method   = "ROUND_ROBIN"
  listener_id = openstack_lb_listener_v2.listener_1.id
}

resource "openstack_lb_members_v2" "members_1" {
  count   = 3
  pool_id = openstack_lb_pool_v2.main_pool.id

  member {
    address       = "192.168.42.${count.index + 10}"
    protocol_port = 80
  }
}

If the loadbalancer CLI commands are missing, install:

pip install python-octaviaclient

(This adds Octavia support to the OpenStack CLI.)

Verification

openstack loadbalancer list

You now have a private network, three compute instances, and a load balancer distributing traffic across them, all managed by Terraform.

Next steps