Deploy a Web App on AWS Elastic Beanstalk

TUTORIAL

Module 2: Create Infrastructure Using AWS CDK

In this module, you will create a CDK application that will create all the necessary infrastructure to deploy the Node.js web app using Elastic Beanstalk

Overview

In this module, you will create a CDK application that will create all the necessary infrastructure to deploy the Node.js web app using AWS Elastic Beanstalk.

What you will accomplish

In this module, you will:
  • Create a simple CDK application
  • Upload a package to S3 using S3 Assets
  • Create an Elastic Beanstalk CDK app, app version, and environment

 Time to complete

15 minutes

 Module prerequisites

  • AWS account with administrator-level access*
  • Recommended browser: The latest version of Chrome or Firefox

[*]Accounts created within the past 24 hours might not yet have access to the services required for this tutorial.

Implementation

Create the CDK app

Please install the specific version of the CDK to match the dependencies that are installed later on.
Example : 

npm install -g cdk@1.180.0
npm i —save-exact @aws-cdk/aws-s3-assets@1.180.0
npm i —save-exact @aws-cdk/aws-elasticbeanstalk@1.180.0
npm i —save-exact @aws-cdk/aws-iam@1.180.0

Create a new directory and move to that directory.

mkdir cdk-eb-infra
cd cdk-eb-infra

Initialize the CDK application that you will use to create the infrastructure.

cdk init app --language typescript

Create the code for the resource stack

Go to the file /lib/cdk-eb-infra-stack.ts, where you will write the code for the resource stack you are going to create. 

A resource stack is a set of cloud infrastructure resources—all AWS resources in this case—that will be provisioned into a specific account. The account where these resources will be provisioned is the stack that you configured in the prerequisite steps. In this resource stack, you are going to create these resources:

  • S3 Assets: This helps you to upload your zipped application into S3 and will provide the CDK application a way to get the object location.
  • Elastic Beanstalk App: A logical collection of Elastic Beanstalk components, including environments, versions, and environment configurations.
  • Elastic Beanstalk App Version: A specific, labeled iteration of deployable code for a web application. An application version points to an Amazon S3 object that contains the deployable code, in this case, the zip file that you will be uploading to S3 using S3 Assets. Applications can have many versions and each application version is unique.
  • Instance profile and role: A container for an AWS Identity and Access Management (IAM) role that you can use to pass role information to an Amazon EC2 instance when the instance starts.
  • Elastic Beanstalk Environment: A collection of AWS resources running an application version. Each environment runs only one application version at a time.

Upload the app to S3 automatically

For deploying your web app, you need to package it and upload it to Amazon S3 so that Elastic Beanstalk can deploy the application in the environment.

We will do the packaging of the application in the third module of this tutorial, but for now we will focus on uploading it to S3. To do that, you will be using a CDK constructor called S3 Assets. The S3 Assets module will upload local files and the directory to S3.

In our CDK application, we first need to install the aws-s3-assets module.

npm i @aws-cdk/aws-s3-assets

Then, in the lib/cdk-eb-infra-stack.ts file, add the dependency to the top of the file.

import s3assets = require('@aws-cdk/aws-s3-assets');

Inside the stack, under the commented line that says The code that defines your stack goes here add the following code.

 // Construct an S3 asset from the ZIP located from directory up.
const webAppZipArchive = new s3assets.Asset(this, 'WebAppZip', {
      path: `${__dirname}/../app.zip`,
});

This code uses the S3 Assets module and takes the zip file of the web app located in the root of the CDK app, and uploads it to S3. Whenever you update the zip file and you deploy this stack, the file will get updated in S3.

Add the Elastic Beanstalk CDK dependencies

Next, we will create the Elastic Beanstalk application, application version, and environment so that you can deploy the web app that you just uploaded to S3 using S3 Assets.

First, you need to install the Elastic Beanstalk module for CDK.

npm i @aws-cdk/aws-elasticbeanstalk

Then, add the dependency to the top of the /lib/cdk-eb-infra-stack.ts file.

import elasticbeanstalk = require('@aws-cdk/aws-elasticbeanstalk');

Create the Elastic Beanstalk application

Now you can create the Elastic Beanstalk app. As mentioned before, an Elastic Beanstalk application is a logical collection of Elastic Beanstalk components, like a folder.

Put this code under the code of the S3 Assets in the /lib/cdk-eb-infra-stack.ts file. This code will create the application with the name MyWebApp in Elastic Beanstalk.

// Create a ElasticBeanStalk app.
const appName = 'MyWebApp';
const app = new elasticbeanstalk.CfnApplication(this, 'Application', {
    applicationName: appName,
});

Create Elastic Beanstalk application version

Now you need to create an application version from the S3 asset that you created earlier. This piece of code will create the app version using the S3 bucket name and S3 object key that S3 Assets and CDK will provide to this method.

// Create an app version from the S3 asset defined earlier
const appVersionProps = new elasticbeanstalk.CfnApplicationVersion(this, 'AppVersion', {
    applicationName: appName,
    sourceBundle: {
        s3Bucket: webAppZipArchive.s3BucketName,
        s3Key: webAppZipArchive.s3ObjectKey,
    },
});

Before moving on, you want to make sure that the Elastic Beanstalk application exists before creating the app version. You can do this with CDK, as shown in the following code snippet.

// Make sure that Elastic Beanstalk app exists before creating an app version
appVersionProps.addDependsOn(app);

Create the instance profile

To create your Elastic Beanstalk environment, you will need to provide an existing instance profile name.

An instance profile is a container for an AWS Identity and Access Management (IAM) role that you can use to pass role information to an Amazon EC2 instance when the instance starts.

In this case, the role will have attached the managed policy AWSElasticBeanstalkWebTier, which grants permissions to the app to upload logs to Amazon S3 and debugging information to AWS X-Ray.

The first thing you need to do is install the IAM module in your CDK app.

npm i @aws-cdk/aws-iam

Then import the dependency in the CDK stack we have been working on:

import iam = require('@aws-cdk/aws-iam');

After the code that creates the application version, add this code:

// Create role and instance profile
const myRole = new iam.Role(this, `${appName}-aws-elasticbeanstalk-ec2-role`, {
    assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
});

const managedPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName('AWSElasticBeanstalkWebTier')
myRole.addManagedPolicy(managedPolicy);

const myProfileName = `${appName}-InstanceProfile`

const instanceProfile = new iam.CfnInstanceProfile(this, myProfileName, {
    instanceProfileName: myProfileName,
    roles: [
        myRole.roleName
    ]
});

The first thing the code does is to create a new IAM role (myRole).

To allow the EC2 instances in your environment to assume the role, the instance profile specifies Amazon EC2 as a trusted entity in the trust relationship policy.

To that role we then add the managed policy AWSElasticBeanstalkWebTier. We then create the instance profile with that role and the profile name.

Create Elastic Beanstalk environment

The last part you need to create is the Elastic Beanstalk environment. The environment is a collection of AWS resources running an application version. For the environment, we will need to give some information about the infrastructure.

Let's start by creating the environment. When creating the environment you need to give it a name that will appear in the Elastic Beanstalk console—in this case, we are naming the environment MyWebAppEnvironment.

Then you need to give the application name, which you will get from the Elastic Beanstalk application definition earlier.

The solution stack name is the name of the managed platform that Elastic Beanstalk provides for running web applications. Using the right solution name, Elastic Beanstalk will provision the right resources for your application, for example, the Amazon EC2 instances. You should choose the right software stack depending on the framework and platform you chose to develop your web app. For this particular case, you are going to put this string '64bit Amazon Linux 2 v5.6.1 running Node.js 14'. At the end of this module, there is more information about solution stack names if you are interested where this string came from.

The option settings attribute allows you to configure the Elastic Beanstalk environment to your needs:

  • IamInstanceProfile: Here you will reference the instance profile created in the previous steps.
  • MinSize, MaxSize, and InstanceTypes: These are configurations for your instances and the autoscaling group that Elastic Beanstalk generates for you. These are optional parameters. If you don't set them up, Elastic Beanstalk will pick the instance type and the minimum and maximum sizes of the autoscaling group according to the platform definition. You are defining them so you can stay within the AWS Free Tier.

For more information about these settings, see Configuration options for Elastic Beanstalk.

To define these configuration options, add the following lines of code:

// Example of some options which can be configured
const optionSettingProperties: elasticbeanstalk.CfnEnvironment.OptionSettingProperty[] = [
    {
        namespace: 'aws:autoscaling:launchconfiguration',
        optionName: 'IamInstanceProfile',
        value: myProfileName,
    },
    {
        namespace: 'aws:autoscaling:asg',
        optionName: 'MinSize',
        value: '1',
    },
    {
        namespace: 'aws:autoscaling:asg',
        optionName: 'MaxSize',
        value: '1',
    },
    {
        namespace: 'aws:ec2:instances',
        optionName: 'InstanceTypes',
        value: 't2.micro',
    },
];

Finally we have the version label. This is an important attribute as it needs to be a reference to the application version that we just created.

With this information, you can now create your Elastic Beanstalk environment.

Paste this code in your stack definition file.

// Create an Elastic Beanstalk environment to run the application
const elbEnv = new elasticbeanstalk.CfnEnvironment(this, 'Environment', {
    environmentName: 'MyWebAppEnvironment',
    applicationName: app.applicationName || appName,
    solutionStackName: '64bit Amazon Linux 2 v5.6.1 running Node.js 14',
    optionSettings: optionSettingProperties,
    versionLabel: appVersionProps.ref,
});

Common mistakes

Using multiple versions of the CDK libraries

One common error you might get when using CDK is that when you import a library and start using it in your application, the word "this" gets highlighted and you receive a compilation error.

This might happen because you are using CDK module with a different version than the CDK core library. CDK updates happen often, so it's a common error.

To fix this, you need to update all the CDK packages to the same version. You can see the version of your CDK packages in the package.json file in your CDK application.

More information

Elastic Beanstalk solution stack name

In the documentation, you can read about all the supported platforms for Elastic Beanstalk. We update this page as newer platforms are added and older platforms get retired.

If you are curious about how to get the right platform name, such as 64bit Amazon Linux 2 v5.6.1 running Node.js 14, you can use the AWS CLI to get a list of all the supported platforms.

aws elasticbeanstalk list-available-solution-stacks

This returns a long list of supported platforms strings that you can use in your CDK application.

Conclusion

In this module, you learned how to create all the necessary resources of Elastic Beanstalk to deploy your application automatically. In the next module, you are going to learn how to deploy this to the cloud and how you can update your app when there are changes.

Up Next: Deploy Application

Was this page helpful?