Full Blog TOC

Full Blog Table Of Content with Keywords Available HERE

Tuesday, February 16, 2021

CloudFormation - Create a VPC and an EC2 based Web Server



 

In the previous post, we've used AWS console to create a VPC, and deployment of a sample web server on a new EC2 instance.

However, if there is a need to deploy this automatically, we can use AWS CloudFormation.

The CloudFormation uses a template YAML or JSON file (aka stack) to create AWS entities. 

Unlike AWS CLI, the CloudFormation support add, update, and delete of the AWS entities as a transaction, so if one of the entities creation had failed, the entire entities in the stack will be rolledback. Also, update of the AWS entities in the template file, will update only the required items in the stack.



Stack Install and Update


To use the CloudFormation, I've found the best method is to use a CLI, which installs or updates the stack, based of if it exists or not. 


deploy.sh

#!/bin/bash
set -e
cd "$(dirname "$0")"
deployFolder=${PWD}

export AWS_SHARED_CREDENTIALS_FILE=${deployFolder}/aws-config/credentials
export AWS_CONFIG_FILE=${deployFolder}/aws-config/config
export AWS_PAGER=""


stackName=mystack
stackExists=$(aws cloudformation describe-stacks | jq -r ".Stacks[].StackName" | grep ${stackName} | wc -l)
if [[ "${stackExists}" = "0" ]]; then
echo "install stack"
aws cloudformation create-stack --stack-name ${stackName} --template-body file://po.yaml
aws cloudformation wait stack-create-complete --stack-name ${stackName}
else
echo "update stack"
aws cloudformation update-stack --stack-name ${stackName} --template-body file://po.yaml
aws cloudformation wait stack-update-complete --stack-name ${stackName}
fi



The Template File


The template file can handle all AWS entities, except for the key pair for EC2, that we need to manually create in advanced. Let review the parts of the template file.


Parameters:
LatestAmiId:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'


This fetch from AWS the latest Linux 64 buts image ID. We will later use it for the EC2 instance configuration.


Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: sample-vpc


Now we present the resources that we want to configure, starting with the VPC configuration. Next we want to configure the subnet.


Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: us-east-1a
Tags:
- Key: Name
Value: sample-subnet1



Notice that the subnet configuration requires the VPC ID. Here we use the CloudFront template function !Ref to fill this information. Next we add the internet gateway, and assign it to the VPC.


InternetGateway:
Type: AWS::EC2::InternetGateway
DependsOn: VPC
Properties:
Tags:
- Key: Name
Value: sample-route-table
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway


Using the AWS console handles these two resources in one dialog, but in the template file, we are exposed to the real AWS implementation, hence we are required to make some more configuration.

Let's add the route table, and add the internet gateway route:


RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: sample-route-table
RouteTableAssociate:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: Subnet1
RouteTableId:
Ref: RouteTable
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway



And lastly, add the EC2 instance, and  assign an elastic IP to it.



SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: the ec2 security group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: sample-ec2-security-group
EC2:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: !Ref LatestAmiId
SubnetId: !Ref Subnet1
KeyName: PO
SecurityGroupIds:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: sample-web
ElasticIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
InstanceId: !Ref EC2
Tags:
- Key: Name
Value: sample-elastic-ip



Final Note


In this post we have reviewed usage of AWS CloudFormation to create AWS entities for VPC, and a EC2 instance on it, which is available as a web server. The CloudFormation is a great tool for automation, and to keep AWS entities configuration. CloudFormation GUI designer can also be used to create the file.

For clarify purpose, I attach the entire file here.


Parameters:
LatestAmiId:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: sample-vpc
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: us-east-1a
Tags:
- Key: Name
Value: sample-subnet1
Subnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: us-east-1b
Tags:
- Key: Name
Value: sample-subnet1
InternetGateway:
Type: AWS::EC2::InternetGateway
DependsOn: VPC
Properties:
Tags:
- Key: Name
Value: sample-route-table
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: sample-route-table
RouteTableAssociate:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: Subnet1
RouteTableId:
Ref: RouteTable
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: the ec2 security group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: sample-ec2-security-group
EC2:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: !Ref LatestAmiId
SubnetId: !Ref Subnet1
KeyName: PO
SecurityGroupIds:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: sample-web
ElasticIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
InstanceId: !Ref EC2
Tags:
- Key: Name
Value: sample-elastic-ip


No comments:

Post a Comment