Loading
Reza Chegini

Junior DevOps Engineer

Junior Cloud Engineer

Junior Site Reliability Engineer

Software Engineer

Backend Developer

Reza Chegini

Junior DevOps Engineer

Junior Cloud Engineer

Junior Site Reliability Engineer

Software Engineer

Backend Developer

Blog Post

AWS CloudFormation in Action: Automating EC2 and Tomcat Setup

AWS CloudFormation in Action: Automating EC2 and Tomcat Setup

1. CloudFormation Overview: The Big Picture

CloudFormation is AWS’s Infrastructure as Code (IaC) tool. It allows you to describe your AWS resources in a declarative way using templates. The main advantages include:

  • Automation: Resources are provisioned automatically, eliminating manual effort.
  • Consistency: Ensures identical configurations across environments (e.g., development, production).
  • Reusability: Templates can be reused, saving time and reducing errors.

2. Parameters: Customizing Your Stack

Parameters are like variables in programming, making the template dynamic and reusable.

Key Concepts:

  1. Environment-Specific Configuration:
EnvironmentName:
  Description: Select the environment
  Type: String
  Default: dev
  AllowedValues:
    - dev
    - prod 
  • Scenario: You may want fewer resources in dev to save costs and more robust configurations in prod.
  • ConstraintDescription: Adds clarity by showing users why only specific values are allowed.

EC2 Instance Types:

InstanceType:
  Description: Select the ec2 instance type
  Type: String
  Default: t2.micro
  AllowedValues:
    - t2.micro
    - t2.small
    - t2.medium
  • Scalability: Start small (t2.micro) for development and scale up (t2.medium) as workloads grow.
  • Flexibility: Parameterizing instance types lets users adapt the infrastructure to their needs.

Availability Zone (AZ) Selection:

AvailabilityZone:
  Description: select the availability zone
  Type: String
  Default: us-east-2a
  AllowedValues:
    - us-east-2a
    - us-east-2b
    - us-east-2c 

High Availability: Distribute resources across AZs to prevent single points of failure


3. Metadata: Enhancing User Experience

Grouping Parameters for Clarity

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "EC2 Instance Configuration"
        Parameters:
          - InstanceType
          - KeyName
          - AvailabilityZone 
  • Purpose: Makes the stack creation interface more intuitive for users.
  • Example: When creating the stack in the AWS Management Console, users will see a logical grouping of options (e.g., instance type, SSH key).

Adding Descriptive Labels

ParameterLabels:
  KeyName:
    default: "Be aware that once keyname is selected we cannot change it unless instance replaced" 
  • Importance: Provides clear instructions, reducing potential errors (e.g., understanding the immutability of SSH keys).

4. Conditions: Logical Resource Creation

Conditions allow for intelligent provisioning of resources.

Example: Elastic IP for Production Only

Conditions:
  CreateEIPForProd: !Equals [ !Ref EnvironmentName, prod ]
  • Cost Optimization: Elastic IPs incur charges when not in use. Only provisioning them for prod saves money.
  • Dynamic Infrastructure: The same template serves both development and production needs.

5. Resources: Core Infrastructure

Security Groups: Defining Network Access

MySecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '8080'
        ToPort: '8080'
        CidrIp: 0.0.0.0/0 
  • Purpose: Controls which IP addresses and ports can access your instance.
  • Example Use Cases:Port 22: Securely SSH into the instance.Port 8080: Access the Tomcat server running the web application.

EC2 Instance: The Workhorse

MyVMInstance:
  Type: AWS::EC2::Instance
  Properties:
    ImageId: ami-063d43db0594b521b
    InstanceType: !Ref InstanceType
    KeyName: !Ref KeyName
    UserData:
      Fn::Base64: |
        #!/bin/bash
        sudo yum update
        sudo yum -y erase java-1.7.0-openjdk.x86_64
        sudo yum -y install java-1.8.0-openjdk.x86_64
        sudo yum -y install tomcat8
        service tomcat8 start 
  • What’s Happening:The specified AMI is used as a base image.Bootstrapping (UserData) installs Java 1.8, removes Java 1.7, and starts Tomcat.A simple web page is created at index.html.

Elastic IP: Static IP for Production

MyProdEIP:
  Type: AWS::EC2::EIP
  Condition: CreateEIPForProd
  • Why It Matters: A static IP ensures your app’s endpoint doesn’t change, critical for production environments.

6. Outputs: Delivering Results

Outputs provide post-deployment information, improving usability.

Example: App URL

Outputs:
  AppURL:
    Description: Tomcat App Access URL
    Value: !Sub 'http://${MyVMInstance.PublicDnsName}:8080/index.html' 

Use Case: After deployment, users can immediately access the app without searching for the instance’s public DNS name.


Why Is This Template Useful?

  1. Flexibility: Parameters allow users to customize deployments for different environments.
  2. Cost-Effectiveness: Conditional logic ensures resources like Elastic IPs are created only when necessary.
  3. Automation: UserData scripts automate configuration, reducing manual effort.
  4. Scalability: This approach can be expanded to include additional instances, load balancers, or other resources.
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  EnvironmentName:
    Description: Select the environment
    Type: String
    Default: dev
    AllowedValues:
    - dev
    - prod
    ConstraintDescription: must be development or production
  InstanceType:
    Description: Select the ec2 instance type
    Type: String
    Default: t2.micro
    AllowedValues:
    - t2.micro
    - t2.small
    - t2.medium
  KeyName:
    Description: Key name to SSH to VM's.
    Type: AWS::EC2::KeyPair::KeyName
  AvailabilityZone:
    Description: select the availability zone
    Type: String
    Default: us-east-2a
    AllowedValues:
    - us-east-2a
    - us-east-2b
    - us-east-2c

Conditions:
  CreateEIPForProd: !Equals [ !Ref EnvironmentName, prod ]

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "EC2 Instance Configuration"
      Parameters:
      - InstanceType
      - KeyName
      - AvailabilityZone
    - Label:
        default: "Environment Configuration"
      Parameters:
      - EnvironmentName
    ParameterLabels:
      EnvironmentName:
        default: "Which environment we are planning to create this instance?"
      KeyName:
        default: "Be aware that once keyname is selected we cannot change it unless instance replaced"

Resources:
  MySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: My SG with port 22, 8080 and 80 inbound
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '8080'
        ToPort: '8080'
        CidrIp: 0.0.0.0/0

  MyVMInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-063d43db0594b521b
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      AvailabilityZone: !Ref AvailabilityZone
      SecurityGroups:
      - !Ref MySecurityGroup
      UserData:
        Fn::Base64: |
          #!/bin/bash
          sudo yum update
          sudo yum -y erase java-1.7.0-openjdk.x86_64
          sudo yum -y install java-1.8.0-openjdk.x86_64
          sudo yum -y install java-1.8.0-openjdk-devel
          sudo yum -y install tomcat8
          service tomcat8 start
          mkdir /usr/share/tomcat8/webapps/ROOT
          touch /usr/share/tomcat8/webapps/ROOT/index.html
          echo "Cloud Formation Tomcat8" > /usr/share/tomcat8/webapps/ROOT/index.html

  MyProdEIP:
    Type: AWS::EC2::EIP
    Condition: CreateEIPForProd
    Properties:
      InstanceId: !Ref MyVMInstance

Outputs:
  AppURL:
    Description: Tomcat App Access URL
    Value: !Sub 'http://${MyVMInstance.PublicDnsName}:8080/index.html'
Tags:
Write a comment