OpenStack Private Cloud›06 · Orchestration
Learning Hub / Cloud — OpenStack, AWS & EKS / OpenStack Private Cloud

Lesson 06 of 9 · Modules

Orchestration

Build OpenStack environments as code: Heat's native HOT templates and stacks, the Terraform OpenStack provider, and how to choose between them for tenant and platform automation.

Practitioner
Key wordsHeatHOT templatesstacksparametersoutputsTerraform OpenStack providerinfrastructure as code

Two ways to describe an environment

Heat Terraform OpenStack provider
Where it runs Inside the cloud (a service) Your machine or CI
Format HOT (YAML) templates HCL
State Kept by Heat Terraform state (remote backend)
Scope OpenStack resources OpenStack and anything else with a provider
Plans/previews stack update --dry-run (limited) Full plan

Heat is the hotel's own event-planning service: you hand them a form, and they set up the rooms, the Wi-Fi and the projectors, and take it all down afterwards. Terraform is an independent event planner who can also book the catering, the taxis and the venue next door, because they work with many companies, not just this hotel.

A HOT template

heat_template_version: 2021-04-16
description: One web server on a private network with a floating IP

parameters:
  key_name:  { type: string }
  image:     { type: string, default: ubuntu-24.04 }
  flavor:    { type: string, default: m1.small }
  public_net: { type: string, default: public }

resources:
  net:
    type: OS::Neutron::Net
  subnet:
    type: OS::Neutron::Subnet
    properties:
      network: { get_resource: net }
      cidr: 10.10.0.0/24
  router:
    type: OS::Neutron::Router
    properties:
      external_gateway_info: { network: { get_param: public_net } }
  router_if:
    type: OS::Neutron::RouterInterface
    properties:
      router: { get_resource: router }
      subnet: { get_resource: subnet }
  web:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }
      key_name: { get_param: key_name }
      networks: [ { network: { get_resource: net } } ]
  fip:
    type: OS::Neutron::FloatingIP
    depends_on: router_if
    properties:
      floating_network: { get_param: public_net }
  fip_assoc:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_resource: fip }
      port_id: { get_attr: [ web, addresses, { get_resource: net }, 0, port ] }

outputs:
  web_ip:
    value: { get_attr: [ fip, floating_ip_address ] }

(Attribute paths such as the port lookup vary slightly between releases; openstack orchestration resource type show OS::Nova::Server lists what your cloud supports.)

$ openstack stack create -t web.yaml --parameter key_name=mykey web --wait
$ openstack stack output show web web_ip

The same with Terraform

terraform {
  required_providers {
    openstack = { source = "terraform-provider-openstack/openstack" }
  }
}

provider "openstack" {}                       # uses OS_CLOUD / clouds.yaml

resource "openstack_networking_network_v2" "net" { name = "web-net" }

resource "openstack_networking_subnet_v2" "subnet" {
  network_id = openstack_networking_network_v2.net.id
  cidr       = "10.10.0.0/24"
}

resource "openstack_compute_instance_v2" "web" {
  name        = "web-01"
  image_name  = "ubuntu-24.04"
  flavor_name = "m1.small"
  key_pair    = "mykey"
  network { uuid = openstack_networking_network_v2.net.id }
}

(Add a router, router interface and floating IP resources to match the Heat example.) All the Terraform practices from Terraform & IaC apply: remote state, modules, plans in CI.

Choosing

  • Heat: tenant self-service without extra tooling; Octavia, Magnum and some services use it internally; no external state to manage.
  • Terraform: platform teams automating OpenStack alongside DNS, Kubernetes, monitoring and other clouds with one workflow.
  • Many organisations use Terraform for platform infrastructure and let tenants choose.

Try it: the same environment twice (lab cloud)

  1. Create the web stack with Heat; read the events as it builds; SSH in via the output IP.
  2. Update the stack with a bigger flavor (openstack stack update … --parameter flavor=m1.medium) and watch what Heat does to the server.
  3. Break the template (a wrong image name), create it, and find the error in the stack events.
  4. Build the same environment with Terraform and the OpenStack provider; compare terraform plan with Heat's behaviour.
  5. Delete both, and confirm nothing is left behind (openstack server list, openstack floating ip list).

Going deeper: IaC for private clouds

  • Keep images, flavors and networks (platform-owned) in platform Terraform; let tenant stacks reference them by name or ID.
  • Use Heat environment files and nested templates for reusable building blocks, or Terraform modules.
  • Automate quotas and projects too (Keystone and Nova resources exist in the Terraform provider), so onboarding a team is a pull request.

Recap

  • Heat: native HOT templates → stacks; debug with stack event list.
  • Terraform OpenStack provider: HCL, plans, state, modules, and multi-provider workflows.
  • Heat for native tenant self-service; Terraform for platform-wide automation. Both are infrastructure as code.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.