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 typet2.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 fileOutput:
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 notOutput:
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.