Configure hazelcast with EC2
Hazelcast is hands down a great caching tool when it comes to a JVM based application. If you use Amazon Web Services Hazelcast integrates wonderfully.
First task is to create a policy responsible for describing instances. We shall name this policy as describe-instances-policy.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1467219263000", "Effect": "Allow", "Action": [ "ec2:DescribeInstances" ], "Resource": [ "*" ] } ] }
Applications that have to access amazon resources, should either use a user or a role that has the policies for the resources we need attached. Using an amazon user for your application is a bad practice and It becomes a maintenance headache managing keys, let alone security issues. Therefore we will focus on hazelcast configuration using IAM roles.
Our role will be called my-ec2-role and will have the policy describe-instances-policy attached.
By doing so an ec2 instance with hazelcast would be able to retrieve the private ip’s of other ec2 instances and therefore would attempt to identify which instances are eligible to establish a distributed cache.
Now we can proceed to the hazelcast configuration. We can either do a java based configuration or an xml based configuration.
Let us start with the xml configuration.
<hazelcast xsi:schemaLocation="https://hazelcast.com/schema/config https://hazelcast.com/schema/config/hazelcast-config-3.7.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <group> <field>ec2-group</field> <password>ec2-password</password> </group> <network> <join> <multicast enabled="false"> </multicast> <tcp-ip enabled="false"> </tcp-ip> <aws enabled="true"> <!--optional, default is us-east-1 --> <region>eu-west-1</region> <iam-role>my-ec2-role</iam-role> <!-- optional, only instances belonging to this group will be discovered, default will try all running instances --> <security-group-field></security-group-field> <tag-key></tag-key> <tag-value></tag-value> </aws> </join> </network> </hazelcast>
And the main class to load the xml file.
package com.gkatzioura.hazelcastec2; import com.hazelcast.config.*; import com.hazelcast.core.Hazelcast; /** * Created by gkatzioura on 7/26/16. */ public class HazelCastXMLExample { public static void main(String args[]) { Config config = new ClasspathXmlConfig("hazelcast.xml"); Hazelcast.newHazelcastInstance(config); } }
Pay extra attention that multicast and tcp-ip should be disabled. Since we specify an IAM role there is no need to provide credentials. Tag-key and Tag-value represent the tags that you can add on an ec2 machine. In case you specify tag key and value a connection will be established only on machine that have the same tag and value.
You can have the security-group-field empty. Hazelcast uses this information for instance filtering however you must make sure the security group that the ec2 instance uses has ports 5701, 5702, and 5703 open for inbound and outbound traffic.
The java configuration follows the same rules.
package com.gkatzioura.hazelcastec2; import com.hazelcast.aws.AWSClient; import com.hazelcast.config.AwsConfig; import com.hazelcast.config.Config; import com.hazelcast.config.GroupConfig; import com.hazelcast.config.JoinConfig; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; /** * Created by gkatzioura on 7/25/16. */ public class HazelCastJavaExample { public static void main(String args[]) { Config config = new Config(); GroupConfig groupConfig = new GroupConfig(); groupConfig.setName("ec2-group"); groupConfig.setPassword("ec2-password"); config.setGroupConfig(groupConfig); JoinConfig joinConfig = config.getNetworkConfig().getJoin(); joinConfig.getTcpIpConfig().setEnabled(false); joinConfig.getMulticastConfig().setEnabled(false); AwsConfig awsConfig = joinConfig.getAwsConfig(); awsConfig.setIamRole("my-ec2-role"); awsConfig.setEnabled(true); awsConfig.setRegion("eu-west-1"); Hazelcast.newHazelcastInstance(config); } }
After uploading your hazelcast apps to ec2 and run them you can see the following log
Jul 26, 2016 6:34:50 PM com.hazelcast.cluster.ClusterService INFO: [172.31.33.104]:5701 [dev] [3.5.4] Members [2] { Member [172.31.33.104]:5701 this Member [172.31.41.154]:5701 }
I have added a gradle file for some quick testing either with xml or java configuration.
group 'com.gkatzioura' version '1.0-SNAPSHOT' apply plugin: 'java' sourceCompatibility = 1.5 repositories { mavenCentral() } apply plugin: 'idea' dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' compile group: 'com.hazelcast', name:'hazelcast-cloud', version:'3.5.4' } task javaConfJar(type: Jar) { manifest { attributes 'Main-Class': 'com.gkatzioura.hazelcastec2.HazelCastJavaExample' } baseName = project.name + '-jconf' from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } with jar } task javaXMLJar(type: Jar) { manifest { attributes 'Main-Class': 'com.gkatzioura.hazelcastec2.HazelCastXMLExample' } baseName = project.name + '-xmlconf' from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } with jar }
You can find the sourcecode on github.
Reference: | Configure hazelcast with EC2 from our JCG partner Emmanouil Gkatziouras at the gkatzioura blog. |