Deploy a high-availability web app using CloudFormation — Network Infrastructure
Published: 2023-02-22 18:25:26


## Deploy a high-availability web app using CloudFormation — Network Infrastructure

[CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) is an AWS Solution for deploying infrastructure as code. Resources are grouped as stacks for ease of management.

This lab scenario entails provisioning the required infrastructure and deploying an application to the cloud along with the supporting software. The deployment is automated so that the infrastructure can be torn down as soon as the dev team completes their tests and gather results.

Prerequisites: familiarity with AWS Cloud concepts and YAML.

In this article, we provision the Networking Infrastructure for our deployment in a YAML file. The article is a walkthrough of the YAML file configuration and JSON parameters files we use to deploy our infrastructure. Hyperlinks are provided to the documentation of the concepts and technologies in use. As you build your CloudFormation script, it is essential to reference the documentation as a guideline for creating your resources. Let’s get right to it!

**Network Diagram**

First, we develop a diagram to visualize the design of our deployment and act as a visual aid to understand the CloudFormation script. We use [LucidChart](https://lucidchart.com) for this purpose.

![](https://cdn-images-1.medium.com/max/3752/1*LaaDqjfA8ywcs_3j6syzeA.png)

Our YAML file is divided into four parts; the description, parameters, resources, and output.

**Description and Parameters**
{% gist https://gist.github.com/PaddyAdallah/cf7d5e2e6ac08263c558d249af33ca8b.js %}
The description provides a summary of what our template will deploy. The parameters section contains a list of variables used in our deployments. Any values that might change during our deployment should be declared here and not hard-coded in the script. Each parameter has its properties defined.

From our design diagram, our deployment will have two public and private subnets, each with its CIDR address block. We deploy our application in two [availability zones](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/) (AZ) for high availability. The application will be deployed in private subnets within the AZs, and accessible through the public subnets, with a [NAT Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html) acting as an intermediary for communication between users on the public internet and the application.

**Resources**

In this section, we declare the AWS resources that we use in our stack. Our resources will be created inside a VPC.
{% gist https://gist.github.com/PaddyAdallah/02addf707bb48e450fb81faccd55ba33.js %}
[**Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html)** — we create an Internet Gateway that gives access to inbound and outbound network traffic from the outside into your VPC.
{% gist https://gist.github.com/PaddyAdallah/08483ceae793846868f58fff5fc9fde9.js %}
We then associate the Internet Gateway to our VPC using a [Gateway Attachment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html). Otherwise, our Internet Gateway will not be connected to our VPC network.

**Subnets **— Public and private subnets are the network address allocations we will use in our deployment. We deploy a public and a private subnet in each availability zone using the *Select *function and reference the CIDR blocks created earlier. The function returns a list of AZs, which are indexed 0, 1, etc.

You can see the index being used from the returning AvailabilityZone’s array. Notice that our subnets are not sharing AvailabilityZones.
{% gist https://gist.github.com/PaddyAdallah/d90e2f448b89ac6e11d5f93bafcbf084.js %}
[*MapPublicIpOnLaunch](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html) *indicates whether instances launched on this subnet receive a public IPv4 address.

**NAT Gateway **— we will allow the NAT Gateways to route traffic for our private subnets to the internet while keeping them private, enabling servers in a private subnet to connect to the internet. We place them in our public subnets.
{% gist https://gist.github.com/PaddyAdallah/1276ae7b5ecba7e50edb4859dce7a1e7.js %}
[**Elastic IPs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)**(EIPs) — specifying elastic IP addresses will request AWS to assign persistent public addresses to the NAT Gateway. The benefit of this is in case of maintenance or a restart of the resources, we will retain the public IP address. This is important when you have applications that depend on a particular IP address.
{% gist https://gist.github.com/PaddyAdallah/1afff46e969523cb6f9234edc36b2cc1.js %}
[*DependsOn](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html) *clause instructs CloudFormation to wait on the creation of the specified resource to be completed before the NAT Gateway EIP is created. It will determine the order in which resources are built. In our scenario, once the Internet Gateway is attached and properly working, CloudFormation will do the IP allocation.

[**Route Table](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html) — **controls traffic flow in and out of the subnet through a set of rules. The default route on the PublicRouteTable will route all outbound traffic to the Internet Gateway. The default route on the PrivateRouteTable will route all outbound traffic to the NAT gateways, keeping the traffic from the private subnets within the VPC. We will associate these rules with the public and private subnets, respectively, using the *SubnetRouteTableAssociation* resource.

Routes should be defined starting with the most specific rule and transitioning to the least specific rule. The rules define what resource has access to communicate with another resource. The *DestinationCidrBlock* property is used for destination matching and a wildcard address (0.0.0/0) to reference all traffic.
{% gist https://gist.github.com/PaddyAdallah/af9579d0e48c5c5c2bd8785cdaa64380.js %}
**Outputs**

The output section collects the resources created and turns them into variables for other scripts. We use the [*Sub *function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html) that takes the specified variable and attaches it to the specified text together with a value.
{% gist https://gist.github.com/PaddyAdallah/bfaaee75ce66ae36d32b1ce9d7d0f3cb.js %}
This way, we can pass the variables as inputs for other scripts. In this scenario, the server resources infrastructure team will be able to create a CloudFormation script using output generated from the network infrastructure CloudFormation script.

JSON File

We use the separate parameter file (JSON) to avoid hard-coding parameters in the template (YAML) file. The named parameters in the [**Parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)** section of the CloudFormation template will require a matching value in the separate Parameter file (JSON). Having this additional file with actual parameter values, allows you to change data that is used by your CloudFormation script without the risk of having to modify the script directly and possibly introduce a typo or some sort of logical error.
{% gist https://gist.github.com/PaddyAdallah/a337bf6bd0e6e453a519f7df2ec605d3.js %}
Finally, with [AWS CLI](https://aws.amazon.com/cli/) installed on our local machine, we create the CloudFormation stack by calling the YAML and JSON parameter files and passing them as parameters to the CloudFormation call.

    aws cloudformation create-stack --stack-name ourNetworkInfra --**template**-body file:*//ourinfra.yml    --parameters file://ourinfra.json  --region=us-east-1*

You can view the deployment status through the AWS console or the *describe-stack *option in the CloudFormation command as below:

    aws cloudformation describe-stack --stack-name ourNetworkInfra

![successfully deployed stack](https://cdn-images-1.medium.com/max/2488/1*-_L6TQujluKU2nRCysOZTA.png)

![Stack resources](https://cdn-images-1.medium.com/max/2866/1*hAvjwS_Kpl9yooKZ80IKDQ.png)

For more information on your deployed stack, read the [CloudFormation CLI documentation reference](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/index.html). Feel free to drop your queries in the comment section. I will be happy to revert and learn from you as well.

You will find the GitHub repository for the project containing the complete YAML files and configurations in the link below;

[https://github.com/PaddyAdallah/AWS-Projects/tree/main/cloudformation_project](https://github.com/PaddyAdallah/AWS-Projects/tree/main/cloudformation_project)

In the [**next article](https://medium.com/@Paddy_Adallah/deploy-a-high-availability-web-app-using-cloudformation-servers-and-security-groups-91f88461e595)**, we provision the servers and security groups infrastructure.