Getting Started With Terraform & Azure

Getting Started With Terraform & Azure

November 25, 2017 Off By kex

Terraform is a way of declaratively configuring infrastructure in various cloud platforms. Some benefits are listed below:

  • Solid team behind the project (the same team behind Vagrant/Packer)
  • Integrates well with version control systems
  • Simple and easily readable DSL
  • Clearly defined and straightforward functionality

 

A example Terraform instruction set could look like this:

Use AzureRM

Login with account 'Admin'

Create a Virtual Network

Create a Virtual Machine from an image

Add the VM to this subnet

Create a Network Security Group

Add the Network Security Group to the Virtual Network

Although the actual syntax is a bit more complicated, this is the fundamental usage of Terraform. As far as deployment tools go it is relatively intelligent, you can link components together in the configuration file, implement dependencies and rely on the tool itself to do things in the right order.

Installation

To get started we will install Terraform, there are packages avaliable for most Linux distros, for the Windows installation just download the executable and add it to your PATH environment. After this we need to create our project directory, create a project direcotry ‘Azure Intro’, in this directory we will have two files, ‘deploy.tf’ and ‘providers.tf’. All files used by Terraform end with the ‘.tf’ extension.

Getting Started

I’ve pasted below an example configuration for ‘deploy.tf’, this configuration should be self explanatory to anyone with any experience using Azure. The documentation for these resources can be found here, the documentation is quite clear so you should be able to pick it up quickly.

resource "azurerm_resource_group" "prod" {
  name     = "PROD-WEB"
  location = "UK West"
}

resource "azurerm_network_security_group" "prod" {
    name                        = "PROD-NSG"
    resource_group_name 	=	"${azurerm_resource_group.prod.name}"
    location                    = "UK West"
}

resource "azurerm_virtual_network" "prod" {
    name 			= "PROD-VNET"
    address_space		= ["10.0.0.0/16"]
    location		        = "UK West"
    resource_group_name 	= "${azurerm_resource_group.prod.name}"

	subnet {
		name 		= "PROD"
		address_prefix 	= "10.0.1.0/24"
		security_group  = "${azurerm_network_security_group.prod.id}"
		}
}

resource "azurerm_sql_server" "prod" {
    name                          = "example-prod-sql" 
    resource_group_name           = "${azurerm_resource_group.prod.name}"
    location                      = "UK West"
    version                       = "12.0"
    administrator_login           = "steve"
    administrator_login_password  = "j-89d6dha__9d6d9ncv8.eu"
}

resource "azurerm_sql_database" "prod" {
    name                = "PROD-SQL"
    resource_group_name = "${azurerm_resource_group.prod.name}"
    location            = "UK West"
    server_name         = "${azurerm_sql_server.prod.name}"
}

The template above will create as follows:

  • A Resource Group that all resources will be added to called ‘PROD-WEB’
  • A Network Security Group which will be attached to the PROD subnet
  • A Virtual Network called ‘PROD-VNET’ with a /16 subnet on 10.0.0.0
  • An Azure SQL Instance called ‘example-prod-sql’
  • A SQL database within the Azure SQL instance called ‘PROD-SQL’

The ‘providers.tf’ file contains the provider definition, which as we know is Azure:

provider "azure" {
  publish_settings = "${file("credentials.publishsettings")}"
}

Now that we’ve created the project files we need to initialize the terraform project, since Terraform is a command line tool we need to use CMD on Windows or a shell such as bash on Linux. For the sake of this tutorial I am using windows so I will proceed using cmd.

Open CMD and browse to the project directory, then run terraform init

This will create a .terraform directory in the project directory containing various files and dependancies (these dependancies are also downloaded during the init process). Next we need to test our Terraform configuration before we commit it to our Azure Subscription, to do this run: the terraform plan command.

If you havn’t authenticated to the Azure CLI, you will be prompted to do so. To do this just run az login and follow the steps listed, this will enable you to use your Azure account to deploy directly to your subscription (there are better ways to do this, however this will do for now). After you’ve authenticated and run terraform plan you should see output similar to this:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

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:

  + azurerm_network_security_group.prod
      id:                                
      location:                          "ukwest"
      name:                              "PROD-NSG"
      resource_group_name:               "PROD-WEB"
      security_rule.#:                   
      tags.%:                            

  + azurerm_resource_group.prod
      id:                                
      location:                          "ukwest"
      name:                              "PROD-WEB"
      tags.%:                            

  + azurerm_sql_database.prod
      id:                                
      collation:                         
      create_mode:                       "Default"
      creation_date:                     
      default_secondary_location:        
      elastic_pool_name:                 
      encryption:                        
      location:                          "ukwest"
      max_size_bytes:                    
      name:                              "PROD-SQL"
      requested_service_objective_id:    
      resource_group_name:               "PROD-WEB"
      restore_point_in_time:             
      server_name:                       "example-prod-sql"
      source_database_deletion_date:     
      source_database_id:                
      tags.%:                            

  + azurerm_sql_server.prod
      id:                                
      administrator_login:               "steve"
      administrator_login_password:      
      fully_qualified_domain_name:       
      location:                          "ukwest"
      name:                              "example-prod-sql"
      resource_group_name:               "PROD-WEB"
      tags.%:                            
      version:                           "12.0"

  + azurerm_virtual_network.prod
      id:                                
      address_space.#:                   "1"
      address_space.0:                   "10.0.0.0/16"
      location:                          "ukwest"
      name:                              "PROD-VNET"
      resource_group_name:               "PROD-WEB"
      subnet.#:                          "1"
      subnet.~3693620554.address_prefix: "10.0.1.0/24"
      subnet.~3693620554.name:           "PROD"
      subnet.~3693620554.security_group: "${azurerm_network_security_group.prod.id}"
      tags.%:                            


Plan: 5 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

As you can see running this plan will create the aforementioned resources and tie them together where specified (subnets into VNET, NSG to subnet for example).

The next step is to push this into live, to do this we run terraform apply, the output of this command will show you exactly what stage terraform is at in the deployment process. After the command is finished running you should see the resources in your Azure Portal like so:

Post terraform deployment

Let’s say we wanted to rename the SQL Database we created, in the deploy.tf file just change the ‘name’ field of the “azurerm_sql_database” resource to ‘LIVE-SQL’, and run terraform apply. You should see output like this:

Amending names

As you can see it deletes the original resource and re-deploys it with the new and updated name. This should be reflected in your portal view (remember to refresh it).

Now that we’ve proved that we can deploy directly to Azure with Terraform we should delete the resources we just created, this will avoid unnecessary spends. To delete everything we just implemented run terraform destroy then type yes when prompted, this will delete everything we created, including the resource group. It’s worth checking the changes are reflected in your Azure Portal to avoid any potential unwanted costs.