How to install Couchbase for Node.js on Amazon Elastic Beanstalk

Hello and welcome to this week’s episode of “How to install Couchbase” ;-)
(I could have called it “How to debug AWS Elastic Beanstalk” but I wanted to keep the tradition)

Since more and more people stumble across my blog in search for Couchbase installation tips, I wrote this guide in the same style.

This time I tried to deploy my HelloWorld app to an AWS Elastic Beanstalk instance.
Unfortunately, the only solution that worked for me was a little bit hacky and is not scalable(!).
I would be very happy about suggestions!

Intro

There are some good beginner tutorials on how to deploy your Node.js app to Amazon Elastic Beanstalk on
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs.html.

The procedure is always the same:

  1. Create a local Git Repo for your project
  2. Define a package.json where all dependencies are specified
  3. Upload your app with EB tools

That’s it!

In theory, Elastic Beanstalk will do the rest for you!! (set up a new instance with Node.js, fetch all the dependencies, start and monitor your app, auto-scale it(!), loadbalance it, …)
So you don’t have to worry about how this stuff works and can concentrate on your app/code. Compared to EC2 this is pure PAAS.
However, with this large number of benefits comes a big disadvantage:
Elastic Beanstalk is a BlackBox – you should not worry about how internal stuff works.

So the concept is nice but has its limitations. There are situations in which you want to customize your envorinment. Maybe your project depends on additional libraries, you want to tweak performance or you want to use Couchbase.

The naive package.json method

One thing in advance: the described deployment procedure will not work for Couchbase.
You can’t define a package.json with

upload it and have fun. The reason is simple: The Node.js Couchbase drivers depend on libcouchbase.
If you try anyway you will see something like this:
beanstalk error

At this point you can start to figure out what went wrong. The best place to do this are the log files.
AWS EB comes with a huge log file with different sections. Nearly all the events of the day are noted in that file which is helpful and confusing at the same time.
You will find something like this:

This info is part of the /var/log/eb-tools.log
“Result message exceeds max result size” is really nice because it says that the logs will not show you why npm crashed but only that it failed. “Snapshot logs for more details.” is also “really helpful” since it is displayed in the log snapshot. Did I miss any other log snapshots?!

The next info I found was from /var/log/cfn-init.log

Unfortunately I could not find more helpful hints. At this moment the only thing I wanted was to get rid of the “cage” and take a look at the internals.

SSH to Elastic Beanstalk

Searching for a way to access my Elastic Beanstalk Instance I found this post on Stackoverflow:
http://stackoverflow.com/questions/4742478/ssh-to-elastic-beanstalk-instance

I followed the two steps:

  1. Configure Security Group
  2. Configure the environment of your Elastic Beanstalk Application

and the tip from “Pete”:

There is a handy ‘Connect’ option in the ‘Instance Actions’ menu for the EC2 instance. It will give you the exact SSH command to execute with the correct url for the instance.

to gain access to the machine.

Debugging AWS Elastic Beanstalk

Next, I used the knowledge gained from the logs to search for the crashing Python script:
One can see from the logs that the path is /opt/elasticbeanstalk/hooks/appdeploy/pre/
AWS Elastic Beanstalk uses a hook mechanism to deploy the app and hook user configurations into this process.
The pre directory contains the following scripts each representing a different pre-deployment step:

The 50npm.sh script is just a starter for a Python script:

Since the wrapping script mechanism consumed all my error messages I executed the relevant part directly from my console.
WARNING the following action is not intended and can mess up your whole environment. Do it at your own risk.

Running the npm installer this way one can see what ist going wrong. This time it is a missing libcouchbase:
fatal error: libcouchbase/couchbase.h: No such file or directory
See my last post for more information on different kinds of errors.

Update 1
Q: Why did I choose to run this command instead of just run npm install?
A: As far as I can tell, you are facing two problems when trying to execute npm install directly.
The first is that the path variable is neither set for node nor npm. This seems to be a minor problem but it is not intended by Amazon and I did not want to take a different approach. The second problem is that the installation routine does more than resolving the dependencies. As one can see, the app is first built into /tmp/deployment/application/. Afterwards it is deployed to /var/app and everything in tmp is cleaned up.

Update 2
Triggering the npm step in the deployement chain is just possible if the deployment failed in this step before. Otherwise, there is no data in the tmp directory.

Customizing and Configuring AWS Elastic Beanstalk Environments

In fact, I cheated a bit. Instead of trying the “naive package.json” way I googled directly for a solution and found this post from Ben Delarre:
http://delarre.net/posts/deploying-libcouchbase-with-aws-elasticbeanstalk/

Amazon already has a hook in its deployment process to configure and customize the environment. It is described here and works the following way:

  1. Create a YAML file in the .elasticbeanstalk folder of your project
  2. Name it [your name].config
  3. Upload it

Ben used this concept in a smart way to define a YAML file executing the needed shell commands. Unfortunately his trick did not work for me. I created a YAML file validated it(!) with the validator on http://yamllint.com/. Then I SSHed to my machine. The file was uploaded but had no effect.
I checked if it worked with the following commands:

If you don’t have SSH to your machine and just deploy your app to EB you will probably get exactly the same error as displayed above.

Manual Installation

The trick with the config file did not work for me and I couldn’t find any other solutions. The only thing that was left was a manual installation of libcouchbase:

  1. SSH to your machine
  2. sudo wget -O/etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos62-x86_64.repo
  3. sudo yum check-update
  4. $ sudo yum install -y libcouchbase2-libevent libcouchbase-devel
  5. create package.json file with couchbase dependency
  6. upload your file

The relevant steps are defined on the Couchbase site and they worked for me. However, you will lose the auto-scaling capability of your system. Whenever AWS creates a new instance for you, libcouchbase will be missing and your app will crash.

Hopefully I will find a more stable solution. If anyone has suggestions please leave a comment.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">