Automate AWS Cloud Infrastructure with Terraform

This blog is for those who works on scalable cloud infrastructure and automating repetitive tasks.We have tools like Terraform that allow us to turn a little bit of code into something that can plan, deploy, modify, and destroy all of our systems. If we’re able to get it working, we’ll also need to make some changes to each system, such as modifying the disk size and memory, so that our client isn’t wasting money on unused resources.
Instead of modifying an existing system using SSH, which is a mutable process, your systems are rebuilt from a well-reviewed template, validated for correctness, and then deployed if they pass all the required checks. This is what’s called “immutable infrastructure”. 
Let’s get started with defining some terms and technology:
  • Terraform: a tool used to turn infrastructure development into code.
  • AWSCLI: command line utility for managing AWS Cloud resources.
So, why do we want to use Terraform? Because doing things manually is inefficient, sometimes boring, and could also lead to misconfigurations and costly mistakes. We also want to be able to spend more time focusing on more important things, such as the security of our services, our product’s features, and things of that nature.

Setup AWS CLI
###############
[root@localhost ~]# yum install python-pip
[root@localhost ~]# pip install awscli boto3
[root@localhost ~]# export AWS_ACCESS_KEY_ID=<your-key-here>
[root@localhost ~]# export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>

Use terraform to setup AWS infrastructure
#####################################

Create a directory then create a file main.tf
#####################################
[root@localhost ~]# cd AWSterra/
[root@localhost AWSterra]# ls
main.tf
[root@localhost AWSterra]# vim main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami = "ami-a4dc46db"
  instance_type = "t2.micro"

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, World" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF
  tags {
    Name = "terraform-example"
  }
}

The first command to run for a new configuration -- or after checking out an existing configuration from version control -- is terraform init, which initializes various local settings and data that will be used by subsequent commands.
Initialize terraform
################
[root@localhost AWSterra]# terraform init 
Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 1.25"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Now plan the execution
#####################
[root@localhost AWSterra]# terraform plan
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.
------------------------------------------------------------------------
Now run terraform apply to see how Terraform will apply the configuration to create resources.
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:
  + aws_instance.example
      id:                           <computed>
      ami:                          "ami-a4dc46db"
      associate_public_ip_address:  <computed>
      availability_zone:            <computed>
      ebs_block_device.#:           <computed>
      ephemeral_block_device.#:     <computed>
      get_password_data:            "false"
      instance_state:               <computed>
      instance_type:                "t2.micro"
      ipv6_address_count:           <computed>
      ipv6_addresses.#:             <computed>
      key_name:                     <computed>
      network_interface.#:          <computed>
      network_interface_id:         <computed>
      password_data:                <computed>
      placement_group:              <computed>
      primary_network_interface_id: <computed>
      private_dns:                  <computed>
      private_ip:                   <computed>
      public_dns:                   <computed>
      public_ip:                    <computed>
      root_block_device.#:          <computed>
      security_groups.#:            <computed>
      source_dest_check:            "true"
      subnet_id:                    <computed>
      tags.%:                       "1"
      tags.Name:                    "terraform-example"
      tenancy:                      <computed>
      user_data:                    "c765373c563b260626d113c4a56a46e8a8c5ca33"
      volume_tags.%:                <computed>
      vpc_security_group_ids.#:     <computed>
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Now run terraform apply to see how Terraform will apply the configuration to create resources. ###############################################################################[root@localhost AWSterra]# terraform apply
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:
  + aws_instance.example
      id:                           <computed>
      ami:                          "ami-a4dc46db"
      associate_public_ip_address:  <computed>
      availability_zone:            <computed>
      ebs_block_device.#:           <computed>
      ephemeral_block_device.#:     <computed>
      get_password_data:            "false"
      instance_state:               <computed>
      instance_type:                "t2.micro"
      ipv6_address_count:           <computed>
      ipv6_addresses.#:             <computed>
      key_name:                     <computed>
      network_interface.#:          <computed>
      network_interface_id:         <computed>
      password_data:                <computed>
      placement_group:              <computed>
      primary_network_interface_id: <computed>
      private_dns:                  <computed>
      private_ip:                   <computed>
      public_dns:                   <computed>
      public_ip:                    <computed>
      root_block_device.#:          <computed>
      security_groups.#:            <computed>
      source_dest_check:            "true"
      subnet_id:                    <computed>
      tags.%:                       "1"
      tags.Name:                    "terraform-example"
      tenancy:                      <computed>
      user_data:                    "c765373c563b260626d113c4a56a46e8a8c5ca33"
      volume_tags.%:                <computed>
      vpc_security_group_ids.#:     <computed>
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes
aws_instance.example: Creating...
  ami:                          "" => "ami-a4dc46db"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  get_password_data:            "" => "false"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  password_data:                "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "<computed>"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "<computed>"
  tags.%:                       "" => "1"
  tags.Name:                    "" => "terraform-example"
  tenancy:                      "" => "<computed>"
  user_data:                    "" => "c765373c563b260626d113c4a56a46e8a8c5ca33"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Still creating... (20s elapsed)
aws_instance.example: Creation complete after 30s (ID: i-0d4605bf2906e7e87)
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Terraform also wrote some data into the terraform.tfstate file. This state file is extremely important; it keeps track of the IDs of created resources so that Terraform knows what it is managing. This file must be saved and distributed to anyone who might run Terraform. It is generally recommended to setup remote state when working with Terraform, to share the state automatically, but this is not necessary for simple situations like this Getting Started guide.

Inspect the current state using terraform show:
#######################################
[root@localhost AWSterra]# terraform show
aws_instance.example:
  id = i-0d4605bf2906e7e87
  ami = ami-a4dc46db
  associate_public_ip_address = true
  availability_zone = us-east-1a
  credit_specification.# = 1
  credit_specification.0.cpu_credits = standard
  disable_api_termination = false
  ebs_block_device.# = 0
  ebs_optimized = false
  ephemeral_block_device.# = 0
  get_password_data = false
  iam_instance_profile = 
  instance_state = running
  instance_type = t2.micro
  ipv6_addresses.# = 0
  key_name = 
  monitoring = false
  network_interface.# = 0
  network_interface_id = eni-0f1dc3509e90c14a2
  password_data = 
  placement_group = 
  primary_network_interface_id = eni-0f1dc3509e90c14a2
  private_dns = ip-172-31-92-100.ec2.internal
  private_ip = 172.31.92.100
  public_dns = ec2-52-55-147-136.compute-1.amazonaws.com
  public_ip = 52.55.147.136
  root_block_device.# = 1
  root_block_device.0.delete_on_termination = true
  root_block_device.0.iops = 100
  root_block_device.0.volume_id = vol-04c93e404bff05000
  root_block_device.0.volume_size = 8
  root_block_device.0.volume_type = gp2
  security_groups.# = 1
  security_groups.3814588639 = default
  source_dest_check = true
  subnet_id = subnet-74cb135a
  tags.% = 1
  tags.Name = terraform-example
  tenancy = default
  user_data = c765373c563b260626d113c4a56a46e8a8c5ca33
  volume_tags.% = 0
  vpc_security_group_ids.# = 1
  vpc_security_group_ids.3395900001 = sg-46ed580d

Now go to your AWS EC2 page to check the instance is running or not
############################################################


Now you can also completely destroy the Terraform-managed infrastructure.
Destroying your infrastructure is a rare event in production environments. But if you're using Terraform to spin up multiple environments such as development, test, QA environments, then destroying is a useful action.
Resources can be destroyed using the terraform destroy command, which is similar to terraform apply but it behaves as if all of the resources have been removed from the configuration.
To destroy managed infrastructure
##################################
[root@localhost AWSterra]# terraform destroy 
aws_instance.example: Refreshing state... (ID: i-0d4605bf2906e7e87)
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy
Terraform will perform the following actions:
  - aws_instance.example
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.
  Enter a value: yes
aws_instance.example: Destroying... (ID: i-0d4605bf2906e7e87)
aws_instance.example: Still destroying... (ID: i-0d4605bf2906e7e87, 10s elapsed)
aws_instance.example: Still destroying... (ID: i-0d4605bf2906e7e87, 20s elapsed)
aws_instance.example: Still destroying... (ID: i-0d4605bf2906e7e87, 30s elapsed)
aws_instance.example: Still destroying... (ID: i-0d4605bf2906e7e87, 40s elapsed)
aws_instance.example: Still destroying... (ID: i-0d4605bf2906e7e87, 50s elapsed)
aws_instance.example: Destruction complete after 57s
Destroy complete! Resources: 1 destroyed.


Post a Comment

0 Comments