Since I started learning to program the field of Dev Ops has been the area I've found fascinating. In January I attended a DevOps Exchange meetup where a member of Sainsbury's Dev Ops team presented on Terraform and decided I'd try it to manage some personal infrastructure. The talk is available for free on the Blog along with an extremely entertaining presnetaiton from my friend Simon Vans-Colina on how to build a bank.

Terraform is a piece of software developed by Hashicorp that lets you describe infrastructure as code. In their own words:

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently.

The advantages of this are manifold; it allows you to create, modify and in case of failure roll back to known working infrastructure. When combined with code version control tool's like Git this together with configuration management tools like Ansible and Puppet gives a level of control over servers that just isn't possible with manual administration.

I've been trying Terraform with AWS to build and tear down servers. In the coming weeks I plan to combine these with Ansible playbooks to be able to repeatable build working infrastructure. The Terraform scripts and Ansible playbooks are held in Bitbucket so I have version control.

Terraform scripts are described using flat text tiles with a .tf suffix.

Getting Terraform to play with AWS is a little tricky, the safest way I've found is to install the AWS CLI tool and use that to create a credentials file to manage API keys. To then tell Terraform to use AWS and the relevant API information I added the following to the start of the file:

provider "aws" {
    shared_credentials_file = "/home/$user/.aws/credentials"
    region = "us-east-1"

This tells Terraform that I want to build infrastructure on AWS, to use the AWS CLI credentials file for API keys and which region I want the servers to be in.

I can then describe the infrastructure I'd like Terraform to build. In this case an Ubuntu 14.04 server I plan to use as an Open VPN server.

resource "aws_instance" "$AWS instance name" {
    ami = "ami-408c7f28"
    instance_type = "t2.micro"
    key_name = "$SSH key"
    tags {
        name = "$server name"
        description = "$description"

This brief piece of code tells AWS I would like an instance of type t2.micro which is the only size that is free to use on AWS's free tier. These are fine for the type of personal use I intend them for and have 1 CPU core and 1 Gb of RAM. Plenty for an Open VPN server with one user. The ami variable lets you set the OS from pre built AWS images, in this case Ubuntu 14.04 Server. The key_name variable allows you to select an SSH key so you can log in.

There are a whole raft of other variables you can use and these can be found in the excellent documentaion provided by Hashicorp.

With this you should be able to provision your server. However before you push the button Terraform lets you test your configuration to see what your script will do before you start spinning up servers. You can do this using the command:

terraform plan

This then looks at Terraform's state, checks if any changes will be made and notifies you in the terminal. If everything looks good you can use:

terraform apply

This will then run through your script and build the servers.

There is a lot to learn with Terraform, it is extremely powerful and in concert with proper configuration management allows you to build, configure and manage your cloud infrastructure all from scripts you can version using something like Git. This makes everything you do repeatable and consistent and more to the point allows you to build an applications infrastructure with only a couple of commands.

This is to my mind at least extremely cool.


comments powered by Disqus