Terraform – Classroom Series – 20/Sep/2019

How to make terraform Scripts Generic

Our Scenario

In the case of sample architecuture, i have created the following variables in a file called as vars.tf

# required variable accesskey
variable "accesskey" {
    type = "string"
}

# required variable secretkey
variable "secretkey" {
    type = "string"
}

# optional region
variable "region" {
    type = "string"
    default = "eu-west-3"
}

variable "subnet1az" {
    type    = "string"
    default = "eu-west-3a"
}


variable "subnet2az" {
    type    = "string"
    default = "eu-west-3b"
}



# optional ami-id
variable "appserverami" {
    type    = "string"
    default = "ami-0ad37dbbe571ce2a1"
  
}

variable "awskeypair" {
    type    = "string"
    default = "forterraform"
  
}

variable "sshusername" {
    type    = "string"
    default = "ubuntu"
  
}

variable "sshkeypath" {
    type    = "string"
    default = "./forterraform.pem"
  
}

Using Variables in terraform resources/providers/outputs

  • Basic Syntax: "${var.<variablename>}"

Lets Examine our Provider

provider "aws" {
   region       = "${var.region}"
   access_key   = "${var.accesskey}"
   secret_key   = "${var.secretkey}"
}

Lets Examine Our Resources

resource "aws_vpc" "my_network" {
    cidr_block              = "10.10.0.0/16"
    enable_dns_hostnames    = true
    tags = {
        Name = "openmrs"
    }
}

resource "aws_subnet" "subnet_1" {
    cidr_block              = "10.10.0.0/24"
    vpc_id                  = "${aws_vpc.my_network.id}"
    availability_zone       = "${var.subnet1az}"
    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_subnet" "subnet_2" {
    cidr_block              = "10.10.1.0/24"
    vpc_id                  = "${aws_vpc.my_network.id}"
    availability_zone       = "${var.subnet2az}"
    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_internet_gateway" "my_igw" {
    vpc_id      = "${aws_vpc.my_network.id}"
    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_route_table" "my_rt" {
    vpc_id = "${aws_vpc.my_network.id}"

    route {
        cidr_block  = "0.0.0.0/0"
        gateway_id  = "${aws_internet_gateway.my_igw.id}"
    }

    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_security_group" "my_sg" {
    name            = "my_sg"
    description     = "created from terraform"
    vpc_id          = "${aws_vpc.my_network.id}"
    ingress{
        cidr_blocks = ["0.0.0.0/0"]
        protocol    = "-1"
        from_port   = "0"
        to_port     = "0"
    }
    egress{
        cidr_blocks = ["0.0.0.0/0"]
        protocol    = "-1"
        from_port   = "0"
        to_port     = "0"
    }
    tags = {
        Name = "openmrs"
    }
}

resource "aws_route_table_association" "subnet1assoc" {
    subnet_id       = "${aws_subnet.subnet_1.id}"
    route_table_id  = "${aws_route_table.my_rt.id}"
  
}

resource "aws_route_table_association" "subnet2assoc" {
    subnet_id       = "${aws_subnet.subnet_2.id}"
    route_table_id  = "${aws_route_table.my_rt.id}"
  
}

resource "aws_instance" "web1" {
    ami                         = "${var.appserverami}"
    instance_type               = "t2.micro"
    subnet_id                   = "${aws_subnet.subnet_1.id}"
    associate_public_ip_address = true
    vpc_security_group_ids      = [ "${aws_security_group.my_sg.id}" ]
    key_name                    = "${var.awskeypair}"
    tags = {
        Name = "openmrs"
    }
  
}


resource "aws_instance" "web2" {
    ami                         = "${var.appserverami}"
    instance_type               = "t2.micro"
    subnet_id                   = "${aws_subnet.subnet_2.id}"
    associate_public_ip_address = true
    vpc_security_group_ids      = [ "${aws_security_group.my_sg.id}" ]
    key_name                    = "${var.awskeypair}"
    tags = {
        Name = "openmrs"
    }
  
}


The commands used to create infra

terraform validate -var 'accesskey=<your access key>' -var 'secretkey=<yoursecretkey>' .
terraform apply -var 'accesskey=<your access key>' -var 'secretkey=<yoursecretkey>' .

What is that we have acheived so far

  • We were able to create ec2 machines and generalize the behavior.
  • Now we can use this script to create ec2 machines in any account & also in any region

We need to install tomcat

  • To do installations , we need to do provisioning
  • Terraform Provisioning more info is available here
  • To acheive our architecture we need to
    • login into ec2 machines => This is acheived by using Terraform Provisioner Connections
    • install tomcat => Can be acheived in different ways, in this example i would be shell script/linux commands (You can use ansible/chef)

Lets look at the script in Terraform to create two ec2 machines & install tomcat

# required variable accesskey
variable "accesskey" {
    type = "string"
}

# required variable secretkey
variable "secretkey" {
    type = "string"
}

# optional region
variable "region" {
    type = "string"
    default = "eu-west-3"
}

variable "subnet1az" {
    type    = "string"
    default = "eu-west-3a"
}


variable "subnet2az" {
    type    = "string"
    default = "eu-west-3b"
}



# optional ami-id
variable "appserverami" {
    type    = "string"
    default = "ami-0ad37dbbe571ce2a1"
  
}

variable "awskeypair" {
    type    = "string"
    default = "forterraform"
  
}

variable "sshusername" {
    type    = "string"
    default = "ubuntu"
  
}

variable "sshkeypath" {
    type    = "string"
    default = "./forterraform.pem"
  
}



provider "aws" {
   region       = "${var.region}"
   access_key   = "${var.accesskey}"
   secret_key   = "${var.secretkey}"
}


resource "aws_vpc" "my_network" {
    cidr_block              = "10.10.0.0/16"
    enable_dns_hostnames    = true
    tags = {
        Name = "openmrs"
    }
}

resource "aws_subnet" "subnet_1" {
    cidr_block              = "10.10.0.0/24"
    vpc_id                  = "${aws_vpc.my_network.id}"
    availability_zone       = "${var.subnet1az}"
    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_subnet" "subnet_2" {
    cidr_block              = "10.10.1.0/24"
    vpc_id                  = "${aws_vpc.my_network.id}"
    availability_zone       = "${var.subnet2az}"
    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_internet_gateway" "my_igw" {
    vpc_id      = "${aws_vpc.my_network.id}"
    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_route_table" "my_rt" {
    vpc_id = "${aws_vpc.my_network.id}"

    route {
        cidr_block  = "0.0.0.0/0"
        gateway_id  = "${aws_internet_gateway.my_igw.id}"
    }

    tags = {
        Name = "openmrs"
    }
  
}

resource "aws_security_group" "my_sg" {
    name            = "my_sg"
    description     = "created from terraform"
    vpc_id          = "${aws_vpc.my_network.id}"
    ingress{
        cidr_blocks = ["0.0.0.0/0"]
        protocol    = "-1"
        from_port   = "0"
        to_port     = "0"
    }
    egress{
        cidr_blocks = ["0.0.0.0/0"]
        protocol    = "-1"
        from_port   = "0"
        to_port     = "0"
    }
    tags = {
        Name = "openmrs"
    }
}

resource "aws_route_table_association" "subnet1assoc" {
    subnet_id       = "${aws_subnet.subnet_1.id}"
    route_table_id  = "${aws_route_table.my_rt.id}"
  
}

resource "aws_route_table_association" "subnet2assoc" {
    subnet_id       = "${aws_subnet.subnet_2.id}"
    route_table_id  = "${aws_route_table.my_rt.id}"
  
}

resource "aws_instance" "web1" {
    ami                         = "${var.appserverami}"
    instance_type               = "t2.micro"
    subnet_id                   = "${aws_subnet.subnet_1.id}"
    associate_public_ip_address = true
    vpc_security_group_ids      = [ "${aws_security_group.my_sg.id}" ]
    key_name                    = "${var.awskeypair}"
    tags = {
        Name = "openmrs"
    }

    connection {
        type        = "ssh"
        user        = "${var.sshusername}"
        private_key = "${file(var.sshkeypath)}"
        host        = "${aws_instance.web1.public_ip}"
    }

    provisioner "remote-exec" {
        inline  = [
            "sudo apt-get update",
            "sudo apt-get install openjdk-8-jdk -y",
            "sudo apt-get install tomcat8 -y"

        ]
    }
  
}


resource "aws_instance" "web2" {
    ami                         = "${var.appserverami}"
    instance_type               = "t2.micro"
    subnet_id                   = "${aws_subnet.subnet_2.id}"
    associate_public_ip_address = true
    vpc_security_group_ids      = [ "${aws_security_group.my_sg.id}" ]
    key_name                    = "${var.awskeypair}"
    tags = {
        Name = "openmrs"
    }

    connection {
        type        = "ssh"
        user        = "${var.sshusername}"
        private_key = "${file(var.sshkeypath)}"
        host        = "${aws_instance.web2.public_ip}"
    }

    provisioner "remote-exec" {
        inline  = [
            "sudo apt-get update",
            "sudo apt-get install openjdk-8-jdk -y",
            "sudo apt-get install tomcat8 -y"

        ]
    }
  
}


output "webserver1-ip" {
  value = "${aws_instance.web1.public_ip}"
}

output "webserver2-ip" {
  value = "${aws_instance.web2.public_ip}"
}


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About continuous learner

devops & cloud enthusiastic learner