Who am I

Adam Burnett

  • 15+ years of professional software development
  • Former Architect @ Cox Automotive in charge of internal tooling and infrastructure teams
  • Currently consulting on AWS and backend development
  • Father, mountain biker, skier

Terraform

Terraform is a tool from HashiCorp (makers of Vagrant) that allows you to codify your infrastructure into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.

Use it for:

  • Software defined networking
  • Multi-tier apps
  • Disposable Environments
  • Multi-provider deployments
  • https://www.terraform.io/intro/use-cases.html

What can I Configure

Lots!

DevOps? - You Bet!

Traditional infrastructure work is done by a team other than the feature development team. At best this work follows a different process from the rest of the application. At worst it is entirely manual.

Using an IaC tool makes creating an entirely self contained team possible. Infrastructure provisioning can now follow the same release process as the rest of the software. This is the heart and sole of DevOps!

Configuration

Configuration syntax: HCL

variable "aws_region" { default = "us-east-1" }

resource "aws_instance" "web" {
    count = "${var.enabled ? 1 : 0}"
	instance_type = "m1.small"
	ami = "${lookup(var.aws_amis, var.aws_region)}"
	vpc_security_group_ids = ["sg1234", "sg5678"]
	tags {
		"MyTag" = "foobar"
	}
}
							

Resources

A Resource represents a component of your infrastructure. This could be a VM instance, firewall rule, user permission, networking configuration, etc.

A resource consists of a name, type and configuration and is specific to a provider.


resource "aws_instance" "web" {
	#     ^^^type^^^    ^name
	# configuration
	instance_type = "m1.small"
	...
}
							

Resources

Resources have inputs and outputs. Outputs can be ref

Resources

Resources have inputs and outputs. Outputs can be referenced to create implicit dependencies between resources. Terraform will ensure correct resource creation / destruction order.

resource "aws_security_group" "global-egress" {
  name        = "global-egress"
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  vpc_security_group_ids = ["${aws_security_group.global-egress.id}"]
  ...
}

							

Resources

Multiples of a resource can be created via a "count". The index of the instance can be used control values on a per-instance basis where needed.

variable "instance_ips" {
  default = {
    "0" = "10.11.12.100"
    "1" = "10.11.12.101"
    "2" = "10.11.12.102"
  }
}

resource "aws_instance" "app" {
  count = "3"
  private_ip = "${lookup(var.instance_ips, count.index)}"
  # ...
}
							

More about count

Resources with a count are referenced by index.

${aws_instance.app.0.id} # the first one
${aws_instance.app.*.id} # all of them
							

Referencing all instances with *

resource "aws_elb" "web" {
  instances       = ["${aws_instance.app.*.id}"]
}
							

Provisioners

Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction. Provisioners can be used to bootstrap a resource, cleanup before destroy, run configuration management, etc.

resource "aws_instance" "app" {
  ...
  provisioner "remote-exec" {
    inline = [
     "apt-get update",
     "consul join ${aws_instance.web.private_ip}",
    ]
  }
}
							

Connections via SSH and WinRM supported.

Providers

A provider is what manages the resources you define. The provider name will match the prefix of the resource name.

Providers are defined in the terraform configuration.

provider "aws" {
    access_key = "foo"
    secret_key = "bar"
    region = "us-east-1"
}

provider "digitalocean" {
  token = "${var.do_token}"
}
							

Demo Time

State

Terraform must store state containing its view of your managed infrastructure. This state is used to create the plan for applying changes.

There is an in-depth explination on why this state is needed on the Terraform site at https://www.terraform.io/docs/state/purpose.html

State

State can be stored in a local file or in a remote store. How you plan on using Terraform and integrating it into your organization will determine your best course of action.

Remote Data Stores

  • S3 (w/ DynamoDB for locking)
  • Artifactory
  • Azure
  • gcs
  • http (roll your own)
  • ...and more

State

State can be inspected with terraform show and terraform console.

Secrets will be in plain text!

Locking?

For one developer using local state committed to source control is good enough. But what if you have a team? Multiple people applying changes at the same time can corrupt the state.

As of Terraform 0.9 there is native support for locking the state in a backend. This will allow only one change at a time to be applied.

3rd party tools like Terragrunt have sprung up to help manage organizational issues that arise with integrating Terraform into the enterprise.

Demo Time!

- look at a local state file - terraform show - show how to init a remote state

Data Sources

TBD: talk about state as a data source

Modules

Modules are used to create reusable components in Terraform as well as for basic code organization.

Modules are most useful when defined with input and output parameters. This allows you to create generic components that can be imported into any configuration.

Ok, let's just look at one...

Modules

Modules can be referenced locally or imported from source control.

Collection of terraform community modules can be found at https://github.com/terraform-community-modules