In this tutorial I’ll explain how you can setup a secure and high available virtual private cloud architecture and automate the setup using CloudFormation.

We will host a basic high available application inside this VPC.

We will also take the cost into account which means we will not make non-critical resources high available.

High Availability in AWS

In AWS you can deploy resources and use services in different regions like eu-west-1 (EU Ireland), us-east-1 (US N. Virgina), and many more. Every AWS region consists of multiple availability zones. An availability zone (AZ) consists of one ore more data centers which are heavily secured. Availability zones are build tens / hundreds of miles from each other. Because of the distance between AZ’s it’s nearly impossible that both zones are down at the same time because of a disaster like an earthquake, a tsunami, an attack, … .

In the world of AWS the term “High Availability” means that your infrastructure will remain available when one AZ goes down.

Architecture of VPC

Let’s take a look to our Architecture and discuss every component.

Infrastructure side

VPC : Amazon Virtual Private Cloud lets you provision a logically isolated section of the Amazon Web Services (AWS) cloud where you can launch AWS resources. You must specify a range of IPv4 addresses for the VPC in the form of a CIDR block (like 10.0.0.0/16). A VPC spans all availability zones in a region.

→ We need 1 VPC for our setup.

: Amazon Virtual Private Cloud lets you provision a logically isolated section of the Amazon Web Services (AWS) cloud where you can launch AWS resources. You must specify a range of IPv4 addresses for the VPC in the form of a CIDR block (like 10.0.0.0/16). A VPC spans all availability zones in a region. → We need 1 VPC for our setup. Subnet : A VPC contains multiple subnets. A Subnet can be public or private and spans one availability zone. Theren is also a CIDR block for the subnet, which is a subset of the VPC CIDR.

→ We need four subnets for our setup. We will use two public subnets and two private subnets, each in a different availability zone. If one zone goes down we still have a public and private subnet available.

: A VPC contains multiple subnets. A Subnet can be public or private and spans one availability zone. Theren is also a CIDR block for the subnet, which is a subset of the VPC CIDR. → We need four subnets for our setup. We will use two public subnets and two private subnets, each in a different availability zone. If one zone goes down we still have a public and private subnet available. IGW : The Internet Gateway is a resource which enables access to the internet for your VPC. Every subnet which has a route through the IGW to the internet (0.0.0.0/0) is a public subnet. Resources in this subnet can communicate with the internet.

→ We need to deploy only one IGW since it’s high available on it’s own and doesn’t have bandwidth constraints.

: The Internet Gateway is a resource which enables access to the internet for your VPC. Every subnet which has a route through the IGW to the internet (0.0.0.0/0) is a public subnet. Resources in this subnet can communicate with the internet. → We need to deploy only one IGW since it’s high available on it’s own and doesn’t have bandwidth constraints. NAT Gateway : Use a NAT gateway in a public VPC subnet to enable outbound internet traffic from instances in a private subnet. The private subnets need a route through the NAT gateway to the internet.

→ Because of cost perspective we will deploy only one NAT gateway. This has as result that our instances in private subnets will loose internet access when the availability zone in which our NAT is deployed goes down.

This is not critical for our application and the app will remain working. This is the reason why we prefer to spin up a new NAT gateway manually instead of making it high available but of course it is possible to have a NAT gateway deployed in every availability zone.

: Use a NAT gateway in a public VPC subnet to enable outbound internet traffic from instances in a private subnet. The private subnets need a route through the NAT gateway to the internet. → Because of cost perspective we will deploy only one NAT gateway. This has as result that our instances in private subnets will loose internet access when the availability zone in which our NAT is deployed goes down. This is not critical for our application and the app will remain working. This is the reason why we prefer to spin up a new NAT gateway manually instead of making it high available but of course it is possible to have a NAT gateway deployed in every availability zone. Bastion Host : A bastion host is a secure public instance which serves as SSH gateway. We can SSH to this public instance and from inside this instance we can SSH to a private instance using its private IP.

The bastion host is secured by a security group which can limit the SSH access to the instance.

→ We will deploy one bastion host. Again, this instance will be down when the Availability zone in which it’s running is down. But just like the NAT gateway our application won’t be impacted and we decide to make the bastion host not high available. In case of an availability zone outage we can spin up an EC2 inside the public subnet of the working AZ.

You can use autoscaling to make your bastion host high available.

: A bastion host is a secure public instance which serves as SSH gateway. We can SSH to this public instance and from inside this instance we can SSH to a private instance using its private IP. The bastion host is secured by a security group which can limit the SSH access to the instance. → We will deploy one bastion host. Again, this instance will be down when the Availability zone in which it’s running is down. But just like the NAT gateway our application won’t be impacted and we decide to make the bastion host not high available. In case of an availability zone outage we can spin up an EC2 inside the public subnet of the working AZ. You can use autoscaling to make your bastion host high available. Route Table : A route table contains a set of rules, called routes, that are used to determine where network traffic is directed. Each subnet in your VPC must be associated with a route table; the table controls the routing for the subnet. A subnet can only be associated with one route table at a time, but you can associate multiple subnets with the same route table.

→ A Route table is a high available service provided by AWS which replaces the router. We need to configure them, but we don’t have to make them high available.

: A route table contains a set of rules, called routes, that are used to determine where network traffic is directed. Each subnet in your VPC must be associated with a route table; the table controls the routing for the subnet. A subnet can only be associated with one route table at a time, but you can associate multiple subnets with the same route table. → A Route table is a high available service provided by AWS which replaces the router. We need to configure them, but we don’t have to make them high available. Security Group: A security group contains rules to allow who can access the resource to which the security group belongs. In our case we have a security group for our ALB (everyone can visit on port 80), for our bastion host (everyone can SSH on port 22) and for our EC2 instances (only the ALB can access the instances on port 80).

→ Security Groups are high available resources. We don’t need to think about making them high available in our environment.

Application Side

EC2 : Our application, a basic Apache web server is hosted on an EC2 instance.

→ We will deploy two EC2 instances in different subnets because an EC2 will be unavailable when the AZ (and consequently the subnet) in which our EC2 is deployed goes down.

: Our application, a basic Apache web server is hosted on an EC2 instance. → We will deploy two EC2 instances in different subnets because an EC2 will be unavailable when the AZ (and consequently the subnet) in which our EC2 is deployed goes down. Application Load Balancer: The ALB will load balance the traffic to our two EC2 instances. If one of them is down the ALB will route all the traffic to the healthy instance. We can make this more advanced by implementing autoscaling for our instances but this is out of scope for this tutorial.

→ We need to deploy only one ALB. Under the hood an ALB consists of multiple EC2s in multiple subnets and AZ’s. If one AZ goes down, the ALB won’t be impacted. The service is high available because of the smart implementation of AWS.

CloudFormation

The CloudFormation template to setup this whole environment is available on my GitHub. Feel free to fork/star the template.

The template will create the resources which we’ve discussed in the previous chapter. Here you can also check how the configuration of our route tables is implemented. The GitHub Readme also contains a full list of which resources will be created in your Amazon account.

$ aws cloudformation create-stack --stack-name vpc-demo --template-body file://template.yaml --parameters file://parameters.json

Check the URL to visit the ALB and check if you can visit the application.

You can also check if you’re able to use the bastion host.

The ALB routes us to one of our two EC2 instances

Remark: The template is tested in the regions eu-west-1 and us-east-1. If some mapping contains an issue. Feel free to open a Pull Request.

Conclusion

We have learned what high availability means in the world of AWS.

After that we have checked a cost optimized high available AWS environment which contains an Application Load balancer and two EC2’s to host a web application. I hope you enjoyed this tutorial!