Automating Apache Web Server Deployment with Terraform and Ansible on AWS
In this project, we deploy an Apache Web Server on an AWS EC2 instance, which is created by Terraform, and use Ansible for configuration management.
Prerequisites
Certainly! Before implementing this Terraform and Ansible project for deploying an Apache web server on AWS, you’ll need to ensure that certain prerequisites are met. Here are the key requirements:
1. AWS Account:
You should have an active AWS account. If you don’t have one, you can create one on the [AWS official website](https://aws.amazon.com/).
2. AWS CLI and Profiles:
Install the AWS Command Line Interface (AWS CLI) on your local machine.
Configure the AWS CLI with your AWS credentials using `aws configure` to set up a profile named “web-user” (or any profile you prefer). This profile will be referenced in the Terraform script.
3. **SSH Key Pair:**
Generate an SSH key pair that will be used for connecting to the EC2 instances. In the Terraform script, the key name is specified as “jenkins,” so ensure that you have the corresponding private key file (e.g., “jenkins.pem”) available locally.
4. **Terraform Installed:**
Install Terraform on your local machine. You can download it from the official Terraform website](https://www.terraform.io/downloads.html).
5. **Ansible Installed:**
Install Ansible on your remote machine. Instructions can be found in the [Ansible documentation](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html).
(Note: In my case, I install the ansible on a remote machine, {which is both the controller node and the managed node in my case.)
6. **Ansible Playbook:**
Prepare an Ansible playbook (e.g., “web-configure.yml”) that contains the necessary tasks for configuring the Apache web server. This playbook should be placed in a directory accessible to Terraform.
7. Local Project Structure:
— Organize your project with the appropriate directory structure. Ensure that your Terraform script, Ansible playbook, and SSH private key file are easily accessible.
8. Local Dependencies:
Make sure any local dependencies, such as the file path for the SSH private key (“jenkins.pem” in this case), are correctly defined in your Terraform script.
9. Security Group Configuration:
Ensure that the security group referenced in the Terraform script (“webport-allow” in this case) allows incoming traffic on the necessary ports (e.g., port 22 for SSH and port 80 for HTTP).
By addressing these prerequisites, you’ll be well-prepared to execute the Terraform script, automating the deployment and configuration of an Apache web server on AWS using Ansible.
Overview
In this Terraform script, we orchestrate the deployment of an Apache web server on an AWS EC2 instance using Ansible for configuration management. The script begins by specifying the AWS provider details and creating an EC2 instance with a specified AMI, instance type, and security groups. It also provisions an EBS volume, attaches it to the instance, and mounts it to the ‘/var/www/html’ directory.
To streamline the configuration process, the script utilizes Ansible through Terraform’s null resources. It installs necessary packages, starts the Apache server, and ensures the web server is up and running. The script also demonstrates how to connect to the EC2 instance using SSH, copy files, and install Ansible on the remote machine.
The final steps involve copying the AWS instance’s public IP to a local file, transferring it to the Ansible control node, and executing an Ansible playbook for further web server configuration. The script showcases a comprehensive integration of Terraform and Ansible, providing a seamless and automated approach to deploying and configuring an Apache web server on AWS infrastructure.
So, Lets begin
Certainly! Let’s break down each part of Terraform script:
1. AWS Provider Configuration:
provider “aws” {
region = “ap-south-1”
profile = “web-user”
}
This section configures the AWS provider with the specified region and user profile.
2. EC2 Instance Creation:
resource “aws_instance” “apache” {
ami = “ami-010aff33ed5991201”
instance_type = “t2.micro”
security_groups = [“webport-allow”]
key_name = “jenkins”
tags = {
Name: “Terraform-Ansible”
}
}
Here, an EC2 instance is created with the specified Amazon Machine Image (AMI), instance type, security groups, key name, and tags.
3. Remote Execution for Apache Configuration:
resource "null_resource" "nullremote-install" {
connection {
type = "ssh"
user = "ec2-user"
private_key = file("C:/Users/jatin/Downloads/jenkins.pem")
host = aws_instance.apache.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo yum install httpd -y",
"sudo yum install php -y",
"sudo systemctl start httpd",
"sudo systemctl start httpd"
]
}
}
This part uses a null resource with a remote-exec provisioner to execute commands on the EC2 instance remotely. It installs and configures Apache web server and PHP.
4. EBS Volume Creation:
resource “aws_ebs_volume” “apache-ebs-vol” {
availability_zone = aws_instance.apache.availability_zone
size = 2
tags = {
Name: “apache-ebs-volume”
}
}
It creates an Elastic Block Store (EBS) volume with a specified size and attaches it to the same availability zone as the EC2 instance.
5. Volume Attachment:
resource “aws_volume_attachment” “ebs_att” {
device_name = “/dev/sdh”
volume_id = aws_ebs_volume.apache-ebs-vol.id
instance_id = aws_instance.apache.id
}
This resource attaches the EBS volume to the EC2 instance at the specified device name.
6. Remote Execution for Mounting EBS Volume:
resource "null_resource" "nullremote-mount" {
depends_on = [aws_volume_attachment.ebs_att]
connection {
type = "ssh"
user = "ec2-user"
private_key = file("C:/Users/jatin/Downloads/jenkins.pem")
host = aws_instance.apache.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo mkfs.ext4 /dev/sdh",
"sudo mount /dev/sdh /var/www/html",
]
}
}
Another null resource is used to remotely execute commands that format and mount the EBS volume to the ‘/var/www/html’ directory.
7. Connecting to Ansible Control Node:
resource “null_resource” “nullremote-connect” {
// (Connection details)
provisioner “local-exec” {
command = “echo ‘Connected to AWS instance’”
}
}
This part establishes an SSH connection to the EC2 instance and executes a local command.
8. Copying Instance IP to a Local File:
resource “local_file” “ip” {
content = aws_instance.apache.public_ip
filename = “ip.txt”
}
The public IP of the EC2 instance is saved to a local file named ‘ip.txt’.
9. Copying IP File to Ansible Control Node:
resource “null_resource” “nullremote1” {
// (Connection details)
provisioner “file” {
source = “ip.txt”
destination = “/home/ec2-user/ip.txt”
}
}
This resource copies the ‘ip.txt’ file to the Ansible control node.
10. Installing Ansible on the Remote Machine:
resource “null_resource” “install-ansible” {
// (Connection details)
provisioner “remote-exec” {
inline = [
“sudo amazon-linux-extras install epel -y”,
“sudo yum install -y epel-release”,
“sudo yum install -y ansible”,
]
}
}
Ansible is installed on the remote machine using a null resource and remote-exec provisioner.
11. Uploading Ansible Playbook and Configuration:
resource “null_resource” “run-ansible-playbook2” {
// (Connection details)
provisioner “file” {
source = “./ansible”
destination = “/home/ec2-user/”
}
// (Configuring Ansible and running playbook)
}
This resource uploads Ansible playbook and related files to the remote machine, configures Ansible, and runs the playbook.
The provided Terraform script integrates AWS infrastructure provisioning with Ansible configuration management, automating the deployment and configuration of an Apache web server on an EC2 instance.