Skip to content

Terraform

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can help with multi-cloud by having one workflow for all clouds. The infrastructure Terraform manages can be hosted on public clouds like Amazon Web Services, Microsoft Azure, and Google Cloud Platform, or on-prem in private clouds such as VMWare vSphere.

Terraform Installation ๐Ÿ“ฅ

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install terraform
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform

Reference ๐Ÿ“Œ

Terraform Registry

https://registry.terraform.io/

Terraform Commands Cheat sheet Reference Link

https://acloudguru.com/blog/engineering/the-ultimate-terraform-cheatsheet

Prerequisites

Before you begin, ensure you have the following prerequisites in place:

  1. AWS Account: You need an active AWS account with necessary permissions to create resources like Ec2 Instances, IAM roles, VPC, etc.

  2. AWS CLI: Install and configure the AWS Command Line Interface (CLI) on your local machine. You can download it from the AWS CLI Documentation.

  3. IAM User: Create an AWS IAM user with programmatic access and necessary permissions (e.g., Ec2 Full Access, S3 Full Access). Note down the user's access key ID and secret access key. ๐Ÿ“Œ Reference Document Link

Warning

Utilize Role-Based Authentication when working with Terraform on AWS Instances or Services, as it offers a higher level of security compared to using access keys.

Terraform Sample Scripts

Provisioning an AWS EC2 Instance

main.tf
provider "aws" {
  region = "us-east-2"
}

resource "aws_instance" "Instance" {
  ami                    = "ami-0fb653ca2d3203ac1"
  instance_type          = "t2.micro"
  key_name               = "terraform"
  vpc_security_group_ids = ["sg-0138c7796472ac9a9"]
  tags = {
    Name = "IAAC"
    Team = "DevOps"
  }
}
main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_key_pair" "example_keypair" {
  key_name   = "satrun"
  public_key = tls_private_key.example_keypair.public_key_openssh
}

resource "tls_private_key" "example_keypair" {
  algorithm = "RSA"
}

resource "local_file" "private_key_file" {
  content  = tls_private_key.example_keypair.private_key_pem
  filename = "satrun.pem"
}

resource "aws_security_group" "example_security_group" {
  name        = "satrun-security-group"
  description = "Example Security Group"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["YOUR PUBLIC IP/32"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["YOUR PUBLIC IP/32"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "example_instance" {
  ami                = "ami-09e67e426f25ce0d7" # Ubuntu 20.04 LTS in us-east-1 (N. Virginia) region
  instance_type      = "t2.micro"
  key_name           = aws_key_pair.example_keypair.key_name
  vpc_security_group_ids = [aws_security_group.example_security_group.id]

  tags = {
    Name = "satrun-instance"
  }
}

Terraform Vars

Using Variables

Create a File with name vars.tf

vim vars.tf
vars.tf
variable "REGION" {
  default = "us-east-2"
}

variable "ZONE1" {
  default = "us-east-2a"
}

variable "AMIS" {
  type = map(any)
  default = {
    us-east-2 = "ami-0fb653ca2d3203ac1"
    us-east-1 = "ami-0e1d30f2c40c4c701"
  }
}

Terraform Provider

Example for AWS

vim provider.tf

provider.tf
provider "aws" {
  region = var.REGION
}

Launching Instance with Vars File

vim main.tf
main.tf
resource "aws_instance" "Instance" {
  ami                    = var.AMIS[var.REGION]
  instance_type          = "t2.micro"
  key_name               = "terraform"
  vpc_security_group_ids = ["sg-0138c7796472ac9a9"]
  tags = {
    Name = "IAAC"
    Team = "DevOps"
  }
}

Terraform Provisioning

Launching AWS Resources and Setting Up a Website with Terraform with existing key-pair

Note

Generate a key pair using the 'ssh-keygen' command and then save the contents of the public and private keys into two new files named 'testing007.pub' and 'testing007'.

main.tf
resource "aws_key_pair" "testing007" {
  key_name   = "testing007"
  public_key = file("testing007.pub")
 }

resource "aws_instance" "Instance" {
  ami                    = var.AMIS[var.REGION]
  instance_type          = "t2.micro"
  key_name               = aws_key_pair.testing007.key_name
  vpc_security_group_ids = ["sg-0138c7796472ac9a9"]
  tags = {
    Name = "IAAC"
    Team = "DevOps"
 }

  provisioner "file" {
    source      = "./web.sh"
    destination = "/tmp/web.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod u+x /tmp/web.sh",
      "sudo /tmp/web.sh"
    ]
  }

  connection {
    user        = var.USER
    private_key = file("testing007")
    host        = self.public_ip
  }
 }

output "PublicIP" {
  value = aws_instance.Instance.public_ip
}

Variables file - vars.tf

vars.tf
variable "REGION" {
  default = "us-east-2"
}

variable "ZONE1" {
  default = "us-east-2a"
}

variable "USER" {
  default = "ubuntu"
}

variable "AMIS" {
  type = map(any)
  default = {
    us-east-2 = "ami-0fb653ca2d3203ac1"
    us-east-1 = "ami-0e1d30f2c40c4c701"
  }

}

To Store State Remotely in S3 Bucket

Create an S3 Bucket

main.tf
terraform {
  backend "s3" {
    bucket = "terraform-state-009"
    key    = "terraform/remote"
    region = "us-east-1"
  }
}

Running Terraform Script using Pipeline

Launching EC2 Instances and Storing State Files in an S3 Bucket with Terraform

Info

Enable Authentications such as service connections, OAuth Tokens and etc of the required platform with your pipeline

main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_key_pair" "example_keypair" {
  key_name   = "mars"
  public_key = tls_private_key.example_keypair.public_key_openssh
}

resource "tls_private_key" "example_keypair" {
  algorithm = "RSA"
}

resource "local_file" "private_key_file" {
  content  = tls_private_key.example_keypair.private_key_pem
  filename = "mars.pem"
}

resource "aws_security_group" "example_security_group" {
  name        = "mars-security-group"
  description = "Example Security Group"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["183.82.115.199/32"]
}

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["183.82.115.199/32"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "example_instance" {
  ami                = "ami-09e67e426f25ce0d7" # Ubuntu 20.04 LTS in us-east-1 (N. Virginia) region
  instance_type      = "t2.micro"
  key_name           = aws_key_pair.example_keypair.key_name
  vpc_security_group_ids = [aws_security_group.example_security_group.id]

  tags = {
    Name = "mars-instance"
  }
}

terraform {

  backend "s3" {
    bucket = "terraform-azuredevops-saitejairrinki-org"
    key    = "terraform/remote"
    region = "us-east-1"
  }
}
main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_key_pair" "example_keypair" {
  key_name   = "satrun"
  public_key = tls_private_key.example_keypair.public_key_openssh
}

resource "tls_private_key" "example_keypair" {
  algorithm = "RSA"
}

resource "local_file" "private_key_file" {
  content  = tls_private_key.example_keypair.private_key_pem
  filename = "satrun.pem"
}

resource "aws_security_group" "example_security_group" {
  name        = "satrun-security-group"
  description = "Example Security Group"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "example_instance" {
  ami                = "ami-09e67e426f25ce0d7" # Ubuntu 20.04 LTS in us-east-1 (N. Virginia) region
  instance_type      = "t2.micro"
  key_name           = aws_key_pair.example_keypair.key_name
  vpc_security_group_ids = [aws_security_group.example_security_group.id]

  tags = {
    Name = "satrun-instance"
  }

  provisioner "file" {
    source      = "./web.sh"
    destination = "/tmp/web.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/web.sh",
      "sudo /tmp/web.sh"
    ]
  }

  connection {
    type        = "ssh"
    user        = "ubuntu"  # Change to the appropriate SSH user for your AMI
    private_key = tls_private_key.example_keypair.private_key_pem
    host        = self.public_ip
  }
}

output "PublicIP" {
  value = aws_instance.example_instance.public_ip
}

terraform {
  backend "s3" {
    bucket = "1terraform"
    key    = "terraform/remote"
    region = "us-east-1"
  }
}

Additional Concepts๐Ÿ”—