Use Terraform to manage an OpenStack cluster

Terraform is a declarative language that can act as a blueprint of the infrastructure you're working on.
1 reader likes this.
What's new in OpenStack in 2016: A look at the Newton release

Opensource.com

After having an OpenStack production and home lab for a while, I can definitively say that provisioning a workload and managing it from an Admin and Tenant perspective is important.

Terraform is an open source Infrastructure-as-Code (IaC) software tool used for provisioning networks, servers, cloud platforms, and more. Terraform is a declarative language that can act as a blueprint of the infrastructure you're working on. You can manage it with Git, and it has a strong GitOps use case.

This article covers the basics of managing an OpenStack cluster using Terraform. I recreate the OpenStack Demo project using Terraform.

Install Terraform

I use CentOS as a jump host, where I run Terraform. Based on the official documentation, the first step is to add the Hashicorp repository:

$ sudo dnf config-manager \
--add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo

Next, install Terraform:

$ sudo dnf install terraform -y

Verify the installation:

$ terraform –version

If you see a version number in return, you have installed Terraform.

Create a Terraform script for the OpenStack provider

In Terraform, you need a provider. A provider is a converter that Terraform calls to convert your .tf into API calls to the platform you are orchestrating.

There are three types of providers: Official, Partner, and Community:

  • Official providers are Hashicorp maintained.
  • Partner providers are maintained by technology companies that partner with Hashicorp.
  • Community providers are maintained by open source community members.

There is a good Community provider for OpenStack in this link. To use this provider, create a .tf file and call it main.tf.

$ vi main.tf

Add the following content to main.tf:

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

provider "openstack" {
  user_name   = “OS_USERNAME”
  tenant_name = “OS_TENANT”
  password    = “OS_PASSWORD”
  auth_url    = “OS_AUTH_URL”
  region      = “OS_REGION”
}

You need to change the OS_USERNAME, OS_TENANT, OS_PASSWORD, OS_AUTH_URL, and OS_REGION variables for it to work.

Create an Admin Terraform file

OpenStack Admin files focus on provisioning external networks, routers, users, images, tenant profiles, and quotas.

This example provisions flavors, a router connected to an external network, a test image, a tenant profile, and a user.

First, create an AdminTF directory for the provisioning resources:

$ mkdir AdminTF

$ cd AdminTF

In the main.tf, add the following:

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

provider "openstack" {
  user_name   = “OS_USERNAME”
  tenant_name = “admin”
  password    = “OS_PASSWORD”
  auth_url    = “OS_AUTH_URL”
  region      = “OS_REGION”
}

resource "openstack_compute_flavor_v2" "small-flavor" {
  name      = "small"
  ram       = "4096"
  vcpus     = "1"
  disk      = "0"
  flavor_id = "1"
  is_public = "true"
}

resource "openstack_compute_flavor_v2" "medium-flavor" {
  name      = "medium"
  ram       = "8192"
  vcpus     = "2"
  disk      = "0"
  flavor_id = "2"
  is_public = "true"
}

resource "openstack_compute_flavor_v2" "large-flavor" {
  name      = "large"
  ram       = "16384"
  vcpus     = "4"
  disk      = "0"
  flavor_id = "3"
  is_public = "true"
}

resource "openstack_compute_flavor_v2" "xlarge-flavor" {
  name      = "xlarge"
  ram       = "32768"
  vcpus     = "8"
  disk      = "0"
  flavor_id = "4"
  is_public = "true"
}

resource "openstack_networking_network_v2" "external-network" {
  name           = "external-network"
  admin_state_up = "true"
  external       = "true"
  segments {
    network_type     = "flat"
    physical_network = "physnet1"
  }
}

resource "openstack_networking_subnet_v2" "external-subnet" {
  name            = "external-subnet"
  network_id      = openstack_networking_network_v2.external-network.id
  cidr            = "10.0.0.0/8"
  gateway_ip      = "10.0.0.1"
  dns_nameservers = ["10.0.0.254", "10.0.0.253"]
  allocation_pool {
    start = "10.0.0.1"
    end   = "10.0.254.254"
  }
}

resource "openstack_networking_router_v2" "external-router" {
  name                = "external-router"
  admin_state_up      = true
  external_network_id = openstack_networking_network_v2.external-network.id
}

resource "openstack_images_image_v2" "cirros" {
  name             = "cirros"
  image_source_url = "https://download.cirros-cloud.net/0.6.1/cirros-0.6.1-x86_64-disk.img"
  container_format = "bare"
  disk_format      = "qcow2"

  properties = {
    key = "value"
  }
}

resource "openstack_identity_project_v3" "demo-project" {
  name = "Demo"
}

resource "openstack_identity_user_v3" "demo-user" {
  name               = "demo-user"
  default_project_id = openstack_identity_project_v3.demo-project.id
  password = "demo"
}

Create a Tenant Terraform file

As a Tenant, you usually create VMs. You also create network and security groups for the VMs.

This example uses the user created above by the Admin file.

First, create a TenantTF directory for Tenant-related provisioning:

$ mkdir TenantTF
$ cd TenantTF

In the main.tf, add the following:

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

provider "openstack" {
  user_name   = “demo-user”
  tenant_name = “demo”
  password    = “demo”
  auth_url    = “OS_AUTH_URL”
  region      = “OS_REGION”
}

resource "openstack_compute_keypair_v2" "demo-keypair" {
  name       = "demo-key"
  public_key = "ssh-rsa ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
}


resource "openstack_networking_network_v2" "demo-network" {
  name           = "demo-network"
  admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "demo-subnet" {
  network_id = openstack_networking_network_v2.demo-network.id
  name       = "demo-subnet"
  cidr       = "192.168.26.0/24"
}

resource "openstack_networking_router_interface_v2" "demo-router-interface" {
  router_id = “XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”
  subnet_id = openstack_networking_subnet_v2.demo-subnet.id
}

resource "openstack_compute_instance_v2" "demo-instance" {
  name            = "demo"
  image_id        = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
  flavor_id       = "3"
  key_pair        = "demo-key"
  security_groups = ["default"]

  metadata = {
    this = "that"
  }

  network {
    name = "demo-network"
  }
}

Initialize your Terraform

After creating the Terraform files, you need to initialize Terraform.

For Admin:

$ cd AdminTF

$ terraform init

$ terraform fmt

For Tenants:

$ cd TenantTF

$ terraform init

$ terraform fmt

Command explanation:

  • terraform init downloads the provider from the registry to use in provisioning this project.
  • terraform fmt formats the files for use in repositories.

Create a Terraform plan

Next, create a plan for you to see what resources will be created.

For Admin:

$ cd AdminTF

$ terraform validate

$ terraform plan

For Tenants:

$ cd TenantTF

$ terraform validate

$ terraform plan

Command explanation:

  • terraform validate validates whether the .tf syntax is correct.
  • terraform plan creates a plan file in the cache where all managed resources can be tracked in creation and destroy.

Apply your first TF

To deploy the resources, use the terraform apply command. This command applies all resource states in the plan file.

For Admin:

$ cd AdminTF

$ terraform apply

For Tenants:

$ cd TenantTF

$ terraform apply

Next steps

Previously, I wrote an article on deploying a minimal OpenStack cluster on a Raspberry Pi. You can discover how to have more detailed Terraform and Ansible configurations and implement some CI/CD with GitLab.

AJ Canlas
AJ Canlas is a Sr. Solutions Consulting Manager in Micro-D International based in the Philippines, He handles both Public and Private Cloud Infrastructure and Initiatives, His Main Strengths is in Linux, OpenStack, Ansible Automation, and Containerization.

Comments are closed.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.