Table of Contents
#Introduction
In this tutorial, How to deploy cluster web servers use Terraform. For example, I will use Terraform deploy cluster web servers.
- Create EC2 instance
- Terraform parameter Count: I will create three EC2 instance use Count parameter
- User user_data and create a script to install Nginx webserver on amazon linux 2.
- Security group ingress rule to allow access web server from my laptop ?
Structure folder and files of Terraform deploy cluster web servers
Created Cluster-WebServer folder contains files as below:
main.tf
output.tf
provider.tf
securitygroups.tf
variables.tf
Deploy cluster Web Servers with Terraform
Create new file main.tf with the content as below
resource "aws_instance" "devopsroles-lab01" {
count = 3
ami = var.ami
instance_type = var.instance_type
vpc_security_group_ids = ["${aws_security_group.webserver_security_group.id}"]
tags = {
Name = "DevopsRoles-${count.index}"
}
key_name = "terraform-demo"
user_data = <<EOF
#!/bin/bash -xe
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
sudo yum update -y
sudo amazon-linux-extras install nginx1 -y
sudo su -c "/bin/echo 'My Site: DevopsRoles.com' >/usr/share/nginx/html/index.html"
instance_ip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
sudo su -c "echo $instance_ip >>/usr/share/nginx/html/index.html"
sudo systemctl start nginx
sudo systemctl enable nginx
EOF
}
On AWS, we created key pair terraform-demo as the picture below
Create a new file provider.tf with the content as below
provider "aws" {
region = var.region
}
New file securitygroups.tf with the content as below
resource "aws_security_group" "webserver_security_group" {
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = [ var.my_public_ip ]
}
ingress {
from_port = var.ssh_port
to_port = var.ssh_port
protocol = "tcp"
cidr_blocks = [ var.my_public_ip ]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
Create a new file output.tf with the content as below
output "public_ip" {
value = [ "${aws_instance.devopsroles-lab01.*.public_ip}"]
}
Create new file variables.tf with the content as below
variable "region" {
description = " Define the AWS region "
default = "us-west-2"
}
variable "server_port" {
description = "http service listen"
default = "80"
}
variable "ssh_port" {
description = "ssh to server"
default = "22"
}
variable "instance_type" {
description = "AWS ec2 instance type"
default="t2.micro"
}
variable "my_public_ip" {
description = "My laptop public IP ..."
default = "116.110.26.150/32"
}
variable "ami" {
description = "amazon machine image"
default = "ami-0c2d06d50ce30b442"
}
variable "azs" {
default = [ "us-east-2a", "us-east-2b", "us-east-2c"]
}
First, we run below to initialize, download the plugins and validate the terraform syntax…
terraform init
terraform validate
The output terminal is as follows
Applying a template
$ terraform apply
The output terminal is as below
C:\Users\HuuPV\Desktop\Terraform\Cluster_WebServer>set AWS_PROFILE=devopsroles-demo
C:\Users\HuuPV\Desktop\Terraform\Cluster_WebServer>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.devopsroles-lab01[0] will be created
+ resource "aws_instance" "devopsroles-lab01" {
+ ami = "ami-0c2d06d50ce30b442"
+ 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_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (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 = "terraform-demo"
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (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" = "DevopsRoles-0"
}
+ tags_all = {
+ "Name" = "DevopsRoles-0"
}
+ tenancy = (known after apply)
+ user_data = "e210837ad2017cf0971bc0ed4af86edab9d8a10d"
+ user_data_base64 = (known after apply)
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (known after apply)
+ capacity_reservation_target {
+ capacity_reservation_id = (known after apply)
}
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ enclave_options {
+ enabled = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ metadata_options {
+ http_endpoint = (known after apply)
+ http_put_response_hop_limit = (known after apply)
+ http_tokens = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_interface_id = (known after apply)
}
+ root_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}
# aws_instance.devopsroles-lab01[1] will be created
+ resource "aws_instance" "devopsroles-lab01" {
+ ami = "ami-0c2d06d50ce30b442"
+ 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_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (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 = "terraform-demo"
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (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" = "DevopsRoles-1"
}
+ tags_all = {
+ "Name" = "DevopsRoles-1"
}
+ tenancy = (known after apply)
+ user_data = "e210837ad2017cf0971bc0ed4af86edab9d8a10d"
+ user_data_base64 = (known after apply)
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (known after apply)
+ capacity_reservation_target {
+ capacity_reservation_id = (known after apply)
}
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ enclave_options {
+ enabled = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ metadata_options {
+ http_endpoint = (known after apply)
+ http_put_response_hop_limit = (known after apply)
+ http_tokens = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_interface_id = (known after apply)
}
+ root_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}
# aws_instance.devopsroles-lab01[2] will be created
+ resource "aws_instance" "devopsroles-lab01" {
+ ami = "ami-0c2d06d50ce30b442"
+ 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_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (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 = "terraform-demo"
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (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" = "DevopsRoles-2"
}
+ tags_all = {
+ "Name" = "DevopsRoles-2"
}
+ tenancy = (known after apply)
+ user_data = "e210837ad2017cf0971bc0ed4af86edab9d8a10d"
+ user_data_base64 = (known after apply)
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (known after apply)
+ capacity_reservation_target {
+ capacity_reservation_id = (known after apply)
}
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ enclave_options {
+ enabled = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ metadata_options {
+ http_endpoint = (known after apply)
+ http_put_response_hop_limit = (known after apply)
+ http_tokens = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_interface_id = (known after apply)
}
+ root_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}
# aws_security_group.webserver_security_group will be created
+ resource "aws_security_group" "webserver_security_group" {
+ arn = (known after apply)
+ description = "Managed by Terraform"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = ""
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = [
+ "116.110.26.150/32",
]
+ description = ""
+ from_port = 22
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 22
},
+ {
+ cidr_blocks = [
+ "116.110.26.150/32",
]
+ description = ""
+ from_port = 80
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 80
},
]
+ name = (known after apply)
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags_all = (known after apply)
+ vpc_id = (known after apply)
}
Plan: 4 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ public_ip = [
+ [
+ (known after apply),
+ (known after apply),
+ (known after apply),
],
]
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_security_group.webserver_security_group: Creating...
aws_security_group.webserver_security_group: Creation complete after 8s [id=sg-05fe82255b21a2c8b]
aws_instance.devopsroles-lab01[1]: Creating...
aws_instance.devopsroles-lab01[0]: Creating...
aws_instance.devopsroles-lab01[2]: Creating...
aws_instance.devopsroles-lab01[0]: Still creating... [10s elapsed]
aws_instance.devopsroles-lab01[2]: Still creating... [10s elapsed]
aws_instance.devopsroles-lab01[1]: Still creating... [10s elapsed]
aws_instance.devopsroles-lab01[2]: Still creating... [20s elapsed]
aws_instance.devopsroles-lab01[0]: Still creating... [20s elapsed]
aws_instance.devopsroles-lab01[1]: Still creating... [20s elapsed]
aws_instance.devopsroles-lab01[1]: Still creating... [30s elapsed]
aws_instance.devopsroles-lab01[2]: Still creating... [30s elapsed]
aws_instance.devopsroles-lab01[0]: Still creating... [30s elapsed]
aws_instance.devopsroles-lab01[0]: Still creating... [40s elapsed]
aws_instance.devopsroles-lab01[1]: Still creating... [40s elapsed]
aws_instance.devopsroles-lab01[2]: Still creating... [40s elapsed]
aws_instance.devopsroles-lab01[0]: Creation complete after 42s [id=i-0ade24acdfd72944c]
aws_instance.devopsroles-lab01[1]: Creation complete after 42s [id=i-00daeeee26f9dcd20]
aws_instance.devopsroles-lab01[2]: Creation complete after 43s [id=i-0b77263afa926a374]
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
public_ip = [
[
"54.189.128.5",
"52.27.217.183",
"54.201.82.158",
],
]
C:\Users\HuuPV\Desktop\Terraform\Cluster_WebServer>
The result, on EC2 AWS
Open Browser, type http://IP_Public_EC2 as below
Webserver 1
Webserver 2
Webserver 3
Conclusion
You have use Terraform deploy cluster web servers. I hope will this your helpful. Thank you for reading the DevopsRoles page!