Learning Amazon Web Services can be very tricky nowadays with over 100+ services that can satisfy thousands if not hundreds of thousands of use cases. Some use cases could even be solved with more than one service! This vast sea of information can make it challenging for hungry and passionate developers to actually learn the AWS platform.
In my latest course, we focus on learning AWS by actually using it. We focus on the problem of hosting, securing, and delivering static websites on AWS. By focusing on the problem we can start to learn services as we are building a solution. This has been great for folks to jump-start their learning of AWS by leveraging services like S3, CloudFront, WAF, ACM, API Gateway, and Lambda.
Even then there are times where we want to go faster. We want to just start experimenting with AWS and not get bogged down in the plethora of information.
Luckily for us, there is a service that helps us do just that.
Elastic Beanstalk is a great service for dipping your toes into the AWS swimming pool. It allows you as a developer to come with your workload and get it running in three simple steps. Create an Elastic Beanstalk application, create an environment, deploy your code, and boom you're off and running.
In this post, we are going to take a sample .NET Core web API and set it up in Elastic Beanstalk in just a few minutes.
Before we dive into the hands-on portion there is some background that is useful to know.
First, Elastic Beanstalk is a service that provisions, maintains, and deploys the underlying AWS infrastructure for you. This is great, developers that are new to AWS might not understand all of the infrastructure concepts, so Elastic Beanstalk can take a lot of that off their plate. As we are going to see we can configure our environment settings and then just deploy our application to it. Never having to worry about provisioning or maintaining the underlying infrastructure.
If at some point the developer needs to take over some of the infrastructure Elastic Beanstalk supports that. However, there is a point where if you need to start configuring the underlying resources by hand, then using a infrastructure as code tool like Terraform might be a better fit.
For the purposes of this post, we are going to pretend that we are brand new to the cloud world. So we are going to get our environment configured and then demonstrate how to deploy to it right from our IDE.
For the purposes of this post, it might be helpful for you to clone the code I am using throughout this post. So, go ahead and clone this GitHub repository.
This repository contains 3 things that we need to get up and running.
- A folder
vpc.yamlfile. This is a CloudFormation template for creating a new VPC in our AWS account. This takes away the complexity of configuring our public and private subnets.
- A folder
runTests.batfile. This a script we can run once our environment is running our code to populate the demo data.
- A sample .NET Core Web API.
To demonstrate AWS best practices we are going to create a new VPC for our Elastic Beanstalk demo. With repository cloned, let's run the following AWS CLI call:
kylegalbraith:~$ aws cloudformation create-stack --stack-name demo-elasticbeanstalk --template-body file://vpc.yaml
This CLI call provisions a brand new VPC as described in
vpc.yaml in our AWS account. This VPC consists of the following resources:
- 2 Private subnets.
- 2 Public subnets. *An internet gateway and route table for the public subnets.
- A NAT gateway and route table for the private subnets.
Before we can configure our environment, we first must create a application in Elastic Beanstalk. An application holds the environments, configurations, and code versions. It is the top level object in Elastic Beanstalk.
To create our application for our environment and code to live in we can run the following command via the aws-cli.
kylegalbraith:~$ aws elasticbeanstalk create-application --application-name SampleWebApi
Once we have the outer Elastic Beanstalk application we can configure our first environment. A environment is the container that all of our AWS infrastructure belongs to. There are two types of environments that can be created, web server and worker. The former is what we need for our post today, as that will provide the necessary resources to handle HTTP requests. A worker environment is used for processing messages off an SQS queue.
There are multiple ways to configure an environment in Elastic Beanstalk. One of the best ways, when you are just getting started with AWS, is to configure it via the Management Console.
From our new Elastic Beanstalk Application.
- Select "Create Environment" from the Actions menu.
- Select "Web server environment".
- Click "Select".
- In the "Environment name", enter
- Check the "Preconfigured platform", and select ".NET (Windows/IIS)" from the drop-down.
- Leave the "Sample application" checked for the application code.
Before we configure anything else, it's worth understanding what would happen if we clicked "Create environment" right now.
- A new environment would be created with the url,
- The environment would be single instance. Meaning we would not have a load balancer and only one EC2 instance in our autoscaling group.
- Everything would be created with the defaults. This includes our healthcheck url, network layout (VPC, subnets, etc), and instance specifics like type, IAM profile, etc.
The main thing to take away here is that clicking create environment right away will get you a single instance proof of concept in Elastic Beanstalk. For our post, we want more than that.
- So, select "Configure more options".
- Select the preset for High Availability. Notice this changes the "Capacity" section from single instance to load balanced, this is exactly what we want.
- Select "Change platform configuration", and then select
64bit Windows Server 2012 R2 v1.2.0from the drop-down. Note: this is specific to your application, for my demo application I must use Windows Server 2012 instead of 2016.
- Click "Modify" under the Load balancer section.
- For the "Health check path" I am going to enter
/api/demossince that is the default route for my API. When configuring your application you should enter in the url that serves as your healthcheck.
- Click "Save".
- Click "Modify" under the Network section.
- Select the
demo-elasticbeanstalkVPC that we created with our CloudFormation template.
- Leave the "Visibility" option as Public.
- For the "Load balancer subnets" select a public subnet in each availability zone.
- For the "Instance subnets" select the private subnet in each availability zone.
- Click "Save".
- Click "Create Environment".
If you are new to networking your head is likely spinning at this point. That is normal, trust me. For the purpose of this blog post I am going to avoid diving into the details of networking in AWS, but here are the highlights/reasons we configured things the way we just did.
- A Virtual Private Cloud (VPC) is a logically isolated network within our AWS account. We have ad default VPC in our account, this is what we selected.
- A public subnet is a sub-network within the CIDR block range of the VPC. They are public because they have an internet gateway attached to them that allows them to talk to the public intranet. Since our load balancer needs to respond to requests from the internet they are sitting in public subnets.
- A private subnet does not have an internet gateway. It can, however, have a NAT gateway that it is used to talk out to the public internet.
With that explanation of networking out of the way, our environment should be created at this point. Elastic Beanstalk is going through the process of setting up all of the infrastructure our load balanced web server environment needs. This includes:
- The load balancer that will receive our API requests with the health check url to ping on our instances.
- The auto scaling group that our API instances belong to.
- The launch configuration that specifies our EC2 instance type, security groups, and more that is attached to our auto scaling group.
- Default scaling policies for our auto scaling group.
- CloudWatch alarms and metrics for our load balancer and EC2 instances.
All of this is provisioned by Elastic Beanstalk without us having to configure those resources ourselves. This is the main value proposition that the service provides you the developer. You don't need to worry about provisioning, scaling, or maintaining your infrastructure, it is handled for you.
This is great when you are just getting started, but as you progress in AWS you will likely outgrow this need. At some point, if you need to/want to have more control over your infrastructure, you can do that with Elastic Beanstalk, but it may be better to consider true Infrastructure-as-Code as that point. For now, we will consider this the best service for getting started and demonstrate how we can deploy to our new environment.
With those two things installed and configured we can deploy to our environment.
- Open the dotnet core web API in Visual Studio.
- Right-click the API project in the Solution Explorer.
- Click "Publish to Elastic Beanstalk".
- Select the
my-test-apifrom the available environments.
- Click "Next".
- Select Release under "Build Configuration".
- Click "Next".
- Click "Publish".
What happens next is that our API will be compiled, zipped up, uploaded to Elastic Beanstalk as a version, and then deployed to our infrastructure all at once in our current configuration. If we were concerned about downtime we can change our deployment strategy from the environment configuration to do rolling updates. This would incrementally roll out the latest version of our code to the EC2 instances behind our load balancer.
Once our new version is deployed we should see that our environment is Green. We can then hit our own healthcheck url and get a successful response.
kylegalbraith:~$ curl http://my-test-api.elasticbeanstalk.com/api/demos
Elastic Beanstalk is not perfect by any means. However, it is a great place to start if you are just beginning your cloud adventure. It allows you as a developer to get the infrastructure up and running to support your application in just a few minutes. Freeing you up to worry about the code you develop and less about the infrastructure provisioning and scaling.
That said, learning and understanding the concepts that make the cloud powerful is important. So there will likely come a point where you need to understand the infrastructure pieces that Elastic Beanstalk is covering for you. In fact, you may reach a point where you need to take control back. In those scenarios, it is worth considering moving away from Elastic Beanstalk depending on your needs.