Tuesday, March 15, 2016

AWS Terraform

If you ever had to manage AWS Amazon environment you probably start by clicking through AWS console - Web GUI, then you quickly realize that it won't scale, because all your clicks are not repeatable and there is no code review of some sort.

Next logical step it to use aws cli, but then you'd need to create a bunch of scripts to manage it.  There are a couple of options for scalable and systematic approach - one is Cloud Formation from Amazon, another cool solution is Terraform.

Terraform allows you to manage pretty much any AWS resource from a single configuration file that could be sitting in your GIT repo.  This is truly "infrastructure as a code" solution.

Here is an example of how to create a simple ec2 instance with your parameters.

resource "aws_instance" "my-server" {
    ami                         = "ami-93742ea3"
    availability_zone           = "us-west-2a"
    ebs_optimized               = false
    instance_type               = "t2.micro"
    monitoring                  = false
    key_name                    = "your-ssh-access-key"
    subnet_id                   = "subnet-99999999"
    security_group_ids      = ["sg-ae33333", "sg-bb33333"]
    associate_public_ip_address = true
    private_ip                  = "10.10.10.50"
    source_dest_check           = true

    root_block_device {
        volume_type           = "gp2"
        volume_size           = 10
        iops                  = 30
        delete_on_termination = true
    }

    tags {
        "Name" = "my-server"
    }
}

As you can see above, some values like subnet and security group are hardcoded since we are dealing with existing infrastructure, and those resources were created by hand.

It's easy enough to refactor those into a separate file called "variables.tf", so that you could at least use them by readable human names.

variable "access_key" {}
variable "secret_key" {}
# Default AWS region is West
variable "aws_region" {
  default = "us-west-2"
}
# Security Groups
variable "sg" {
    default = {
        internal_ping = "sg-0444444"
        internal_ssh = "sg-444444444"
   }
}

Now you can start using those variables and you terraform template will be more readable
  security_group_id      = "${var.sg.internal_ping},${var.sg.internal_ssh},${var.sg.internal_http}"

Here is another example on how Terraform can manage a single DNS entry assuming that you have all your zones in that variables.tf file
resource "aws_route53_record" "my-server-A" {
    zone_id = "${var.dns_zone.company_com}"
    name    = "my-server.company.com"
    type    = "A"
    records = ["10.10.10.50"]
    ttl     = "600"
}