AWS Elastic Beanstalk
Developer Guide (last updated: 12 December, 2014) (API Version 2010-12-01)
Did this page help you?  Yes | No |  Tell us about it...
« PreviousNext »
View the PDF for this guide.Go to the AWS Discussion Forum for this product.Go to the Kindle Store to download this guide in Kindle format.

Deploying an Express Application with Clustering to AWS Elastic Beanstalk

This section walks you through deploying a sample application to AWS Elastic Beanstalk using eb (an updated command line interface) and Git, and then updating the application to use the Express framework and Amazon ElastiCache for clustering. Clustering enhances your web application's high availability, performance, and security. To learn more about Amazon ElastiCache, go to Introduction to ElastiCache in the Amazon ElastiCache User Guide.

Note

This example creates AWS resources, which you may be charged for. For more information about AWS pricing, go to http://aws.amazon.com/pricing/. Some services are part of the AWS Free Usage Tier. If you are a new customer, you may test drive these services for free. Go to http://aws.amazon.com/free/ for more information.

Step 1: Set Up Your Git Repository

Eb is a command line interface that enables you to deploy applications quickly and more easily using Git. Eb is available as part of the Elastic Beanstalk command line tools package. Follow the steps below to install eb and initialize your Git repository.

To install eb, its prerequisite software, and initialize your Git repository

Step 2: Set Up Your Express Development Environment

Set up Express and create the project structure. The following walks you through setting up Express on a Linux operating system.

To set up your Express development environment on your local computer

  1. Install node.js. For instructions, go to http://nodejs.org/. Verify you have a successful installation before proceeding to the next step.

    $ node -v

    Note

    For information about what Node.js versions are supported, see Supported Platforms.

  2. Create a directory for your Express application.

    $ mkdir express-cluster
    $ cd express-cluster
  3. Install npm.

    express-cluster# cd . && yum install npm
  4. Install Express globally so that you have access to the express command.

    express-cluster# npm install -g express-generator
  5. Depending on your operating system, you may need to set your path to run the express command. If you need to set your path, use the output from the previous step when you installed Express. The following is an example.

    express-cluster# export:PATH=$PATH:/usr/local/share/npm/bin/express
  6. Run the express command. This generates package.json.

    express-cluster# express

    When prompted if you want to continue, type y.

  7. Set up local dependencies

    express-cluster# cd . && npm install
  8. Verify it works.

    express-cluster# node app

    You should see output similar to the following:

    Express server listening on port 3000

    Press Ctrl+C to stop the server.

  9. Initialize the Git repository.

    express-cluster# git init 
  10. Exclude the following files from being added to the repository. This step is not required, but it is recommended.

    express-cluster# cat > .gitignore <<EOT 
    node_modules/
    .gitignore
    .elasticbeanstalk/
    EOT				

Step 3: Configure AWS Elastic Beanstalk

You use eb, a command line tool, to configure AWS Elastic Beanstalk. If you haven't already installed eb on your local computer, do that now at the AWS Sample Code & Libraries website. If you are running eb on a Linux operating system, you will need to install Python 2.7 or 3.0.

Before you use eb, set your PATH to the location of eb. The following table shows an example for Linux/UNIX and Windows.

In Linux and UNIXIn Windows
$ export PATH=$PATH:<path to unzipped eb CLI package>/eb/linux/python2.7/

If you are using Python 3.0, the path will include python3 rather than python2.7.

C:\> set PATH=%PATH%;<path to unzipped eb CLI package>\eb\windows\

Use the init command, and AWS Elastic Beanstalk will prompt you to enter this information. If a default value is available, and you want to use it, press Enter.

To configure AWS Elastic Beanstalk

  1. From the directory where you created your local repository, type the following command:

    eb init
  2. When you are prompted for the access key ID, type your access key ID. To get your access key ID, see How Do I Get Security Credentials? in the AWS General Reference.

    Enter your AWS Access Key ID (current value is "AKIAIOSFODNN7EXAMPLE"): 
  3. When you are prompted for the secret access key, type your secret access key. To get your secret access key, see How Do I Get Security Credentials? in the AWS General Reference.

    Enter your AWS Secret Access Key (current value is "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"): 
  4. When you are prompted for the AWS Elastic Beanstalk region, type the number of the region. For information about this product's regions, go to Regions and Endpoints in the Amazon Web Services General Reference. For this example, we'll use US East (Virginia).

  5. When you are prompted for the AWS Elastic Beanstalk application name, type the name of the application. AWS Elastic Beanstalk generates an application name based on the current directory name if an application name has not been previously configured. In this example, we use expressapp.

    Enter an AWS Elastic Beanstalk application name (auto-generated value is "express-cluster"): expressclusterapp

    Note

    If you have a space in your application name, make sure you do not use quotation marks.

  6. When you are prompted for the AWS Elastic Beanstalk environment name, type the name of the environment. AWS Elastic Beanstalk automatically creates an environment name based on your application name. If you want to accept the default, press Enter.

    Enter an AWS Elastic Beanstalk environment name (current value is "express-cluster-env"): expressclusterapp-env

    Note

    If you have a space in your application name, make sure you do not have a space in your environment name.

  7. When you are prompted, choose an environment tier. For more information about environment tiers, see Architectural Overview. For this example, we'll use 1.

    Available environment tiers are:
    1) WebServer::Standard::1.0
    2) Worker::SQS/HTTP::1.0
    
  8. When you are prompted for the solution stack, type the number of the solution stack you want. For more information about solution stacks, see Supported Platforms. For this example, we'll use 32bit Amazon Linux running Node.js.

  9. When you are prompted, choose an environment type. For this example, we'll use 2.

    Available environment types are: 
    1) LoadBalanced
    2) SingleInstance
    
  10. When you are prompted to create an Amazon RDS database, type y or n. For more information about using Amazon RDS, see Using AWS Elastic Beanstalk with Amazon RDS. For this example, we'll type n.

    Create RDS instance? [y/n]: n
  11. When you are prompted to enter your instance profile name, you can choose to create a default instance profile or use an existing instance profile. Using an instance profile enables IAM users and AWS services to gain access to temporary security credentials to make AWS API calls. Using instance profiles prevents you from having to store long-term security credentials on the EC2 instance. For more information about instance profiles, see Granting Permissions to Users and Services Using IAM Roles. For this example, we'll use Create a default instance profile.

    You should see a confirmation that your AWS Credential file was successfully updated.

After configuring AWS Elastic Beanstalk, you are ready to deploy a sample application.

If you want to update your AWS Elastic Beanstalk configuration, you can use the init command again. When prompted, you can update your configuration options. If you want to keep any previous settings, press the Enter key.

Step 4: Create an Application

Next, you need to create and deploy a sample application. For this step, you use a sample application that is already prepared. AWS Elastic Beanstalk uses the configuration information you specified in the previous step to do the following:

  • Create an application using the application name you specified.

  • Launch an environment using the environment name you specified that provisions the AWS resources to host the application.

  • Deploy the application into the newly created environment.

Use the start command to create and deploy a sample application.

To create the application

  • From the directory where you created your local repository, type the following command:

    eb start

It may take several minutes to complete this process. AWS Elastic Beanstalk provides status updates during the process. If at any time you want to stop polling for status updates, press Ctrl+C. When the environment status is Green, AWS Elastic Beanstalk outputs a URL for the application.

Step 5: View the Application

In the previous step, you created an application and deployed it to AWS Elastic Beanstalk. After the environment is ready and its status is Green, AWS Elastic Beanstalk provides a URL to view the application. In this step, you can check the status of the environment to make sure it is set to Green and then copy and paste the URL to view the application.

Use the status command to check the environment status, and then use the URL to view the application.

To view the application

  1. From the directory where you created your local repository, type the following command:

    eb status --verbose

    AWS Elastic Beanstalk displays the environment status. If the environment is set to Green, AWS Elastic Beanstalk displays the URL for the application. If you attached an RDS DB instance to your environment, your RDS DB information is displayed.

  2. Copy and paste the URL into your web browser to view your application.

Step 6: Update the Application

After you have deployed a sample application, you can update it with your own application. In this step, we update the sample application to use the Express framework. You can download the final source code from http://elasticbeanstalk-samples-us-east-1.s3.amazonaws.com/nodejs-example-express-elasticache.zip.

To update your application to use Express

  1. On your local computer, rename express-cluster/app.js to express-cluster/express-app.js.

    express-cluster# mv app.js express-app.js
  2. Update the line var app = express(); in express-cluster/express-app.js to the following:

    var app = module.exports = express();
  3. On your local computer, create a file named express-cluster/app.js with the following code.

    var cluster = require('cluster'),
        app = require('./express-app');
    
    var workers = {},
        count = require('os').cpus().length;
    
    function spawn(){
      var worker = cluster.fork();
      workers[worker.pid] = worker;
      return worker;
    }
    
    if (cluster.isMaster) {
      for (var i = 0; i < count; i++) {
        spawn();
      }
      cluster.on('death', function(worker) {
        console.log('worker ' + worker.pid + ' died. spawning a new process...');
        delete workers[worker.pid];
        spawn();
      });
    } else {
      app.listen(process.env.PORT || 5000);
    }
  4. Stage the files.

    express-cluster# git add .
    express-cluster# git commit -m "First express app"
    express-cluster# git aws.push
  5. Your environment will be updated after a few minutes. Once the environment is green and ready, refresh the URL to verify it worked. You should see a web page that says "Welcome to Express".

You can access the logs for your EC2 instances running your application. For instructions on accessing your logs, see Working with Logs.

Next, let's update the Express application to use Amazon ElastiCache.

To update your Express application to use Amazon ElastiCache

  1. On your local computer, create an .ebextensions directory in the top-level directory of your source bundle. In this example, we use express-cluster/.ebextensions.

  2. Create a configuration file express-cluster/.ebextensions/elasticache-iam-with-script.config with the following snippet. For more information about the configuration file, see Customizing and Configuring a Node.js Environment. This creates an IAM user with the permissions required to discover the elasticache nodes and writes to a file anytime the cache changes. You can also copy the file from http://elasticbeanstalk-samples-us-east-1.s3.amazonaws.com/nodejs-example-express-elasticache.zip. For more information on the ElastiCache properties, see Example Snippets: ElastiCache. For a more complete reference, see AWS Resource Types Reference.

    Resources:
      MyElastiCache:
        Type: AWS::ElastiCache::CacheCluster
        Properties:
          CacheNodeType: 
             Fn::GetOptionSetting:
                 OptionName : CacheNodeType
                 DefaultValue: cache.m1.small
          NumCacheNodes: 
               Fn::GetOptionSetting:
                 OptionName : NumCacheNodes
                 DefaultValue: 1
          Engine: 
               Fn::GetOptionSetting:
                 OptionName : Engine
                 DefaultValue: memcached
          CacheSecurityGroupNames:
            - Ref: MyCacheSecurityGroup
      MyCacheSecurityGroup:
        Type: AWS::ElastiCache::SecurityGroup
        Properties:
          Description: "Lock cache down to webserver access only"
      MyCacheSecurityGroupIngress:
        Type: AWS::ElastiCache::SecurityGroupIngress
        Properties:
          CacheSecurityGroupName: 
            Ref: MyCacheSecurityGroup
          EC2SecurityGroupName:
            Ref: AWSEBSecurityGroup
      AWSEBAutoScalingGroup :
        Metadata :
          ElastiCacheConfig :
            CacheName :
              Ref : MyElastiCache
            CacheSize :
               Fn::GetOptionSetting:
                 OptionName : NumCacheNodes
                 DefaultValue: 1
      WebServerUser : 
        Type : AWS::IAM::User
        Properties :
          Path : "/"
          Policies:
            -
              PolicyName: root
              PolicyDocument :
                Statement :
                  -
                    Effect : Allow
                    Action : 
                      - cloudformation:DescribeStackResource
                      - cloudformation:ListStackResources
                      - elasticache:DescribeCacheClusters
                    Resource : "*"
      WebServerKeys :
        Type : AWS::IAM::AccessKey
        Properties :
          UserName :
            Ref: WebServerUser
    
    Outputs:
      WebsiteURL:
        Description: sample output only here to show inline string function parsing
        Value: |
          http://`{ "Fn::GetAtt" : [ "AWSEBLoadBalancer", "DNSName" ] }`
      MyElastiCacheName:
        Description: Name of the elasticache
        Value:
          Ref : MyElastiCache
      NumCacheNodes:
        Description: Number of cache nodes in MyElastiCache
        Value:
          Fn::GetOptionSetting:
            OptionName : NumCacheNodes
            DefaultValue: 1
    
    files:
      "/etc/cfn/cfn-credentials" :
        content : |
          AWSAccessKeyId=`{ "Ref" : "WebServerKeys" }`
          AWSSecretKey=`{ "Fn::GetAtt" : ["WebServerKeys", "SecretAccessKey"] }`
        mode : "000400"
        owner : root
        group : root
    
      "/etc/cfn/get-cache-nodes" :
        content : |
          # Define environment variables for command line tools
          export AWS_ELASTICACHE_HOME="/home/ec2-user/elasticache/$(ls /home/ec2-user/elasticache/)"
          export AWS_CLOUDFORMATION_HOME=/opt/aws/apitools/cfn
          export PATH=$AWS_CLOUDFORMATION_HOME/bin:$AWS_ELASTICACHE_HOME/bin:$PATH
          export AWS_CREDENTIAL_FILE=/etc/cfn/cfn-credentials
          export JAVA_HOME=/usr/lib/jvm/jre
    
          # Grab the Cache node names and configure the PHP page
          cfn-list-stack-resources `{ "Ref" : "AWS::StackName" }` --region `{ "Ref" : "AWS::Region" }` | grep MyElastiCache | awk '{print $3}' | xargs -I {} elasticache-describe-cache-clusters {} --region `{ "Ref" : "AWS::Region" }` --show-cache-node-info | grep CACHENODE | awk '{print $4 ":" $5}' > `{ "Fn::GetOptionSetting" : { "OptionName" : "NodeListPath", "DefaultValue" : "/var/www/html/nodelist" } }`
        mode : "000500"
        owner : root
        group : root
    
      "/etc/cfn/hooks.d/cfn-cache-change.conf" :
        "content": |
          [cfn-cache-size-change]
          triggers=post.update
          path=Resources.AWSEBAutoScalingGroup.Metadata.ElastiCacheConfig
          action=/etc/cfn/get-cache-nodes
          runas=root
    
    sources :
      "/home/ec2-user/elasticache" : "https://s3.amazonaws.com/elasticache-downloads/AmazonElastiCacheCli-latest.zip"
    
    commands: 
      make-elasticache-executable:
        command: chmod -R ugo+x /home/ec2-user/elasticache/*/bin/*
    
    packages : 
      "yum" :
        "aws-apitools-cfn"  : []
    
    container_commands:
      initial_cache_nodes:
        command: /etc/cfn/get-cache-nodes
  3. On your local computer, create a configuration file express-cluster/.ebextensions/elasticache_settings.config with the following snippet to configure ElastiCache.

    option_settings:
      "aws:elasticbeanstalk:customoption" :
         CacheNodeType : cache.m1.small
         NumCacheNodes : 1
         Engine : memcached
         NodeListPath : /var/nodelist 
  4. On your local computer, replace express-cluster/express-app.js with the following snippet. This file reads the nodes list from disk (/var/nodelist) and configures express to use memcached as a session store if nodes are present. Your file should look like the following.

    /**
     * Module dependencies.
     */
    
    var express = require('express'),
        fs = require('fs'),
        filename = '/var/nodelist',
        app = module.exports = express();
    
    var MemcachedStore = require('connect-memcached')(express);
    
    function setup(cacheNodes) {
      app.configure(function(){
          app.use(express.bodyParser());
          app.use(express.methodOverride());
          if (cacheNodes) {
              app.use(express.cookieParser());
    
              console.log('Using memcached store nodes:');
              console.log(cacheNodes);
    
              app.use(express.session({
                  secret: 'your secret here',
                  store: new MemcachedStore({'hosts':cacheNodes})
              }));
          } else {
            console.log('Not using memcached store.');
            app.use(express.cookieParser('your secret here'));
            app.use(express.session());
          }
          app.use(app.router);
      });
    
      app.get('/', function(req, resp){
          resp.writeHead(200, "Content-type: text/html");
          resp.write("You are session: " + req.session.id);
          resp.end();
      });
    
      if (!module.parent) {
          console.log('Running express without cluster.');
          app.listen(process.env.PORT || 5000);
      }
    }
    
    // Load elasticache configuration.
    fs.readFile(filename, 'UTF8', function(err, data) {
        if (err) throw err;
        var cacheNodes = [];
        if (data) {
            var lines = data.split('\n');
            for (var i = 0 ; i < lines.length ; i++) {
                if (lines[i].length > 0) {
                    cacheNodes.push(lines[i]);
                }
            }
        }
        setup(cacheNodes);
    });
  5. On your local computer, update express-cluster/package.json to add connect-memcached to the dependencies.

    {
      "name": "application-name",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "node app"
      },
      "dependencies": {
        "express": "3.1.0",
        "jade": "*",
        "connect-memcached": "*"
      }
    }
  6. Add your updated files to your local repository and commit your changes.

    express-cluster# git add .
    express-cluster# git commit -m "Adding ElastiCache"
    express-cluster# git aws.push
  7. Your environment will be updated after a few minutes. After your environment is green and ready, verify everything worked.

    1. Check the Amazon CloudWatch console to view your ElastiCache metrics. To view your ElastiCache metrics, click ElastiCache in the left pane, and then select ElastiCache: Cache Node Metrics from the Viewing list.

      Note

      Make sure you are looking at the same region that you deployed your application to.

      If you copy and paste your application URL into another web browser, you should see your CurrItem count go up to 2 after 5 minutes.

    2. Take a snapshot of your logs, and check /var/log/nodejs/nodejs.log. For more information about logs, see Working with Logs. You should see something similar to the following:

      MemcachedStore initialized for servers: aws-my-1oys9co8zt1uo.1iwtrn.0001.use1.cache.amazonaws.com:11211

Step 7: Clean Up

If you no longer want to run your application, you can clean up by terminating your environment and deleting your application.

Use the stop command to terminate your environment and the delete command to delete your application.

To terminate your environment and delete the application

  1. From the directory where you created your local repository, type the following command:

    eb stop

    This process may take a few minutes. AWS Elastic Beanstalk displays a message once the environment has been successfully terminated.

    Note

    If you attached an RDS DB instance to your environment, your RDS DB will be deleted, and you will lose your data. To save your data, create a snapshot before you delete the application. For instructions on how to create a snapshot, go to Creating a DB Snapshot in the Amazon Relational Database Service User Guide.

  2. From the directory where you installed the command line interface, type the following command:

    eb delete

    AWS Elastic Beanstalk displays a message once it has successfully deleted the application.