19. July 2019
7 min

Deployment of a Spring Boot application using AWS Elastic Beanstalk, Amazon Route 53 and AWS Certificate Manager

This post describes the usage of the standard AWS command line to deploy a Spring Boot service using AWS Elastic Beanstalk as the runtime environment. To be able to call the service with a user-friendly name and the https protocol, Amazon Route 53 as a Domain Name Service and AWS Certificate Manager are part of the solution as well.

Background

The focus of the blog post is the usage of the AWS command line and not the creation of a Spring Boot application. So, the following prerequisites exist:

  1. You are already familiar with the development of Spring Boot applications. If this is not the case, a good place to start is Spring.io.
  2. You have already an AWS account, otherwise it is possible to register for the free tier which includes 5 GB S3 storage and 750 hours of EC2 usage.
  3. You have an installed version of the AWS cli on your local machine, otherwise this might help you.
  4. You configured the AWS cli on your local machine with your AWS account details, otherwise checkout the documentation here.

So, before we start and get our hands dirty, a little background information about the things we like to achieve.

First of all, a Spring Boot service is deployed to AWS Elastic Beanstalk using the AWS cli to make the service accessible in the cloud using http. Afterwards, a new domain name is made available through Amazon Route 53 and the load balancer of the AWS Elastic Beanstalk environment is configured to accept only https traffic to be able to call the service using a user-friendly url using https.

As an example service, I use a simple service that retrieves a list of persons using the endpoint /person/get. Regarding the development of the Spring Boot application, only one aspect is specific to AWS Elastic Beanstalk, namely the usage of port 5000 for the server.port property. This port is the standard port that is assigned for web applications in AWS Elastic Beanstalk.

But what exactly is AWS Elastic Beanstalk? Amazon describes the service in the following way: “Elastic Beanstalk is the fastest and simplest way to deploy your application on AWS. Elastic Beanstalk provisions and operates the infrastructure and manages the application stack (platform) for you, so you don’t have to spend the time or develop the expertise.” This means that AWS Elastic Beanstalk is one of the easiest ways to set up a cloud environment for web applications consisting of load balancers, security groups, EC2 instances and many more components that otherwise would have to be set up separately.

Overview

The figure shows the components that will be used in the following sections:

  • AWS Elastic Beanstalk is hosted in the eu-west-1 availability zone and consits of an AWS Classic Load Balancer which is Internet facing with a public IP address. In addition to the load balancer, it consists of several components like a VPC where all of the other AWS resources are hosted, a network access control list and a security group to restrict access (not shown here for the sake of simplicity), an auto scaling group which is able to scale the Amazon EC2 virtual machines based on metrics like cpu utilization. The Amazon EC2 instance is the virtual machine where the Spring Boot service is hosted.
  • Amazon Route 53 is the DNS server which will host a user-frindly DNS name for our service.
  • AWS Certificate Manager managed the certificate which is used to access our service through https.
  • Amazon S3 is used to manage the code of our Spring Boot service.
  • Amazon Cloud Watch provides log functionality and monitoring capabilities for our Amazon EC2 instance.

Please note that using Amazon Route 53 is outside of the AWS free tier (see prizes).

Deployment to AWS Elastic Beanstalk

So, let’s start by creating an application that can be hosted on AWS Elastic Beanstalk later on:

As we can see, our application has been created in the eu-west-1 region (our default region which has been specified during the set-up of the AWS cli on the local machine). For simplicity, we did not used any configuration templates to customize the environment and did not activate any lifecycle configuration.

Now, we have to create an environment for our application. Every environment in AWS Elastic Beanstalk is created using a specific solution stack (Java, node.js, Go, etc.). So, so we now need to find out the name of the solution stack for our Java based Spring Boot service using the AWS cli:

As a result, the available list of solution stacks (omitted here) is returned and the solution stack with the name “64bit Amazon Linux 2018.03 v2.8.2 running Java 8” will be used for creating our runtime environment later on. An AWS Elastic Beanstalk environment can be compared to a stage in the software development lifecycle, so typically a development -, integration – and production environment will be created for any application.

Let’s create a development environment called PersonService-dev for our PersonService application:

As you can see, our newly created environment has the unique id e-8enmyw47g2 and is created in the background (status “Launching”). As soon it is available its health will become “Green”.

Before we can actually deploy our Spring Boot service to AWS Elastic Beanstalk, we have to create an S3 bucket where your application code can be uploaded:

As a result, the name of the newly created S3 bucket is returned. After running a local maven build, we can now upload the created jar using the given bucket location:

After the upload is complete, the code is ready to be deployed. So, in the first step we first create a new application version that will be activated in the second step.

Before our deployed Spring Boot service can be accessed, we need to find out the hosts name where the service is located:

Now we are able to call our Spring Boot microservice using HTTP and the endpoint URL that has been returned namely http://awseb-e-8-awsebloa-1edi9feaj6flr-181762183.eu-west-1.elb.amazonaws.com/person/get

Using Amazon Route 53

Though, our service is now available to the public, the URL is not very user-friendly and the usage of https for accessing the service would be preferable.

Due to the fact, that my company Novatec Consulting GmbH already had a registered top-level domain called novatec-playground53.de. If you do not have any top-level domains, you can buy or transfer them via the AWS console using Amazon Route 53.

For mapping any sub-domain to our AWS Elastic Beanstalk environment, you have to find out the id of the hosted zone (“A hosted zone is a container for records, and records contain information about how you want to route traffic for a specific domain, such as example.com, and its subdomains like acme.example.com or zenith.example.com“) of your top-level domain:

Then we have to find out the current CNAME of our environment using the command line:

Now a new subdomain, e.g. pkt-dev.novatec-playground53.de, can be mapped to the CNAME of our PersonService-dev environment using the following command:

Content of the create_route53_cname.json file:

Basically, the content of the file means that the CNAME pkt-dev.novatec-playground53.de is mapped to the CNAME PersonService-dev.tvumy5sv4s.eu-west-1.elasticbeanstalk.com and made available in the hosted zone with the given id.

As soon as the change has been processed, we are able to call our Spring Boot service using HTTP and the endpoint URL  http://pkt-dev.novatec-playground53.de/person/get

Using AWS Certificate Manager

So far, so good. In the last part, we like to allow only https calls to access our service. This is where AWS Certificate Manager is used. So, we have to request a certificate for our pkt-dev.novatec-playground53.de subdomain:

Now, we finally like to assign the requested certificate to port 443 and disable port 80, so only https traffic is able to access our service.

The most easiest way to achieve this, is not to use the AWS command line, but to use a config file namely listeners.config (YAML format) in a directory named .ebextensions as part of our source code with the following content:

The config file has the effect that a https listener for the load balancer in the AWS Elastic Beanstalk environment is enabled and associated with the given certificate and the http listener is disabled. So http traffic is no longer allowed and our service can only accessed using the url https://pkt-dev.novatec-playground53.de/person/get. Note, the same functionality can be achieved using the AWS cli, but you need to modify the load balancer as well as the associated security group accordingly which is a little more complicated. By the way, AWS Elastic Beanstalk uses a classic load balancer – the old way of balancing load on application level (OSI level 7) and on network level (OSI level 4).

Conclusion

As you could see, it is not that complicated to deploy a simple Spring Boot service and make it available in AWS in a secure fashion. AWS Elastic Beanstalk, Amazon Route 53 and AWS Certificate Manager are the services to get this job done. Using the AWS cli you are able to repeat the set-up for different environments and settings in an easy way.

It has to be noted that the deployment process is only feasible for service which are not changed very often. In a typical development project another setup with an automatic build would be used, but this is a topic for another blog post.