Introduction: Provisioning infrastructure on cloud platforms like Amazon Web Services (AWS) can be a complex task. However, with the help of Infrastructure as Code (IaC) tools like Terraform, the process becomes more streamlined and manageable. In this article, we will explore a Terraform script that provisions essential infrastructure components on AWS, including VPC, subnet, internet gateway, security group, and an EC2 instance. By understanding this script, you will gain insights into how to leverage Terraform for automating infrastructure provisioning.

Prerequisites: Before diving into the Terraform script, make sure you have the following prerequisites in place:

  • An AWS account with appropriate permissions to create resources.
  • Terraform installed on your local machine.

Script Overview: The provided Terraform script demonstrates a common infrastructure setup on AWS. Let’s go through the key components and their purpose:

provider "aws" {
region = "ap-south-1"
}

// Define input variables
variable vpc_cidr_block {} // CIDR block for the VPC
variable subnet_cidr_block {} // CIDR block for the subnet
variable avail_zone {} // Availability zone for the subnet
variable env_prefix {} // Prefix to be used for naming resources
variable my_ip {} // IP address allowed for SSH access
variable instance_type {} // EC2 instance type
variable ami_name {} // Name of the Amazon Machine Image (AMI)
variable public_key_location {} // File location of the public key

// Create VPC resource
resource "aws_vpc" "myapp-vpc" {
cidr_block = var.vpc_cidr_block

tags = {
Name = "${var.env_prefix}-vpc"
}
}

// Create subnet resource
resource "aws_subnet" "myapp-subnet-1" {
vpc_id = aws_vpc.myapp-vpc.id
cidr_block = var.subnet_cidr_block
availability_zone = var.avail_zone

tags = {
Name = "${var.env_prefix}-subnet-1"
}
}

// Create internet gateway resource
resource "aws_internet_gateway" "myapp-igw" {
vpc_id = aws_vpc.myapp-vpc.id

tags = {
Name = "${var.env_prefix}-igw"
}
}

// Create default route table resource
resource "aws_default_route_table" "main-rtb" {
default_route_table_id = aws_vpc.myapp-vpc.default_route_table_id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.myapp-igw.id
}

tags = {
Name = "${var.env_prefix}-main-rtb"
}
}

// Create default security group resource
resource "aws_default_security_group" "default-sg" {
vpc_id = aws_vpc.myapp-vpc.id

// Ingress rules
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.my_ip] // Allow SSH access only from the specified IP
}

ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] // Allow incoming traffic on port 8080 from any IP
}

// Egress rule
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] // Allow outgoing traffic to any IP
prefix_list_ids = []
}

tags = {
Name = "${var.env_prefix}-default-sg"
}
}

// Data source for retrieving the latest Amazon Linux AMI
data "aws_ami" "latest-amazon-linux-image" {
most_recent = true
owners = ["amazon"]

filter {
name = "name"
values = [var.ami_name] // Specify the desired AMI name
}

filter {
name = "virtualization-type"
values = ["hvm"]
}
}

// Create key pair resource for SSH access
resource "aws_key_pair" "ssh-key" {
key_name = "server-key"
public_key = file(var.public_key_location)
}

// Create EC2 instance resource
resource "aws_instance" "myapp-server" {
ami = data.aws_ami.latest-amazon-linux-image.id
instance_type = var.instance_type

subnet_id = aws_subnet.myapp-subnet-1.id
vpc_security_group_ids = [aws_default_security_group.default-sg.id]
availability_zone = var.avail_zone

associate_public_ip_address = true
key_name = aws_key_pair.ssh-key.key_name

user_data = file("installing-jenkins.sh") // Script to install Jenkins

tags = {
Name = "${var.env_prefix}-server"
}
}

// Output the AMI ID
output "aws_ami_id" {
value = data.aws_ami.latest-amazon-linux-image.id
}

// Output the public IP of the EC2 instance
output "ec2_public_ip" {
value = aws_instance.myapp-server.public_ip
}

Variable file “terraform.tfvars”

vpc_cidr_block = "10.0.0.0/16"
subnet_cidr_block = "10.0.10.0/24"
env_prefix = "Jenkins-Master"
my_ip = "yourIP"
instance_type = "t2.micro"
ami_name = "ubuntu/images/hvm-ssd/ubuntu-jammy-*-amd64-server-*"
public_key_location = "/home/userid/.ssh/id_rsa.pub"
  1. Provider Configuration: The script begins with the declaration of the AWS provider and specifies the region where the infrastructure will be provisioned. In this case, it is set to “ap-south-1” (Asia Pacific [Mumbai] region). Modify this configuration if you want to deploy in a different region.
  2. Variable Declarations: Next, the script defines several variables that allow customization of the infrastructure. These variables include VPC CIDR block, subnet CIDR block, availability zone, environment prefix, IP address for SSH access, instance type, AMI name, and public key file location. Modify these variables to suit your requirements.
  3. VPC and Subnet Creation: The script creates a VPC and a subnet within it using the specified CIDR blocks and availability zone. The VPC represents an isolated virtual network, while the subnet defines a smaller network segment within the VPC.
  4. Internet Gateway: An internet gateway is created and associated with the VPC. This allows the resources within the VPC to communicate with the internet.
  5. Default Route Table: A default route table is created and associated with the VPC. It defines a route to the internet gateway, enabling internet connectivity for resources within the VPC.
  6. Default Security Group: The script provisions a default security group within the VPC. It allows inbound SSH access from the specified IP address and allows inbound traffic on port 8080 from any source. Outbound traffic is allowed to any destination. You can uncomment additional security group rules if required.
  7. Amazon Machine Image (AMI) Selection: The script uses the “data” block to fetch the latest Amazon Linux image matching the specified name and virtualization type. This ensures that the EC2 instance uses the desired base image for deployment.
  8. SSH Key Pair: An SSH key pair is created to enable secure access to the EC2 instance. The public key provided in the specified file location is used for authentication.
  9. EC2 Instance Provisioning: Finally, the script creates an EC2 instance using the selected AMI, instance type, subnet, security group, and other parameters. It associates a public IP address, attaches the SSH key pair, and executes the specified user data script during instance initialization.

Outputs: The script includes two outputs that provide useful information after provisioning:

  • “aws_ami_id” outputs the ID of the Amazon Linux AMI used for the EC2 instance.
  • “ec2_public_ip” outputs the public IP address of the EC2 instance.

Jenkins Installation Script: installing-jenkins.sh

#!/bin/bash

# Install Java
sudo apt update -y
sudo apt install default-jre -y
sudo apt install default-jdk -y

# Install Jenkins on Ubuntu

# https://www.jenkins.io/doc/book/installing/linux/#debianubuntu

# add the repository key to your system:
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
/usr/share/keyrings/jenkins-keyring.asc > /dev/null

# append the Debian package repository address to the server
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null

# To use the new repository
sudo apt-get update -y


# install Jenkins and its dependencies:
sudo apt-get install jenkins -y

# starting-jenkins
sudo systemctl start jenkins.service

# verify that Jenkins started successfully:
# sudo systemctl status jenkins

Terraform Commands:

terraform init

terraform plan

terraform apply

By executing terraform init before running other Terraform commands, you ensure that the necessary dependencies are set up, including provider plugins and backend configurations. It is typically the first command you run in a new Terraform project or when working with an existing project on a new machine.

terraform plan, you can review the proposed changes to your infrastructure before actually applying them. It helps you understand the impact of your configuration changes and ensures that you have a clear understanding of the actions Terraform will take.

By running terraform apply, you initiate the process of provisioning and managing your infrastructure as defined in the Terraform configuration. It allows you to deploy and modify resources in a consistent and reproducible manner.

Now, Connect to the EC2 Instance and check the Jenkins Service Status and Installed Version.

GitHub Link: https://github.com/ganeshpondy/AutomateHub/tree/main/Terraform/Jenkins-Master

Conclusion: Automating infrastructure provisioning on AWS is crucial for efficient and scalable cloud deployments. With Terraform, you can define your infrastructure as code, making it easily reproducible and manageable. The provided Terraform script demonstrates how to create a VPC, subnet, internet gateway, security group, and EC2 instance on AWS.

Leave a Reply

Your email address will not be published. Required fields are marked *