Infrastructure as Code

Photo by Jan Huber on Unsplash

Infrastructure as Code

Streamlining Infrastructure Provisioning and Migration with Terraform

Introduction:

This blog provides an introduction to using Terraform for infrastructure provisioning and migration across different cloud providers. It highlights the benefits of Infrastructure as Code (IaC) and explains how Terraform can be used as a tool to automate the deployment and management of resources. The blog also includes a step-by-step guide on getting started with Terraform, including installing Terraform, writing Terraform files, and executing the Terraform commands. By the end, readers will have a basic understanding of how to use Terraform to define and manage their infrastructure on various cloud platforms.

What Is The Problem?

For example, if a company (let's call it XYZ) is currently using AWS as its cloud provider and has automated its DevOps operations using AWS CloudFormation Template (CFT), it will need to develop new scripts and automation tools if they decide to migrate their resources to Microsoft Azure, as the current ones are specific to AWS.

Moreover, in modern operating systems, large institutes are opting for hybrid cloud solutions, which involve using different cloud service providers to fulfill different requirements.

Infrastructure as Code (IaC) is the practice of managing and provisioning computing infrastructure using machine-readable definition files, rather than manual configuration. By using IaC, organizations can automate the process of deploying and managing their infrastructure, which can lead to more efficient and reliable systems.

We can use Terraform to define and manage cloud infrastructure resources across multiple cloud providers, such as AWS, Azure, and Google Cloud Platform. The Terraform code describes the desired state of the infrastructure and the tool manages the provisioning and deployment of resources to achieve that state. This allows for a consistent and reproducible infrastructure environment across different cloud providers and deployment environments.

Solution Offered Using Terraform:

As discussed above, migration of resources from one platform to another using the traditional method is time-consuming and prone to errors, and highly inefficient. Engineers are required to learn multiple tools and technologies for the task of migration. All this is solved by the introduction of a tool named Terraform in which this migration process is very smooth and efficient as compared to the traditional method. Terraform offers API as code in which under the hood terraform will talk with the API of different cloud providers and the details provided by the user, will be converted into the format of the target cloud-providing platform. Let's say you are choosing to use an AWS cloud provider then you will have to give your specification to Terraform and Terraform will convert this specification which is acceptable and understandable to the AWS platform and you will be getting your requirement ready. This is the process used by Terraform to create user-requited resources in multiple platforms easily and efficiently.

We can say that Terraform is the middleman between the user and the API of cloud providing platform In simple words instead of directly talking with AIP user uses Terraform modules which ultimately talk with APIs of respective cloud providers and the task that are requested by the user are performed. This is how Terraform utilizes API as a core concept.

Getting Started With Terraform:

Before actually getting our hands over Terraform to deal with a cloud provider platform we need to take into consideration that Terraform does what we ask it to do on our behalf so we must test our code or let's say requirements before posting them to the cloud platform using Terraform. For this Terraform provides a DRY RUN facility. The dry run helps us understand what are the steps that are going to take place so that we can rectify our mistakes beforehand and avoid future problems.

Installing Terraform on EC2 instance:

Terraform mainly works on four commands which are:

  • terraform init (initialize)

  • terraform plan (Dry run)

  • terraform apply

  • terraform destroy

Writing Terraform File:

  • Terraform file is the file that contains all the necessary configurations which are required by the user to be configured on a target cloud platform. This file has an extension of .tf and it contains the following structure:

      terraform {
        required_providers {
          aws = {
            source  = "hashicorp/aws"
            version = "~> 4.16"
          }
        }
    
        required_version = ">= 1.2.0"
      }
    
      provider "aws" {
        region  = "us-east-1"
      }
    
      resource "aws_instance" "app_server" {
        ami           = "ami-830c94e3"
        instance_type = "t2.micro"
    
        tags = {
          Name = "Terraform_Demo"
        }
      }
    
  • This block defines the required version of Terraform and the AWS provider version. It specifies that the configuration requires the AWS provider version 4.16 or later and a minimum Terraform version of 1.2.0.

      terraform {
        required_providers {
          aws = {
            source  = "hashicorp/aws"
            version = "~> 4.16"
          }
        }
        required_version = ">= 1.2.0"
      }
    
  • This block defines the provider (in this case, AWS) and the region where the resources will be created. Here, it specifies the US East (N. Virginia) region.

      provider "aws" {
        region  = "us-east-1"
      }
    
  • This block creates an AWS EC2 instance with the specified AMI (Amazon Machine Image) and instance type. In this case, it uses the AMI ID ami-830c94e3 and the instance type t2.micro. Additionally, it assigns a tag to the instance with the key "Name" and value "Terraform_Demo".

      resource "aws_instance" "app_server" {
        ami           = "ami-830c94e3"
        instance_type = "t2.micro"
        tags = {
          Name = "Terraform_Demo"
        }
      }
    

Authenticating AWS CLI:

  • install AWS CLI

  • run aws configure to add access keys and default regions.

Executing Terraform File:

  • To initialize Terraform use terraform init the command.

    Output:

  • Run terraform plan to execute the infrastructure mentioned in the main.tf file

    Output:

      ubuntu@ip-172-31-84-161:~/write_your_first_terraform_project/aws/local_state$ terraform plan
    
      Terraform used the selected providers to generate the following execution plan. Resource actions
      are indicated with the following symbols:
        + create
    
      Terraform will perform the following actions:
    
        # aws_instance.app_server will be created
        + resource "aws_instance" "app_server" {
            + ami                                  = "ami-830c94e3"
            + arn                                  = (known after apply)
            + associate_public_ip_address          = (known after apply)
            + availability_zone                    = (known after apply)
            + cpu_core_count                       = (known after apply)
            + cpu_threads_per_core                 = (known after apply)
            + disable_api_stop                     = (known after apply)
            + disable_api_termination              = (known after apply)
            + ebs_optimized                        = (known after apply)
            + get_password_data                    = false
            + host_id                              = (known after apply)
            + host_resource_group_arn              = (known after apply)
            + iam_instance_profile                 = (known after apply)
            + id                                   = (known after apply)
            + instance_initiated_shutdown_behavior = (known after apply)
            + instance_state                       = (known after apply)
            + instance_type                        = "t2.micro"
            + ipv6_address_count                   = (known after apply)
            + ipv6_addresses                       = (known after apply)
            + key_name                             = (known after apply)
            + monitoring                           = (known after apply)
            + outpost_arn                          = (known after apply)
            + password_data                        = (known after apply)
            + placement_group                      = (known after apply)
            + placement_partition_number           = (known after apply)
            + primary_network_interface_id         = (known after apply)
            + private_dns                          = (known after apply)
            + private_ip                           = (known after apply)
            + public_dns                           = (known after apply)
            + public_ip                            = (known after apply)
            + secondary_private_ips                = (known after apply)
            + security_groups                      = (known after apply)
            + source_dest_check                    = true
            + subnet_id                            = (known after apply)
            + tags                                 = {
                + "Name" = "Terraform_Demo"
              }
            + tags_all                             = {
                + "Name" = "Terraform_Demo"
              }
            + tenancy                              = (known after apply)
            + user_data                            = (known after apply)
            + user_data_base64                     = (known after apply)
            + user_data_replace_on_change          = false
            + vpc_security_group_ids               = (known after apply)
          }
    
      Plan: 1 to add, 0 to change, 0 to destroy.
    
      ────────────────────────────────────────────────────────────────────────────────────────────────── 
    
      Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take       
      exactly these actions if you run "terraform apply" now.
    
  • Now run terraform apply to create infrastructure written in main.tf file. After running this command notice in your AWS console if the required changes are applied or not

    Output:

      ubuntu@ip-172-31-84-161:~/write_your_first_terraform_project/aws/local_state$ terraform apply
    
      Terraform used the selected providers to generate the following execution plan. Resource actions
      are indicated with the following symbols:
        + create
    
      Terraform will perform the following actions:
    
        # aws_instance.app_server will be created
        + resource "aws_instance" "app_server" {
            + ami                                  = "ami-053b0d53c279acc90"
            + arn                                  = (known after apply)
            + associate_public_ip_address          = (known after apply)
            + availability_zone                    = (known after apply)
            + cpu_core_count                       = (known after apply)
            + cpu_threads_per_core                 = (known after apply)
            + disable_api_stop                     = (known after apply)
            + disable_api_termination              = (known after apply)
            + ebs_optimized                        = (known after apply)
            + get_password_data                    = false
            + host_id                              = (known after apply)
            + host_resource_group_arn              = (known after apply)
            + iam_instance_profile                 = (known after apply)
            + id                                   = (known after apply)
            + instance_initiated_shutdown_behavior = (known after apply)
            + instance_state                       = (known after apply)
            + instance_type                        = "t2.micro"
            + ipv6_address_count                   = (known after apply)
            + ipv6_addresses                       = (known after apply)
            + key_name                             = (known after apply)
            + monitoring                           = (known after apply)
            + outpost_arn                          = (known after apply)
            + password_data                        = (known after apply)
            + placement_group                      = (known after apply)
            + placement_partition_number           = (known after apply)
            + primary_network_interface_id         = (known after apply)
            + private_dns                          = (known after apply)
            + private_ip                           = (known after apply)
            + public_dns                           = (known after apply)
            + public_ip                            = (known after apply)
            + secondary_private_ips                = (known after apply)
            + security_groups                      = (known after apply)
            + source_dest_check                    = true
            + subnet_id                            = (known after apply)
            + tags                                 = {
                + "Name" = "Terraform_Demo"
              }
            + tags_all                             = {
                + "Name" = "Terraform_Demo"
              }
            + tenancy                              = (known after apply)
            + user_data                            = (known after apply)
            + user_data_base64                     = (known after apply)
            + user_data_replace_on_change          = false
            + vpc_security_group_ids               = (known after apply)
          }
    
      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.app_server: Creating...
      aws_instance.app_server: Still creating... [10s elapsed]
      aws_instance.app_server: Still creating... [20s elapsed]
      aws_instance.app_server: Still creating... [30s elapsed]
      aws_instance.app_server: Creation complete after 32s [id=i-072553ad99cb7d0b2]
    
      Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
    

    conclusion:

    In conclusion, Terraform offers a powerful and efficient solution for managing infrastructure across multiple cloud providers. By leveraging Infrastructure as Code principles, organizations can automate the deployment and management of their resources, leading to more efficient and reliable systems. Terraform acts as the bridge between users and the APIs of different cloud providers, allowing for a unified and consistent approach to provisioning infrastructure. With Terraform, developers and DevOps teams can easily migrate resources between cloud platforms, such as AWS, Azure, and Google Cloud Platform, without learning multiple tools and technologies. By adopting Terraform, organizations can streamline their operations, improve scalability, and ensure a smoother transition in hybrid cloud environments.