In the world of ever-changing requirements and workloads, the pressure and constant demand for deployment of applications and infrastructure is relentless. The days when IT admins would install servers manually are slowly but surely fading away. However, as in any situation that removes manual processes, something else must take its place, and in this circumstance it is Infrastructure as code.

Today the biggest and most prominent promoters of infrastructure as code is probably Amazon Web Service (AWS.) After all, it was AWS that introduced us to CloudFormation, the holy grail of Infrastructure as Code. With the use of a structured file, a piece of code you were now able to control anything in your infrastructure; networks, compute resources, storage, automation, DNS, databases, security, scaling, everything.

OpenStack adopted some of the tools used in AWS for their own Orchestration engine Heat and some of them are even still supported today in the current Liberty version. And, although most of the functionality has moved over to Heat native resources, the tools are still beneficial for everyday use.

As the use of cloud technologies and infrastructure grew, the need for solutions that are not solely dependent on a single vendor became a necessity. Cloud environments fail, and with all your eggs in a single basket, IT becomes vulnerable. IT admins started to look for a way to deploy their workloads across clouds and different providers to minimize exposure to risk. The missing piece in this scenario, was a single tool that would allow the end user (be it an IT admin or a developer creating an application) to manage multiple environments with a standard set of tools. Welcome to Terraform.

Terraform Terraform

Terraform is a tool for building, changing, and versioning your infrastructure in a safe and efficient manner. Terraform can manage existing and popular service providers as well as custom in-house solutions, OpenStack, being one of them. Terraform is self-sufficient and executable, which makes it extremely simple to install, and it works on almost any platform.

As of today, Terraform works with the following providers, enabling you to control different types of resources and infrastructures:

Atlas (Hashicorp workflow engine)

AWS, GCE, Azure, OpenStack, DigitalOcean, Docker, CloudStack, Heroku, vSphere, vCloud (Cloud Infrastructure)

Chef, Rundeck (Configuration Management)

CloudFlare, DNSMadeEasy, Dyn, DNSimple (DNS provider)

Mailgun (Email)

Consul, PowerDNS (DNS and service registry)

MySQL, PostgreSQL (Database)

StatusCake (Monitoring)

TLS (Certificates)

Terraform and OpenStack Terraform and OpenStack

Terraform has a number of modules that will allow you manage your OpenStack infrastructure. It does support some (but not all) of the components of OpenStack, namely:

The one obvious component that is not supported is Heat – the orchestration engine – for an obvious reason, Terraform itself is an orchestration tool, and duplication is never a good thing.

Deploying a typical service with Terraform Deploying a typical service with Terraform

In the following example, we will deploy 2 OpenStack instances, install a web server on each of them and configure each of the servers with a default index.html page that displays its hostname – all by using Terraform.

Terraform stores the configuration in files with a .tf extension. First up we will define the variables.

variable "openstack_user_name" { description = "The username for the Tenant." default = "myuser" } variable "openstack_tenant_name" { description = "The name of the Tenant." default = "my_tenant" } variable "openstack_password" { description = "The password for the Tenant." default = "my_password" } variable "openstack_auth_url" { description = "The endpoint url to connect to OpenStack." default = "http://<HOSTNAME>:5000/v2.0" } variable "openstack_keypair" { description = "The keypair to be used." default = "my_keypair" } variable "tenant_network" { description = "The network to be used." default = "my_network" }

Here we have a file that will store all the information you need to interact with your OpenStack infrastructure.

provider "openstack" { user_name = "${var.openstack_user_name}" tenant_name = "${var.openstack_tenant_name}" password = "${var.openstack_password}" auth_url = "${var.openstack_auth_url}" }

Next, we have the provider definitions, the values will be populated from our variable definitions above.

variable "count" { default = 2 } resource "openstack_compute_instance_v2" "web" { count = "${var.count}" name = "${format("web-%02d", count.index+1)}" image_name = "CentOS6" availability_zone = "AZ1" flavor_id = "2" key_pair = "${openstack_keypair}" security_groups = ["default"] network { name = "${tenant_network}" } user_data = "${file("bootstrapweb.sh")}" }

Here we have defined a how many instances are to be deployed and given each of them a name accordingly. We have also defined that the instance should run a number of commands that are defined in the bootstrapweb.sh file below.

#!/bin/bash yum install -y httpd chkconfig --level 345 httpd on cat <<EOF > /var/www/html/index.html <html> <body> <p>hostname is: $(hostname)</p> </body> </html> EOF chown -R apache:apache /var/www/html service httpd start

To test the configuration – we run the following command

terraform plan

This will go through the configuration that you have provided and do a dry run – and will print out what the outcome of your provisioned state will be. An example of such outcome is below:

+ openstack_compute_instance_v2.web.1 access_ip_v4: "" => "<computed>" access_ip_v6: "" => "<computed>" availability_zone: "" => "AZ1" flavor_id: "" => "2" flavor_name: "" => "<computed>" image_id: "" => "<computed>" image_name: "" => "CentOS-DevOPS-v2.4" key_pair: "" => "my_keypair" name: "" => "web-02" network.#: "" => "1" network.0.fixed_ip_v4: "" => "<computed>" network.0.fixed_ip_v6: "" => "<computed>" network.0.mac: "" => "<computed>" network.0.name: "" => "my_network" network.0.port: "" => "<computed>" network.0.uuid: "" => "<computed>" security_groups.#: "" => "1" security_groups.3814588639: "" => "default" user_data: "" => "67b4a89214eb5ecc368e8dbec1bd4bba566cc78d" volume.#: "" => "<computed>" Plan: 2 to add, 0 to change, 0 to destroy.

Here we see what resources will be created, where <computed> appears – the resources will be created upon instantiation. The last line details that two resources will be created. Since this is first time that they are going to be created, nothing will be changed, or destroyed.

After deployment you can see that there are two instances, each with Apache running and their default page populated.

$ curl http://192.168.100.56 <html> <body> <p>hostname is: web-01</p> </body> </html> $ curl http://192.168.100.57 <html> <body> <p>hostname is: web-02</p> </body> </html>

Of course cleaning up afterwards is just running another command:

terraform destroy Do you really want to destroy? Terraform will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes openstack_compute_instance_v2.web.0: Refreshing state... (ID: 783cbddf-7cbd-4b56-808d-01a6b05d8f03) openstack_compute_instance_v2.web.1: Refreshing state... (ID: 0b90d987-f339-47c9-9d83-a78ffb7234ca) openstack_compute_instance_v2.web.0: Destroying... openstack_compute_instance_v2.web.1: Destroying... openstack_compute_instance_v2.web.1: Destruction complete openstack_compute_instance_v2.web.0: Destruction complete Apply complete! Resources: 0 added, 0 changed, 2 destroyed.

Summary

Is Terraform a full replacement for Heat? Due to the fact there are a number of resources that are not available at the moment in Terraform, it doesnít seem so. However, Terraform is a powerful provisioning tool and it has the option to interact with multiple cloud providers and other solutions thus providing a complete infrastructure solution.

This post first appeared on Stratoscale’s blog.

Superuser is always interested in opinion pieces and how-tos. Please get in touch: [email protected]

Cover Photo // CC BY NC