Infrastructure as code is taking over in cloud infrastructure management. It ensures automated provisioning which lessens the time taken to create multiple virtual machines. With infrastructure as code, we use configuration files having code that corresponds to the specifications of the provider being used. Terraform is therefore a tool that you can use manage your infrastructure using codes written in configuration files. With such configuration files, you can deploy any number of virtual machines also easily make replacements in case a VM crashes. In this guide today, we are going to look at how to deploy Virtual Machines in Openstack using terraform. I am going to be using Ubuntu 24.04 where Terraform will be installed.
Step 1: Install Terraform on Linux
The first step is to install Terraform on your working environment.
# Ubuntu/Debian
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
# CentOS/RHEL
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform
# Fedora
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager addrepo --from-repofile=https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
sudo dnf -y install terraform
# Amazon Linux
sudo yum install -y yum-utils shadow-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum -y install terraform
# macOS Homebrew
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
Confirm Terraform installation:
$ terraform --version
Terraform v1.11.2
on linux_amd64
Step 2: Create Terraform Working directory
We need to create a directory where all our Terraform files will be stored. We will initialize Terraform in this directory
mkdir Terraform
cd Terraform
Step 3: Initialize Terraform for OpenStack
Now create a file to define your provider. Note that Terraform reads from files ending with .tf. You can create a file called providers.tf
vim provider.tf
Since our provider is openstack, add the below content to your file:
terraform {
required_version = ">= 0.14.0"
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 1.35.0"
}
}
}
Save the file and initialize terraform.
terraform init
Sample output:
Initializing the backend...
Initializing provider plugins...
- Finding terraform-provider-openstack/openstack versions matching "~> 1.35.0"...
- Installing terraform-provider-openstack/openstack v1.35.0...
- Installed terraform-provider-openstack/openstack v1.35.0 (self-signed, key ID 4F80527A391BEFD2)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Step 4: Create VMs with Terraform on Opestack
Now that we have our working directory and have initialized Terraform, we will go ahead to see how to manage one virtual machine on Openstack with Terraform. Follow the steps as below:
Provide ssh key
We need to provide a public key that we will use to access the created virtual machines. Here I am going to create a file called main.tf with the below content:
resource "openstack_compute_keypair_v2" "my-cloud-key" {
name = "my-key"
public_key = "ssh-rsa AAAAB3Nz…….
}
Where:
openstack_compute_keypair_v2
: the type of the resoure
my-cloud-key
: the name of the specific resource
- Replace the value for public_key with your own key.
Define provider access credentials
We need to be able to connect to our Openstack infrastructure. Define access url, access username, password and any other required specifications. You can define them as variables or include them in your .tf files. In my providers.tf file, I added the content as below:
provider "openstack" {
user_name = "username"
password = "password"
auth_url = "http://<ip>/v2"
user_domain_name = "Default"
project_domain_name = "Default"
}
Here, you need to replace all the values above with the ones corresponding to your environment.
Creating a single VM
To be able to create a VM with terraform, I added the below content in my providers.tf
file
resource "openstack_compute_instance_v2" "my_instance" {
name = "my_instance"
image_id = "your_image_id"
flavor_name = "flavor_name"
key_pair = "my-key"
network {
uuid = "your_network_uuid"
name = "public"
}
}
openstack_compute_instance_v2
: the type of resource
my_instance
: the name of the resource
Run terraform plan
Running ‘terraforn plan’ is not necessary but it is meant to show you the changes that will be applied before they are actually applied.
$ terraform plan
openstack_compute_keypair_v2.my-cloud-key: Refreshing state... [id=my-key]
openstack_compute_instance_v2.my_instance: Refreshing state... [id=2ccae904-0257-4cdc-9964-b01e0feafd1d]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# openstack_compute_instance_v2.my_instance will be created
+ resource "openstack_compute_instance_v2" "my_instance" {
+ access_ip_v4 = (known after apply)
+ access_ip_v6 = (known after apply)
+ all_metadata = (known after apply)
+ all_tags = (known after apply)
+ availability_zone = (known after apply)
+ flavor_id = (known after apply)
+ flavor_name = "m1.small"
+ force_delete = false
+ id = (known after apply)
+ image_id = "0b89b169-0ddb-46df-94cd-748692421574"
+ image_name = (known after apply)
+ key_pair = "my-key"
+ name = "my_instance"
+ power_state = "active"
+ region = (known after apply)
+ security_groups = (known after apply)
+ stop_before_destroy = false
+ network {
+ access_network = false
+ fixed_ip_v4 = (known after apply)
+ fixed_ip_v6 = (known after apply)
+ floating_ip = (known after apply)
+ mac = (known after apply)
+ name = "public"
+ port = (known after apply)
+ uuid = "ad3eddbb-fc0f-4450-a427-3f050ea2f0e1"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Run Terraform Apply
The last step is to apply your configuration on the Openstack environment. Simply run ‘terafform apply’
$ terraform apply
openstack_compute_keypair_v2.my-cloud-key: Refreshing state... [id=my-key]
openstack_compute_instance_v2.my_instance: Refreshing state... [id=2ccae904-0257-4cdc-9964-b01e0feafd1d]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# openstack_compute_instance_v2.my_instance will be created
+ resource "openstack_compute_instance_v2" "my_instance" {
+ access_ip_v4 = (known after apply)
+ access_ip_v6 = (known after apply)
+ all_metadata = (known after apply)
+ all_tags = (known after apply)
+ availability_zone = (known after apply)
+ flavor_id = (known after apply)
+ flavor_name = "m1.small"
+ force_delete = false
+ id = (known after apply)
+ image_id = "0b89b169-0ddb-46df-94cd-748692421574"
+ image_name = (known after apply)
+ key_pair = "my-key"
+ name = "my_instance"
+ power_state = "active"
+ region = (known after apply)
+ security_groups = (known after apply)
+ stop_before_destroy = false
+ network {
+ access_network = false
+ fixed_ip_v4 = (known after apply)
+ fixed_ip_v6 = (known after apply)
+ floating_ip = (known after apply)
+ mac = (known after apply)
+ name = "public"
+ port = (known after apply)
+ uuid = "ad3eddbb-fc0f-4450-a427-3f050ea2f0e1"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
Enter ‘yes’ when prompted. And configuration application will continue and your VM will be created.
openstack_compute_instance_v2.my_instance: Creating...
openstack_compute_instance_v2.my_instance: Still creating... [10s elapsed]
openstack_compute_instance_v2.my_instance: Creation complete after 15s [id=10e581e1-68f8-4b89-943d-9bd3a4c5bbf1]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Your VM should be created now. To confirm, login to your Openstack web UI or run ‘terraform show’ on your terminal which shows you the VM specifications including the IP address.
$ terraform show
# openstack_compute_instance_v2.my_instance:
resource "openstack_compute_instance_v2" "my_instance" {
access_ip_v4 = "192.168.50.2"
all_metadata = {}
all_tags = []
availability_zone = "external"
flavor_id = "2"
flavor_name = "m1.small"
force_delete = false
id = "2ccae904-0257-4cdc-9964-b01e0feafd1d"
image_id = "0b89b169-0ddb-46df-94cd-748692421574"
image_name = "Debian-10.7.0"
key_pair = "my-key"
name = "my_instance"
power_state = "active"
security_groups = [
"default",
]
stop_before_destroy = false
tags = []
network {
access_network = false
fixed_ip_v4 = "192.168.50.2"
mac = "fe:36:3h:af:4g:59"
name = "public"
uuid = "ad3eddbb-fc0f-4450-a427-3f050ea2f0e1"
}
}
# openstack_compute_keypair_v2.my-cloud-key:
resource "openstack_compute_keypair_v2" "my-cloud-key" {
fingerprint = "ec:6a:87:91:7f:3e:6a:87:76:4d:ba:00:f3:g1:ae:32"
id = "my-key"
name = "my-key"
public_key = "ssh-rsa AAAAB3NzaC1yc -----
}
You have successfully created your first virtual machine on Openstack using Terraform.
Adding more Virtual Machines
If you need to add more virtual machines with the same specs, simply provide the number of Vms needed and you can choose to increment the naming to the number of Vms you need.Example below:
resource "openstack_compute_instance_v2" "exec" {
name = "exec-${count.index}"
image_name = "denbi-centos7-j10-2e08aa4bfa33-master"
flavor_name = "m1.tiny"
key_pair = "${openstack_compute_keypair_v2.my-cloud-key.name}"
security_groups = ["default"]
count = 2
network {
name = "public"
}
}
Then run terraform apply.
At thispoint, you have successfully installed Terraform on Ubuntu 24.04 and deployed your first virtual machine. Note that this tutorial does not include everything required for you to become an expert in Terraform but meant to give a quick start guide in your journey in Infrastructure as code and cloud automation. I hope the guide will be of help to you. Check more automation-related guides below: