HashiCorp Terraform
is aninfrastructure as a code
tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. Terraform can manage low-level components like computing, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.
- Creating a development environment on AWS using Terraform is a powerful approach that allows developers to provision and manage infrastructure as code. By leveraging the capabilities of Terraform and AWS, developers can easily spin up and configure resources required for their development work, ensuring consistency and reproducibility across environments. Let's explore the steps involved in setting up a development environment on AWS using Terraform.
-
Prerequisites:
- An AWS account with appropriate permissions.
- Terraform installed on your local machine.
-
Configure AWS Credentials:
- Obtain your AWS
access key
ID andsecret access key
from the AWS Management Console. - Set up your AWS credentials either by exporting environment variables or using
AWS CLI
'saws configure
command.
- Obtain your AWS
-
Initialize Terraform:
- Create a new directory for your Terraform project.
- Open a terminal in the project directory and run
terraform init
. - This command initializes the Terraform project and downloads the necessary provider plugins.
-
Write Terraform Configuration:
- Create a new file, typically named
main.tf
, and define your desired AWS resources. - For a development environment, you might provision resources like virtual machines (EC2 instances), virtual networks (VPC) or other necessary services.
- Specify resource details such as instance types, network configurations, security groups, and any other required parameters.
- Create a new file, typically named
-
Create the Development Environment:
- Run
terraform plan
to see a preview of the changes Terraform will make. - Review the plan to ensure it aligns with your expectations.
- Execute
terraform apply
to create the development environment on AWS. - Terraform will prompt for confirmation before making any changes.
- Type
yes
to proceed, and Terraform will provision the specified resources.
- Run
-
Access and Configure the Environment:
- Once the provisioning process completes, Terraform will display the
output variables
defined in your configuration file. - These outputs might include the IP addresses, access keys, or other important details required to connect to your development environment.
- Make note of these outputs and use them to access and configure your development environment accordingly.
- Once the provisioning process completes, Terraform will display the
-
Managing the Environment:
- To make changes to your development environment, modify your Terraform configuration file (e.g.,
main.tf
) as needed. - Run
terraform plan
to preview the changes andterraform apply
to apply them. - Terraform will automatically determine the delta between the desired and existing state and apply the necessary updates.
- To make changes to your development environment, modify your Terraform configuration file (e.g.,
-
Destroying the Environment:
- When you no longer need the development environment, you can use Terraform to clean up the provisioned resources.
- Run
terraform destroy
to destroy all the resources created by Terraform. - Confirm the destruction by typing
yes
when prompted.
- By following these steps, you can easily
create and manage a development environment on AWS using Terraform
. This approach enablesinfrastructure-as-code
practices, ensures consistency across environments, and allows for easy reproducibility and scalability of your development setup.
- Create a file
providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "ap-south-1"
shared_credentials_file = "~/.aws/credentials"
profile = "[replace you aws user]"
}
And run this command terraform init
- Terraform Docs for AWS Provide.
- Create a file
main.tf
resource "aws_vpc" "dhruv_vpc" {
cidr_block = "10.123.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
name = "dev"
}
}
- Terraform Docs Reference for creating a VPC
- Add subnet configuration in
main.tf
resource "aws_subnet" "dhruv_public_subnet" {
vpc_id = aws_vpc.dhruv_vpc.id
cidr_block = "10.123.1.0/24"
map_public_ip_on_launch = true
availability_zone = "ap-south-1a"
tags = {
Name = "dev-public"
}
}
- Terraform Docs Reference for creating a Subnet.
- Add Internet Gateway configurations in
main.tf
resource "aws_internet_gateway" "dhruv_internet_gateway" {
vpc_id = aws_vpc.dhruv_vpc.id
tags = {
Name = "dev-igw"
}
}
- Terraform Docs Reference for creating an Internet Gateway.
- Add Route Table configuration in
main.tf
.
resource "aws_route_table" "dhruv_public_rt" {
vpc_id = aws_vpc.dhruv_vpc.id
tags = {
Name = "dev_public_rt"
}
}
- Terraform Docs Reference for creating a Route Table.
- Add Route in
main.tf
resource "aws_route" "def_route" {
route_table_id = aws_route_table.dhruv_public_rt.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.dhruv_internet_gateway.id
}
- Terraform Docs Reference for defining a Route.
- Associate subnet with route table in
main.tf
resource "aws_route_table_association" "dhruv_public_assoc" {
subnet_id = aws_subnet.dhruv_public_subnet.id
route_table_id = aws_route_table.dhruv_public_rt.id
}
- Terraform Docs for Route table association.
- Add a security group in
main.tf
resource "aws_security_group" "dhruv_sg" {
name = "dev_sg"
description = "dev security Group"
vpc_id = aws_vpc.dhruv_vpc.id
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
- Terraform Docs for creating a security group.
-
In this project, we use
Ubuntu Server-20.04
-
AMI ID:
ami-08e5424edfe926b43
-
AMI Name:
ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20230517
-
Owner ID:
099720109477
-
Create new file
datasources.tf
data "aws_ami" "server_ami" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20230517"]
}
}
- Terraform Docs for AMI.
- Go to VS Code terminal and run this command
ssh-keygen -t ed25519
and press Enter - You can see this type of output
Generating public/private ed25519 key pair.
C:\Users\Dhruv/.ssh/id_ed25519):
- Copy this path
C:\Users\Dhruv/.ssh/
and enter yourKey Name
. - It looks like this
C:\Users\Dhruv/.ssh/dhruvkey
- And then press
Enter
- key was generated After that run this command in terminal
ls ~/.ssh
- You can see all directories and files in
C:\Users\Dhruv\.ssh
- In this, you can see
dhruvkey
anddhruvkey.pub
-
In this part, we use terraform file function for passing the public key as a file
path
. -
Add this configuration in
main.tf
.
resource "aws_key_pair" "dhruv_auth" {
key_name = "dhruvkey"
public_key = file("~/.ssh/dhruvkey.pub")
}
- Terraform Docs for aws_key_pair.
- Terraform Docs for Terraform file function.
- Create Template file
userdata.tpl
for update and install docker
#!/bin/bash
sudo apt-get update -y &&
sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common &&
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - &&
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" &&
sudo apt-get update -y &&
sudo sudo apt-get install docker-ce docker-ce-cli containerd.io -y &&
sudo usermod -aG docker ubuntu
- Add this EC2 instance configuration in
main.tf
file.
resource "aws_instance" "dhruv_node" {
instance_type = "t2.micro"
ami = data.aws_ami.server_ami.id
key_name = aws_key_pair.dhruv_auth.id
vpc_security_group_ids = [aws_security_group.dhruv_sg.id]
subnet_id = aws_subnet.dhruv_public_subnet.id
user_data = file("userdata.tpl")
root_block_device {
volume_size = 10
}
tags = {
Name = "dhruv-node"
}
- Terraform Docs for AWS Instances.
- For this task run a
ssh -i C:\Users\Dhruv\.ssh\dhruvkey ubuntu@13.233.64.121
in terminal and pressEnter
-> TypeYes
-> (you are in instance)
- This SSH configuration script is to allow VS Code to connect our EC2 Instance.
- Create Template file
windows-ssh-config.tpl
for Windows system.
add-content -path C:/Users/Dhruv/.ssh/config -value @'
Host ${hostname}
HostName ${hostname}
User ${user}
IdentityFile ${identityfile}
'@
- For Linux or Mac
linux-ssh-config.tpl
cat << EOF >> ~/.ssh/config
Host ${hostname}
HostName ${hostname}
User ${user}
IdentityFile ${identityfile}
EOF
- Add provisioner in
main.tf
file.
provisioner "local-exec" {
command = templatefile("windows-ssh-config.tpl", {
hostname = self.public_ip,
user = "ubuntu",
identityfile = "~/.ssh/dhruvkey"
})
interpreter = ["Powershell", "-command"]
}
}
-
After the provisioner run this command in terminal
cat ~/.ssh/config
. -
The output looks like this.
- After that follow this flow
In Vs code -> View -> Command Palette.. -> Remote-SSH: Connect to Host.. -> select(13.233.64.121) -> Open new VS code Window -> Linux -> Continue -> And see Output like this
Terraform Docs provisioners
- Terraform Variables for choosing dynamic OS
- Use
Variable Precedence
- Create variable file
variables.tf
variable "host_os" {
type = string
default = "windows"
}
- Create
terraform.tfvars
host_os = "linux"
- Here
terraform.tfvars
takes precedence over a defaultvariable.tf
file.
-
Here
variable inline command
takes precedence over aterraform.tfvars
file. -
Terraform Docs for variable.
- Add this
provisioner
code inmain.tf
file.
provisioner "local-exec" {
command = templatefile("${var.host_os}-ssh-config.tpl", {
hostname = self.public_ip,
user = "ubuntu",
identityfile = "~/.ssh/dhruvkey"
})
interpreter = var.host_os == "windows" ? ["Powershell", "-command"] : ["bash", "-c"]
}
}
- Terraform Docs for conditional expression.
- Create
output.tf
file.
output "dev_ip" {
value = aws_instance.dhruv_node.public_ip
}
- Terraform Docs for output values.
terraform fmt
- The
terraform fmt
command is used to rewrite Terraform configuration files to a canonical format and style. This command applies a subset of the Terraform language style conventions, along with other minor adjustments for readability.
terraform state
- The command will list all resources in the state file matching the given addresses (if any). If no addresses are given, all resources are listed.
terraform plan
- The
terraform plan
command creates an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure. By default, when Terraform creates a plan it: - Reads the current state of any already-existing remote objects to make sure that the Terraform state is up-to-date.
- Compares the current configuration to the prior state and notes any differences.
- Proposes a set of change actions that should, if applied, make the remote objects match the configuration.
terraform show
- The
terraform show
command is used to provide human-readable output from a state or plan file. This can be used to inspect a plan to ensure that the planned operations are expected or to inspect the current state as Terraform sees it. Machine-readable output is generated by adding the -json command-line flag.
terraform apply
- When you run
terraform apply
without passing a saved plan file, Terraform automatically creates a new execution plan as if you had runterraform plan
, prompts you to approve that plan, and takes the indicated actions. You can use all of the planning modes and planning options to customize how Terraform will create the plan. You can pass the-auto-approve
option to instruct Terraform to apply the plan without asking for confirmation.
terraform destroy
- The
terraform destroy
command is a convenient way to destroy all remote objects managed by a particular Terraform configuration.