This article demonstrates the use of IBM WebSphere Application Server in the Amazon Elastic Compute Cloud (Amazon EC2), in the Amazon Web Services (AWS) family. We show how WebSphere Liberty, a lightweight, dynamic Java application server can be scaled and load balanced by EC2 components.

By Mark Nuttall and Jeremy Hughes

Nobody working in IT today can have missed the current trend towards cloud computing. This term refers to a move from companies owning and managing local machinery on which to run their websites and corporate IT systems, towards renting computing resource online. Amazon Web Services was one of the first successful providers of Infrastructure as a service (IaaS) – virtual machines and network infrastructure, available for hire on a ‘pay as you go’ basis.

This first article deals with the simplest interesting topic available to us: WebSphere Liberty running in Amazon EC2 virtual machines, scaled and load balanced by the default EC2 services. In this model, we have one Liberty instance running per virtual machine (VM). Scaling is performed at the VM level: if load is too high, another VM is started, and then stopped once overall load has fallen.


You will need an Amazon Web Services account with access to EC2, VPC, and CloudFormation. We’ll take the following steps to get this sample working:

  1. Create an Amazon Machine Image (AMI).
  2. Decide where to deploy the sample.
  3. Install the sample using Cloud Formation.
  4. Test that the application works.

Building an AMI

The virtual machine is the simplest unit of scaling and load balancing in AWS EC2. An AutoScalingGroup has a particular virtual machine image that it uses as a template when creating new runtime instances. These snapshots are called AMIs, Amazon Machine Images. In our case we want an AMI for a simple Linux virtual machine which starts a Liberty server instance when the VM starts.

There are many ways to create an AMI. We take the most manual route in the steps below. This involves creating a basic virtual machine, installing Liberty, and then creating an AMI from that instance by taking a snapshot from the web-based AWS Management Console. This manual route is good for learning about the process but is typically automated in a real project. See for example the section Building an AMI using Packer in Arthur Barr’s recent MQdev Blog post.

Before getting started you should be able to launch virtual machine instances from the EC2 dashboard, and SSH into those instances. Exactly how you do this will depend on your local operating system. Once you have SSH working, follow these steps to manually create a Liberty AMI:

  1. From the EC2 dashboard launch an instance based on the Red Hat Enterprise Linux (RHEL) AMI or Amazon Linux. By default, this will create a new security group launch-wizard-n granting SSH access to the VM. Back in the EC2 Dashboard, find the new instance and its Public DNS so you can SSH to it.
  2. On RHEL only, install unzip: sudo yum -y install unzip
  3. On RHEL only, install Java: sudo yum -y install java
  4. Download Liberty: curl -O http://repo1.maven.org/maven2/com/ibm/websphere/appserver/runtime/wlp-webProfile7/8.5.5.9/wlp-webProfile7-8.5.5.9.zip
  5. Unzip Liberty: sudo sg ec2-user "unzip wlp-webProfile7-8.5.5.9.zip -d /opt/websphere"
  6. Set up environment variables:
    1. Run echo "PATH=/opt/websphere/wlp/bin:$PATH" >> ~/.bashrc
    2. Run echo "export WLP_USER_DIR=~/liberty" >> ~/.bashrc
    3. Run source ~/.bashrc
  7. Create a Liberty server: server create
  8. Install the ferret sample application: curl http://repo1.maven.org/maven2/net/wasdev/wlp/sample/ferret/1.0/ferret-1.0.war -o ~/liberty/servers/defaultServer/dropins/ferret-1.0.war
  9. Liberty is secure out of the box. The default configuration must be changed to permit remote HTTP access. Since we’re going to be enabling public internet access, edit the “ stanza in ~/liberty/servers/defaultServer/server.xml:
        <httpEndpoint id="defaultHttpEndpoint"
                    httpPort="9080"
                    host="*"
                    httpsPort="9443" />
      

  10. Run the server: server run

  11. Test the instance! When you created the instance, EC2 created a new security group for you. Add a rule to that group for the port that Liberty is going to listen on:
    1. Find Network & Security > Security Groups in the EC2 Dashboard.
    2. Find the security group you just created (group name starts launch-wizard-). Select it.
    3. On the Inbound tab, click Edit > Add rule to create a custom tcp rule with a port range of 9080, and a source of Anywhere.
    4. Using the Public DNS of the instance you used in the ssh command, access the sample app in a web browser: http://[public dns]:9080/ferret should show the running sample application.
  12. Finally, create an AMI from the running instance:
    1. Click Instances > instances.
    2. Locate the instance you just worked on.
    3. Right-click Image > Create image.
    4. Give it a name, click Create Image.
    5. You’ll get a pop-up saying the Create Image request received. Make a note of the image ID that starts ami-

Deploying to AWS EC2 using Cloud Formation

AWS Cloud Formation enables developers and administrators to create collections of AWS resources from templates stored as JSON files. This is an example of the declarative approach to treating infrastructure as code – see here and here for overviews of the subject. The JSON template below is enough to create a scaled, load-balanced deployment.

It is, however, only suitable for development purposes: there’s a lot more that needs to be done to create a production environment. For example, we use a single availability zone for simplicity, whereas Amazon recommend multiple availability zones for production deployments. See Andrew Sullivan’s excellent presentation for an overview of the many issues that must be considered when building a production-ready environment. Also please note that we’re downloading Liberty from WASdev.net: see this short article which explains what you can use this download for.

The JSON code below can be used to create an instance of the architecture shown in the diagram above. It takes several parameters:

  • The identity of the Virtual Private Cloud (VPC) in which to create the deployment. We’ve tested this using the default VPC; the script may need modification in order to work with a different VPC.
  • An availability zone – essentially a virtual local area network – within the VPC to deploy into.
  • An Amazon Machine Image (AMI) identity from which to create virtual machine images.

The only Liberty-specific section of this template is the UserData section of the Launch Configuration: this is the script that starts Liberty instances once a virtual machine instance is running.

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "myVPC" : {
      "Type" : "String",
      "Description" : "VpcId of your existing Virtual Private Cloud (VPC)"
    },
    "availZone" : {
      "Type" : "String",
      "Description" : "The Availability Zone to deploy into"
    },
    "ami" : {
      "Type" : "String",
      "Description" : "The AMI to deploy"
    }
  },
  "Resources": {
    "basicLb": {
      "Type": "AWS::ElasticLoadBalancing::LoadBalancer",
      "Properties": {
        "AvailabilityZones" : [
          {
            "Ref": "availZone"
          }
        ],
        "HealthCheck": {
          "HealthyThreshold": "5",
          "Interval": "5",
          "Target": "HTTP:9080/",
          "Timeout": "3",
          "UnhealthyThreshold": "2"
        },
        "ConnectionDrainingPolicy": {
          "Enabled": "true",
          "Timeout": "300"
        },
        "ConnectionSettings": {
          "IdleTimeout": "60"
        },
        "CrossZone": "true",
        "SecurityGroups": [
          {
            "Ref": "sgwebtraffic"
          }
        ],
        "Listeners": [
          {
            "InstancePort": "9080",
            "LoadBalancerPort": "80",
            "Protocol": "HTTP",
            "InstanceProtocol": "HTTP"
          }
        ]
      }
    },
    "asg1": {
      "Type": "AWS::AutoScaling::AutoScalingGroup",
      "Properties": {
        "AvailabilityZones": [
          {
            "Ref": "availZone"
          }
        ],
        "Cooldown": "300",
        "DesiredCapacity": "2",
        "HealthCheckGracePeriod": "300",
        "HealthCheckType": "EC2",
        "MaxSize": "5",
        "MinSize": "2",
        "LaunchConfigurationName": {
          "Ref": "lcBasicdemolaunchconfig"
        },
        "LoadBalancerNames": [
          {
            "Ref": "basicLb"
          }
        ],
        "TerminationPolicies": [
          "Default"
        ]
      }
    },
    "lcBasicdemolaunchconfig": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "Properties": {
        "ImageId": {
            "Ref": "ami"
        },
        "InstanceType": "t2.micro",
        "SecurityGroups": [
          {
            "Ref": "sgwebtraffic"
          }
        ],
        "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [
          "#!/bin/bash n",
          "runuser -l ec2-user -c 'server start' n"
        ]]}}
      }
    },
    "sgbase": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Basic - SSH open",
        "VpcId": { "Ref" : "myVPC" }
      }
    },
    "sgwebtraffic": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "9000-9499",
        "VpcId": { "Ref" : "myVPC" }
      }
    },
    "scalingIncreaseGroupSize": {
      "Type": "AWS::AutoScaling::ScalingPolicy",
      "Properties": {
        "AdjustmentType": "ChangeInCapacity",
        "ScalingAdjustment": "1",
        "AutoScalingGroupName": {
          "Ref": "asg1"
        }
      }
    },
    "scalingDecreaseGroupSize": {
      "Type": "AWS::AutoScaling::ScalingPolicy",
      "Properties": {
        "AdjustmentType": "ChangeInCapacity",
        "ScalingAdjustment": "-1",
        "AutoScalingGroupName": {
          "Ref": "asg1"
        }
      }
    },
    "cpuTooHighAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "ActionsEnabled": "true",
        "ComparisonOperator": "GreaterThanOrEqualToThreshold",
        "EvaluationPeriods": "1",
        "MetricName": "CPUUtilization",
        "Namespace": "AWS/EC2",
        "Period": "300",
        "Statistic": "Average",
        "Threshold": "50.0",
        "AlarmActions": [
          {
            "Ref": "scalingIncreaseGroupSize"
          }
        ],
        "Dimensions": [
          {
            "Name": "AutoScalingGroupName",
            "Value": "auto scaling group 1"
          }
        ]
      }
    },
    "cpuLowAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "ActionsEnabled": "true",
        "ComparisonOperator": "LessThanOrEqualToThreshold",
        "EvaluationPeriods": "4",
        "MetricName": "CPUUtilization",
        "Namespace": "AWS/EC2",
        "Period": "300",
        "Statistic": "Average",
        "Threshold": "30.0",
        "AlarmActions": [
          {
            "Ref": "scalingDecreaseGroupSize"
          }
        ],
        "Dimensions": [
          {
            "Name": "AutoScalingGroupName",
            "Value": "auto scaling group 1"
          }
        ]
      }
    },
    "ingress19": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {
          "Ref": "sgwebtraffic"
        },
        "IpProtocol": "tcp",
        "FromPort": "80",
        "ToPort": "80",
        "CidrIp": "0.0.0.0/0"
      }
    },
    "ingress20": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {
          "Ref": "sgwebtraffic"
        },
        "IpProtocol": "tcp",
        "FromPort": "9000",
        "ToPort": "9499",
        "CidrIp": "0.0.0.0/0"
      }
    },
    "ingress21": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {
          "Ref": "sgwebtraffic"
        },
        "IpProtocol": "tcp",
        "FromPort": "443",
        "ToPort": "443",
        "CidrIp": "0.0.0.0/0"
      }
    }
  },
  "Description": "Basic load balanced deployment"
}
  

Follow these steps to create a running, scaled Liberty deployment:

  1. Make a note of the default VPC ID from the VPC Dashboard.
  2. Save the JSON above to a local file.
  3. Run the JSON through Amazon Cloud Formation: from the Cloud Formation page, click Create Stack. Within the Choose template section, browse to your locally saved copy of the JSON.
  4. Give the stack a name, provide the Liberty AMI ID and the VPC ID you noted from the steps above, and provide the availability zone you prefer to use. For example, us-east-1b. Click Next, then Create. The stack takes a few minutes to create.
  5. From the EC2 Dashboard, select Load Balancers and select the newly created load balancer. The Description page lists the DNS name of the load balancer. Use this public internet address of the created Load Balancer from the EC2 Dashboard menu and access that address using a web browser: you should see the default Liberty landing page.
  6. Access the /ferret endpoint to see the running ferret sample application.

You’ll need a more demanding web application before you can use a performance test harness to drive CPU load above the threshold required to instantiate more servers, even if you reduce the thresholds from those in our sample. You can use Amazon’s CloudWatch service to monitor the state and health of your virtual machine instances. Once you’re done testing your application you can delete the entire stack from the Cloud Formation menu.

Summary and next steps

We’ve shown how to get a sample Liberty application up and running in Amazon AWS, using the default Amazon scaling and load-balancing facilities. While some parts of the process were nicely automated, there was some manual work required to build an AMI. We also rather glossed over the application code, simply downloading a finished binary from well-known location. We intend to demonstrate more extensive automation in a future article.

12 comments on"Getting started with WebSphere Liberty in Amazon Web Services"

  1. Hi,
    The latest version of Liberty is 17.0.0.2. However i see that you are using 8.5.5.9. Can you clarify the difference? I am trying to download Liberty latest version and confused with the above. Thanks in advance.
    Regards, Mad Pil

  2. Even after server start and adding security groups with 8090 it does not shows up in browser. Still getting “This site can’t be reached”.

  3. In this example, ELB is used to load balance liberty profile servers. In case of cluster or ND case, Do you think the same configuration can be applied? I guess the current Network Deployment requires use of the Web Server in front of the liberty server. I am not sure if there is really a need for web server when using ELB.

    • Mark Nuttall January 06, 2017

      Hi Jags,
      You might need to use IBM HTTP Server (IHS) if you were using some of the application-aware routing capabilities in WebSphere ND, or if you had run up against some other technical limitation in Amazon ELB that was solved in IHS. I would expect Amazon ELB to be sufficient for many usage scenarios. One area I haven’t investigated is, what if you’re hosting large amounts of static content? You typically don’t want to serve that from an application server, so IHS could be useful in those cases, unless Amazon provides a better means of doing so.

      Regards,
      Mark

  4. Hi again Raj,
    Can I just check if you’re asking about WebSphere traditional or WebSphere liberty, please? Obviously the previous link is only applicable to WAS traditional. Many thanks,

    — Mark

  5. Name Mark Nuttall August 31, 2016

    Hi Raj,
    I’ve just finished testing WAS traditional ND clusters in AWS EC2. I’m not sure that there’s a lot to add to our existing documentation and design guidelines, because AWS EC2 virtual machines look just like any other remote datacenter. It’s not my specialist subject but I believe that Tom Alcott’s ‘Can I run a WebSphere Application Server cell over multiple data centers?’ at http://www.ibm.com/developerworks/websphere/techjournal/0606_col_alcott/0606_col_alcott.html is still as relevant as ever.

    Regards,
    Mark

  6. Hi,

    Nice article. Do you have any documents, pointers to setup Web Sphere Cluster and replicating the cluster to a DR region in AWS?

    thanks

Join The Discussion

Your email address will not be published. Required fields are marked *