Terraform excels in infrastructure management with a declarative approach for provisioning and life cycle management. Ansible focuses on configuration management and application deployment using an imperative style, making it less suited for full infrastructure control than Terraform.
How to deploy an EC2 instance using Ansible
Key takeaways:
Ansible automates tasks like provisioning and application deployment using modules via SSH.
Create a security group to limit traffic to public port
3000.Use a YAML playbook to define tasks for creating the security group and launching the EC2 instance.
The security group allows TCP communication on port
3000with all outbound traffic permitted.Launch an EC2 instance specifying AMI, instance type, and a user data script for setup.
The user data script updates packages, installs Node.js, clones a GitHub repository, and runs the Node.js app.
AWS credentials are needed to run the code, executed with Ansible commands.
The application can take up to 2 minutes to be accessible at the public IP on port
3000.
Ansible is an open-source automation tool designed to streamline provisioning, configuration management, application deployment, and orchestration tasks. It connects nodes and deploys small programs called Ansible modules to execute tasks. These modules run over SSH (or alternative protocols if SSH is unavailable) and are removed once the tasks are completed.
In this Answer, we will create a security group and set up a React application on an EC2 instance, ensuring the instance’s security by using only public port 3000.
We will examine the code, provision the infrastructure, and finally create the security group. After that, we’ll launch an EC2 instance to host the React application, configuring it by specifying its
Here is an architecture diagram of the provisioned infrastructure.
Create a security group
A security group manages the inbound and outbound traffic for an associated resource. In other words, it acts as a firewall for the resource. We will create a security group to allow limited access to our EC2 instance; the security group instance_sg will only use public port 3000 to ensure the security of the EC2 instance.
# This playbook creates an AWS Security Group and outputs its ID- name: Create AWS Security Grouphosts: localhostgather_facts: no # Facts are not needed for localhosttasks:- name: Create a security groupamazon.aws.ec2_group:name: allow-port-3000 # Name of the security groupdescription: Allow incoming traffic on port 3000 # Description of the security groupregion: us-east-1 # AWS region where the security group will be created; change as neededrules:- proto: tcp # Protocol for the rule (TCP in this case)from_port: 3000 # Starting port for the ruleto_port: 3000 # Ending port for the rulecidr_ip: 0.0.0.0/0 # CIDR block to allow access from (0.0.0.0/0 means from anywhere)rules_egress:- proto: all # Protocol for the egress(outbound) rule (all protocols)from_port: 0 # Starting port for the egress ruleto_port: 0 # Ending port for the egress rulecidr_ip: 0.0.0.0/0 # CIDR block to allow egress to (0.0.0.0/0 means to anywhere)register: sg # Register the result in the variable 'sg'- name: Output the security group IDdebug:msg: "Security Group ID is {{ sg.group_id }}" # Output the ID of the created security group
Explanation
Let’s take a look at the above code and understand it.
Line 1: Marks the beginning of the YAML file.
Line 2: Name of the playbook. It gives an idea of what the playbook does.
Line 3: Specifies that the playbook will run on the local machine (the control node where Ansible is executed).
Line 4: Disables fact gathering, a process where Ansible collects details about the hosts. It’s unnecessary here because the tasks only interact with AWS and don’t require information about the local machine.
Lines 6–26 :
tasks:Create a security groupemploysamazon.aws.ec2_group. The module defines the group’s attributes, including its name, description, and regional placement. Through specified rules, the playbook configures inbound traffic through specified rules to permit TCP communication on port3000from any source IP while allowing all outbound(Egress) traffic. The results are registered in the variablesg.Lines 23–25: After execution, the playbook captures the newly created security group’s details into the variable
sg. Subsequently, a debug message displays the security group’s ID,
Create an EC2 instance
---- name: Launch AWS EC2 Instance # Name of the playbookhosts: localhost # Run on the local machinegather_facts: no # Disable gathering facts about the local machinetasks:- name: Launch EC2 instance # Task to launch an EC2 instanceamazon.aws.ec2_instance: # Using the EC2_instance module from the AWS collectionami: "ami-0fa1ca9559f1892ec" # ID of the Amazon Machine Image (AMI)instance_type: "t2.micro" # Type of EC2 instancekey_name: null # Name of the key pair for SSH authentication (null means none)security_groups: # List of security groups for the instance- "{{ aws_security_group.instance_sg.name }}" # Reference to the security group created earlieruser_data: | # User data script to be executed on instance launch#!/bin/bashsudo yum -y update && \sudo yum -y install git && \sudo yum install https://rpm.nodesource.com/pub_16.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y && \sudo yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 && \git clone https://github.com/theHaziqali/my-reactapp.git && \cd my-reactapp && \npm install && \npm starttags: # Tags for the EC2 instanceName: "clab-app" # Name tag for identifying the instanceregister: ec2post_tasks:- name: Output the public IP # Task to output the public IP of the instancedebug:msg: "Public IP is {{ ec2.instances[0].public_ip }}" # Output the public IP of the first instance created
Explanation
Let’s take a look at the above code and understand it.
Lines 6–25: Orchestrates the launch of an AWS EC2 instance, specifying the
, instance type, and security group. A user data script is provided to execute commands upon instance launch, such as updating packages, installing Node.js, cloning a GitHub repository, and starting a Node.js application.AMI An Amazon Machine Image (AMI) is a pre-configured template for EC2 instances that includes the operating system, application server, and applications. It allows you to quickly launch new instances with identical configurations. Lines 27–30: After the task execution, a debug message outputs the public IP address of the launched EC2 instance.
Now that we clearly understand each Ansible task we will use, let’s provision the infrastructure.
Configure resources
We have assembled the above-discussed code and used AWS credentials to access the account and deploy infrastructure in the specified region.
Before we deploy the infrastructure on AWS, we need credentials to log in. Enter your AWS access_key_id and secret_access_key in the widget below before running any commands.
- name: Create AWS Security Group and Launch EC2 Instance
hosts: localhost
gather_facts: no
tasks:
- name: Create AWS Security Group
amazon.aws.ec2_group:
name: allow-port-3000
description: Allow incoming traffic on port 3000
region: us-east-1 # Change to your desired region
rules:
- proto: tcp
from_port: 3000
to_port: 3000
cidr_ip: 0.0.0.0/0
rules_egress:
- proto: all
from_port: 0
to_port: 0
cidr_ip: 0.0.0.0/0
register: sg
- name: Launch EC2 instance
amazon.aws.ec2_instance:
image_id: "ami-0fa1ca9559f1892ec"
instance_type: "t2.micro"
key_name: null
security_groups:
- "{{ sg.group_id }}"
user_data: |
#!/bin/bash
sudo yum -y update && \
sudo yum -y install git && \
sudo yum install https://rpm.nodesource.com/pub_16.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y && \
sudo yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 && \
git clone https://github.com/theHaziqali/my-reactapp.git && \
cd my-reactapp && \
npm install && \
npm start
tags:
Name: "clab-app"
register: ec2
- name: Output the public IP of the EC2 instance
debug:
msg: "Public IP is {{ ec2.instances[0].public_ip_address }}"
Click the “Run” button and type the following command to execute the Ansible playbook.
ansible-playbook main.yaml
Note: The application may take upto two minutes to be available after running the EC2 instance.
Copy the public IP from the terminal, paste it into the address bar of the new web page, and add the port 3000 at the end.
<Public_IP_Address>:3000
Congratulations!. Our application is live.
Conclusion
Ansible provides a streamlined method to deploy applications on AWS EC2, ensuring security through careful traffic management. By following the steps outlined, users can efficiently set up and run their applications in the cloud, leveraging Ansible's automation capabilities for a smoother deployment experience.
Frequently asked questions
Haven’t found what you were looking for? Contact Us
Why is Terraform better than Ansible?
How can you stop an EC2 instance using an Ansible Playbook?
How do I automatically shut down my EC2 instance?
Free Resources