DEV Community

Cover image for Add & Configure Resources- CloudFormation for Infrastructure set up-03
Gayan Fonseka for AWS Community Builders

Posted on

Add & Configure Resources- CloudFormation for Infrastructure set up-03

In the previous articles, we looked at an ideal infrastructure set up to host our application. Then we went on to create the VPC and the subnets that were discussed, using CloudFormation. Just having the subnets won't do, we had to create the security groups and the IAM roles that would provide the required permissions and open the ports for the communication. All the above steps were discussed in the previous two articles and the links are given below,

Get rid of old habits- Use CloudFormation for infrastructure set up -01

Configuring Security Groups/IAM roles - CloudFormation for infrastructure set up -02

Now that we have most of the network set up it is time to add some compute resources and have them configured. The whole idea of this exercise is to provide a set of temples that you can easily modify and use to set up your own infrastructure and compute resources and not to detail CloudFormation basics. 

What do we have here? You may want to decide whether you are adding resources for the Production environment or something else like QA or Dev. Depending on the environment the size of your resources may vary and I have showcased how that can be handled by providing the option to select the environment (dev, qa, prod) before the execution of the template.

Also, I hope you can remember me suggesting that it is better to use the SSM agent to connect to the servers as opposed to the bastion host. I have taken the necessary steps to install the SSM agent and to enable it as you can see in the code. Assuming that we'll be using a PHP application, the necessary steps are taken to install the prerequisites.

Having the compute resources in an autoscaling group is key to handling the scaling requirements of the systems. In this sample setup, I have taken the necessary steps to place the resources in autoscaling groups. It's time to share the code that does all this and it is as follows.

########################################################################
# Compute & Network resources Configurations (ALB,EC2,ASG,Listners,TG) #
########################################################################
---
Parameters:
EnvType:
Description: Select the Environment to create
Type: String
Default: dev
AllowedValues:
- dev
- qa
- prod
ConstraintDescription: Must specify the environment
AbcKey:
Description: AbcKey is a name of an existing EC2 KeyPair to enable SSH access to the instances.
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: Must be the name of an existing EC2 KeyPair.
Conditions:
CreateProdResources: !Equals [ !Ref EnvType, prod ]
CreateQAResources: !Equals [ !Ref EnvType, qa ]
CreateDevResources: !Equals [ !Ref EnvType, dev ]
Resources:
#Internal App Subnet ALBs and Configurations
InternalALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: InternalAppALB
Scheme: internet-facing
SecurityGroups:
- !ImportValue ALBSG
Subnets:
- !ImportValue PublicSubnet01
- !ImportValue PublicSubnet02
Type: application
InternalALBListner:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref InternalALB
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref AdminAppTargetGroup
AdminListnerRules:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref AdminAppTargetGroup
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- inventory.abc.com
ListenerArn: !Ref InternalALBListner
Priority: 1
InventListnerRules:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref InventoryAppTargetGroup
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- admin.abc.com
ListenerArn: !Ref InternalALBListner
Priority: 2
AdminAppTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: AdminAppTG
TargetType: instance
HealthCheckEnabled: true
HealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 10
UnhealthyThresholdCount: 3
HealthCheckPath: /index.html
VpcId: !ImportValue AbVPC
Port: 80
Protocol: HTTP
InventoryAppTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: InventoryAppTG
TargetType: instance
HealthCheckEnabled: true
HealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 10
UnhealthyThresholdCount: 3
HealthCheckPath: /index.html
VpcId: !ImportValue AbVPC
Port: 80
Protocol: HTTP
ExConnALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: ExConnALB
Scheme: internal
SecurityGroups:
- !ImportValue ExConnALBSG
Subnets:
- !ImportValue ExternalAppSub01
- !ImportValue ExternalAppSub02
Type: application
ExConnALBListner:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref ExConnALB
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref ExConnTargetGroup
ExConnTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: ExConnALBTG
TargetType: instance
HealthCheckEnabled: true
HealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 10
UnhealthyThresholdCount: 3
HealthCheckPath: /companies
VpcId: !ImportValue AbVPC
Port: 5000
Protocol: HTTP
########################################
#Launch Configurations with AutoScaling #
########################################
ExConnLC:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
LaunchConfigurationName: ExConnLC
Condition: CreateProdResources
InstanceType: !If [ CreateProdResources, t2.large, t2.micro]
ImageId: "ami-0f86a70488991335e"
KeyName: !Ref AbcKey
IamInstanceProfile: !ImportValue Ec2InstanceProfile
SecurityGroups:
- !ImportValue Ec2SG
UserData:
Fn::Base64: |
#!/bin/bash
sudo yum update -y
sudo yum install python3 git wget -y
sudo pip3 install flask
sudo dnf install -y https://s3.ap-south-1.amazonaws.com/amazon-ssm-ap-south-1/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl start amazon-ssm-agent
sudo systemctl enable amazon-ssm-agent
echo "healthy" > /var/www/html/healthy.html
wget https://aws-codedeploy-ap-southeast-1.s3.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
AdminLC:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
LaunchConfigurationName: AdminLC
Condition: CreateProdResources
InstanceType: !If [ CreateProdResources, t2.large, t2.micro]
ImageId: "ami-0f86a70488991335e"
KeyName: !Ref AbcKey
IamInstanceProfile: !ImportValue Ec2InstanceProfile
SecurityGroups:
- !ImportValue Ec2SG
UserData:
Fn::Base64: |
#!/bin/bash
sudo yum update -y
sudo yum install httpd php mysql php-mysqli git ruby wget -y
sudo dnf install -y https://s3.ap-south-1.amazonaws.com/amazon-ssm-ap-south-1/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl start amazon-ssm-agent
sudo systemctl enable amazon-ssm-agent
echo "healthy" > /var/www/html/healthy.html
groupadd www
usermod -aG www ec2-user
chown -R root:www /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
mkdir -p /var/www/inc
wget https://raw.githubusercontent.com/ecloudvalley/AWS-Read-Replica-RDS-Database/master/SamplePage.php
mv SamplePage.php /var/www/html/
echo "server " > /var/www/html/index.html
cd /home/ec2-user
wget https://aws-codedeploy-ap-southeast-1.s3.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
chkconfig httpd on
systemctl start httpd
InventLC:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
LaunchConfigurationName: InventLC
Condition: CreateProdResources
InstanceType: !If [ CreateProdResources, t2.large, t2.micro]
ImageId: "ami-0f86a70488991335e"
KeyName: !Ref AbcKey
IamInstanceProfile: !ImportValue Ec2InstanceProfile
SecurityGroups:
- !ImportValue Ec2SG
UserData:
Fn::Base64: |
#!/bin/bash
sudo yum update -y
sudo yum install httpd php mysql php-mysqli git ruby wget -y
sudo dnf install -y https://s3.ap-south-1.amazonaws.com/amazon-ssm-ap-south-1/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl start amazon-ssm-agent
sudo systemctl enable amazon-ssm-agent
echo "healthy" > /var/www/html/healthy.html
groupadd www
usermod -aG www ec2-user
chown -R root:www /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
mkdir -p /var/www/inc
wget https://raw.githubusercontent.com/ecloudvalley/AWS-Read-Replica-RDS-Database/master/SamplePage.php
mv SamplePage.php /var/www/html/
echo "server " > /var/www/html/index.html
cd /home/ec2-user
wget https://aws-codedeploy-ap-southeast-1.s3.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
chkconfig httpd on
systemctl start httpd
CoreBELC:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
LaunchConfigurationName: CoreBELC
Condition: CreateProdResources
InstanceType: !If [ CreateProdResources, t2.large, t2.micro]
ImageId: "ami-0f86a70488991335e"
KeyName: !Ref AbcKey
IamInstanceProfile: !ImportValue Ec2InstanceProfile
SecurityGroups:
- !ImportValue Ec2SG
UserData:
Fn::Base64: |
#!/bin/bash
sudo yum update -y
sudo yum install httpd php mysql php-mysqli git ruby wget -y
sudo dnf install -y https://s3.ap-south-1.amazonaws.com/amazon-ssm-ap-south-1/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl start amazon-ssm-agent
sudo systemctl enable amazon-ssm-agent
echo "healthy" > /var/www/html/healthy.html
groupadd www
usermod -aG www ec2-user
chown -R root:www /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
mkdir -p /var/www/inc
wget https://raw.githubusercontent.com/ecloudvalley/AWS-Read-Replica-RDS-Database/master/SamplePage.php
mv SamplePage.php /var/www/html/
echo "server " > /var/www/html/index.html
cd /home/ec2-user
wget https://aws-codedeploy-ap-southeast-1.s3.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
chkconfig httpd on
systemctl start httpd
AdminEc2AutoScaling:
Type: AWS::AutoScaling::AutoScalingGroup
DependsOn: AdminTargetGroup
Properties:
AutoScalingGroupName: AdminEc2AutoScalingGroup
VPCZoneIdentifier:
- !ImportValue InternalAppSub01
- !ImportValue InternalAppSub02
LaunchConfigurationName: !Ref AdminLC
DesiredCapacity: !If [ CreateProdResources, '4', '1']
MinSize: !If [ CreateProdResources, '4', '1']
MaxSize: !If [ CreateProdResources, '4', '1']
TargetGroupARNs:
- !Ref AdminAppTargetGroup
Tags:
- Key: Name
Value: AdminPortal
InventoryEc2AutoScaling:
Type: AWS::AutoScaling::AutoScalingGroup
DependsOn: InventoryTargetGroup
Properties:
AutoScalingGroupName: InventoryEc2AutoScalingGroup
VPCZoneIdentifier:
- !ImportValue InternalAppSub01
- !ImportValue InternalAppSub02
LaunchConfigurationName: !Ref InventLC
DesiredCapacity: !If [ CreateProdResources, '4', '1']
MinSize: !If [ CreateProdResources, '4', '1']
MaxSize: !If [ CreateProdResources, '4', '1']
TargetGroupARNs:
- !Ref InventoryAppTargetGroup
Tags:
- Key: Name
Value: InventoryPortal
ExConnEc2AutoScaling:
Type: AWS::AutoScaling::AutoScalingGroup
DependsOn: ExConnTargetGroup
Properties:
AutoScalingGroupName: ExConnEc2AutoScalingGroup
VPCZoneIdentifier:
- !ImportValue ExternalAppSub01
- !ImportValue ExternalAppSub02
LaunchConfigurationName: !Ref ExConnLC
DesiredCapacity: !If [ CreateProdResources, '4', '1']
MinSize: !If [ CreateProdResources, '4', '1']
MaxSize: !If [ CreateProdResources, '4', '1']
TargetGroupARNs:
- !Ref ExConnTargetGroup
Tags:
- Key: Name
Value: ExternalConnector
CoreBEEc2AutoScaling:
Type: AWS::AutoScaling::AutoScalingGroup
DependsOn: ExConnTargetGroup
Properties:
AutoScalingGroupName: CoreBEEc2AutoScalingGroup
VPCZoneIdentifier:
- !ImportValue ExternalAppSub01
- !ImportValue ExternalAppSub02
LaunchConfigurationName: !Ref ExConnLC
DesiredCapacity: !If [ CreateProdResources, '4', '1']
MinSize: !If [ CreateProdResources, '4', '1']
MaxSize: !If [ CreateProdResources, '4', '1']
TargetGroupARNs:
- !Ref ExConnTargetGroup
Tags:
- Key: Name
Value: CoreBackEnd
#Customer Backend Instance creation
CustomerBackend:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: "ami-00b8d9cb8a7161e41"
KeyName: !Ref AbcKey
SubnetId: !Ref ExternalAppSub01
SecurityGroupIds:
- !GetAtt Ec2SG.GroupId
Tags:
- Key: Name
Value: CustomerBackend
Outputs:
#VPC
alblistner:
Description: Information about ALB Listner details
Value: !Ref ExConnALBListner
Export:
Name: ExConnectorListner

Now you are good to go ahead and run the CloudFormation (yaml) files in the three articles to set up the infrastructure suggested by me. It would be easier to get these into three files before execution. You can easily modify this to include additional resources, change the configuration of the resources, or both.

Also, there is a VSCode plug-in that you can use while doing templates named CloudFomration Snippets. This can come in handy with auto-completion.

Screenshot 2021-04-06 at 15.49.29

All the other resources such as API Gateway, VpcLink, API endpoints and etc can be configured with CloudFormation Templates. This would be the next step for you to try. Hope these three articles were helpful and thanks a lot for reading.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Create a simple OTP system with AWS Serverless cover image

Create a simple OTP system with AWS Serverless

Implement a One Time Password (OTP) system with AWS Serverless services including Lambda, API Gateway, DynamoDB, Simple Email Service (SES), and Amplify Web Hosting using VueJS for the frontend.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay