How to setup a Connect2id server cluster in the AWS cloud

The clustering stack of the Connect2id server is based on Infinispan and JGroups, and out of the box it’s configured for UDP/IP multicast node discovery and message passing. Multicast is the most efficient way to pass messages around a cluster, especially with many nodes, thanks to its minimal networking overhead. In order for multicast to work, the Connect2id server nodes must be on the same subnet, connected to the same (physical) switch / router.

Unfortunately AWS and other popular cloud provider don’t support IP multicast, due to limitations of their virtual environments. Therefore, in order to deploy a Connectid server cluster in the AWS cloud, the Infinispan / JGroups stack must be configured for different networking:

  • S3_PING for initial node auto-discovery, where a shared S3 bucket is used to let the Connect2id server nodes discover one another when a new one goes up.

  • TCP for passing messages between the Connect2id server nodes.

Setup instructions

Step 1. Create an AWS user

We first need to create a dedicated AWS user for Connect2id server nodes to access the S3 bucket.

Sign in to the AWS console and click on the Identity and Access Management (IAM) tab.

Creating a new AWS user

Under Users click on Create New Users and enter the desired username, e.g. c2id. Make sure Generate an access key for each user is selected. Then click on Create.

Record the generated user credentials:

  • Access key ID, e.g. AKIAIHGHNQXQKYJEPEMA
  • Secure access key, e.g. GjE5InROhZXvysBLyrRL0mJkjlrUJpMxLX7YUwhF

Also, record the ARN (Amazon Resource Identifier) for the new user. This can be viewed when you choose the c2id user in the IAM users lists.

  • User ARN, e.g. arn:aws:iam::673931619296:user/c2id

No other credentials are required for the c2id user. Note that you must be the AWS account administrator or have the required permission to be able to create a new user.

Step 2. Create S3 bucket

Click on the S3 management tab and then on Create Bucket.

Enter a bucket name, e.g. s3ping-infinispan-c2id.

Creating a new S3 bucket

The name will be used to construct the bucket URL, i.e. https://s3ping-infinispan-c2id.s3.amazonaws.com and should therefore contain letters, numbers and dashes only. Do not include dots as this will cause SSL certificate validation problems later on!

Step 3. Assign permission policy to S3 bucket

Left-click on the newly created S3 bucket and select Properties, then Permissions. This will open up a panel where you can specify the access permissions for the bucket.

Click on Edit bucket policy and paste the following JSON in the provided text area:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "[USER-ARN]"
            },
            "Action": [
                "s3:GetObjectVersion",
                "s3:DeleteObject",
                "s3:DeleteObjectVersion",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::[BUCKET]/*"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "[USER-ARN]"
            },
            "Action": [
                "s3:ListBucketVersions",
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::[BUCKET]"
        }
    ]
}

where [USER-ARN] should be replaced with the ARN of the registered user (step 1), e.g. arn:aws:iam::673931619296:user/c2id and [BUCKET] with the bucket name (step 2), e.g. s3ping-infinispan-c2id.

Click on Save to apply the entered policy to the S3 bucket. The registered jgroups user will then have permission to list the bucket’s content and view, create and delete objects in it.

Step 4. Configure Infinispan / JGroups for S3_PING discovery

The Connect2id server WAR package comes with a set of ready JGroups configurations. For AWS with S3_PING use default-jgroups-s3ping.xml. To apply it, open your current Infinispan configuration file, e.g. /WEB-INF/infinispan-mysql.xml, and update the jgroups file path like this:

<jgroups>
   <stack-file name="jgroups-config" path="default-jgroups-s3ping.xml"/>
</jgroups>

Then pass the following Java system properties to each Connect2id server node:

Property name Description
jgroups.s3.bucket The name of the S3 bucket
jgroups.s3.access_key The access key for the AWS user
jgroups.s3.secret_access_key The secure access key for the AWS user
jgroups.tcp.address (Optional) By default the Connect2id server will bind the JGroups socket to a site local (non routable) IP address, e.g. from the 192.168.0.0 or 10.0.0.0 address range. Override to specify a different IP address to bind to.

These Java system properties can be passed on JVM startup with the -D command line parameter, e.g. by editing tomcat/bin/setenv.sh (if you’re using a Tomcat web server).

export CATALINA_OPTS="$CATALINA_OPTS -Djgroups.s3.bucket=s3ping-infinispan-c2id -Djgroups.s3.access_key=AKIAIHGHNQXQKYJEPEMA -Djgroups.s3.secret_access_key=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"

Alternatively, if you’re using Amazon’s Elastic Beanstalk you can set the properties from the EB console by selecting the application, clicking on Default configuration, then Configuration and finally Software Configuration. This will present you with a panel named Environment Properties where you can provide arbitrary properties to your application, including the the S3 bucket settings.

System properties

Step 5. Deploy your service / application to EC2

Deploy your Connect2id server nodes and check your server logs. If JGroups encounters a faulty S3_PING configuration it will throw a fatal exception and Infinispan will abort.

Some common exceptions and how to resolve them:

The S3 bucket name, access key or secret key may be invalid:

java.io.IOException: bucket ‘s3ping-infinispan-c2id’ could not be accessed (rsp=403 (Forbidden). Maybe the bucket is owned by somebody else or the authentication failed

or

org.infinispan.commons.CacheException: java.io.IOException: bucket ‘/tmp/jgroups’ could not be accessed (rsp=301 (Moved Permanently). Maybe the bucket is owned by somebody else or the authentication failed

You registered an S3 bucket name with dots, which caused the wildcard SSL certificate of AWS to be rejected by JGroups:

org.infinispan.commons.CacheException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching s3ping.cluster.c2id.s3.amazonaws.com found.

Automation

Note that the steps above can be fully automated via the AWS API:

  • JGroups user creation
  • Bucket creation and policy setting
  • Deployment to EC2 / Elastic Beanstalk and System Properties setting.

comments powered by Disqus