I Tried Deploying an EC2 Web Server with CloudFormation and Ansible

2023.08.03

In this blog, I will walk you through the process of deploying an EC2 instance using CloudFormation and then configuring a web server in it using Ansible. i will be using personal laptop as an Ansible controller for seamless management and configuration.

Prerequisites

  • Install Ansible using Homebrew:
brew install ansible
  • Make sure you have AWS CLI installed and configured with your credentials.

Cloudformation Template for EC2 and Networking

save this file with name ec2.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: this template will create ec2

Parameters:
  Keypair:
    Description: please enterthe name of keypair available in ap-northeast-1a
    Type: String
    Default: web

  SystemName:
    Description: this name will be the prefix of all the resources.
    Type: String
    Default: Web

  VpcCidr:
    Description: CIDR Blocjk for the VPC . the Cidr dhould be unique in your environment
    Type: String
    Default: 10.0.0.0/18

  InstanceType:
    Description: please selecet based on performance and network requirement
    Type: String
    Default: t3.micro

  AmiId:
    Description: make sure your ami is of correct region
    Type: String
    Default: ami-0947c48ae0aaf6781

  SubnetCidr:
    Description: this is the CIDR of public Subnet which should lie between VPC CIDR and should have enough capacity with 5 IPs for aws
    Type: String
    Default: 10.0.0.1/24

Resources:
##########################
#Network
#########################
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-vpc

  IGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-IGW

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref IGW

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      VpcId: !Ref VPC
      CidrBlock: !Ref SubnetCidr
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-publicsubnet

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-RouteTable

  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW

  PublicRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

#############################
#EC2
#############################

  EIP1:
    Type: AWS::EC2::EIP

  EniAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt EIP1.AllocationId
      InstanceId: !Ref ServerInstance

  ServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId : !Ref AmiId
      InstanceType: !Ref InstanceType
      KeyName : !Ref Keypair
      SubnetId : !Ref PublicSubnet
      SecurityGroupIds:
           - !Ref SecGroup
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}

  SecGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: serverinstance-sg
      GroupDescription: thi is the security group for web server
      VpcId: !Ref VPC
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
        -
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-sg

Deploy EC2 Server

  •  Run the CloudFormation template to create an EC2 instance. Replace `Your-Keypair-Name` with your keypair name:
aws cloudformation deploy --template-file ec2.yml --stack-name ec2 --region ap-northeast-1 --parameter-overrides keypair=Your-Keypair-Name

Note: This will create the EC2 instance using the specified CloudFormation template. Make sure to change the Keypair parameter to match your keypair file.

  •  Update the values in the `inventory.txt` file with the appropriate username and host information.

save the bellow code with file name inventory.txt

# Inventory file for Ansible playbook

# Group definition for the EC2 instance(s) to manage
[web_ec2_instance]

# Define the hostname or IP address of the EC2 instance
# Replace 'xx.xx.xx.xxx' with the actual IP address or hostname of the EC2 instance
# Define the SSH user to be used for connecting to the EC2 instance (in this case, 'ec2-user')
# Define the SSH connection type ('ssh' in this case)
# Define the path to the private key file ('xxx.pem') for SSH authentication
web ansible_host=xx.xx.xx.xxx ansible_user=ec2-user ansible_connection=ssh ansible_ssh_private_key_file=/.ssh/xxx.pem

Ansible Configuration

Save the below template with name playbook.yml

# Play 1: Install httpd package on all hosts
- 
  name: play 1
  hosts: all # Replace with the target host/group where you want to create the file
  become: true
  tasks:
    - 
      name: Install httpd
      yum:
        name: httpd
        state: present

# Play 2: Start the httpd service on all hosts
- 
  name: play 2
  hosts: all  # Replace with the target host/group where the service should be started
  become: true
  tasks:
    - 
      name: Start the httpd service
      service:
        name: httpd  
        state: started

# Play 3: Create an index.html file on all hosts
- 
  name: play 3
  hosts: all  
  become: true
  tasks:
    - 
      name: Create the index.html file
      file:
        path: /var/www/html/index.html  
        state: touch

# Play 4: Append a line to the index.html file on all hosts
- 
  name: play 4
  hosts: all
  become: true
  tasks:
    - 
      name: Append line to index.html
      lineinfile:
        path: /var/www/html/index.html
        line: '<h1>Hello, World!</h1>'
  •  Run the Ansible playbook to configure the server. Make sure to specify the inventory file:
ansible-playbook playbook.yml -i inventory.txt

The playbook will execute tasks defined in playbook.yml on the target hosts specified in the inventory.txt file.

Conclusion

With this combined approach, you can quickly and confidently deploy and manage your EC2 web server, ensuring a reliable and scalable infrastructure for your applications. Embrace the power of CloudFormation and Ansible, and take your infrastructure management to the next level. Happy deploying!