Clustering WSO2 Identity Server and Load balancing it with WSO2 Elastic Load Balancer
- Chamara Ariyarathne
- Associate Technical Lead - QA - WSO2
The WSO2 Identity server 4.5.0 and WSO2 Enterprise Load Balancer 2.1.0 is now released. So with this post I'm going to guide you with each and every and complete set of steps on how to cluster Identity server with two nodes and loadbalance it with ELB. And this setup is going to be in one Ubuntu machine.
Prerequisites:
1. Ubuntu 12.04 or a Linux similar platform
2. Java 1.6 or above (I'm using 1.7.0_25 64-bit)
3. Mysql (I'm using Ver 14.14 Distrib 5.5.32)
Let's go through the steps on how to cluster IS
1. Pointing to same User store and User Management db.
Being a cluster of IS, every node need to share the same User Store and User Management databases. So that every request come through load balancer will be served by any node similarly.
For User Store you can use any LDAP as Active Directory, Apache DS, OpenLDAP etc. Here I'm using the JDBC userstore which is supported by Identity Server to use a relational database as the user store.
I'm using mysql database for this.
Create a new database
mysql -uroot -proot
mysql> create database is_user_store;
Populate the tables needed. For that you can use the db scripts in the dbscripts directory in Identity Server home.
${IS_HOME}/dbscripts/mysql.sql ${IS_HOME}/dbscripts/identity/mysql.sql ${IS_HOME}/dbscripts/service-provider/mysql.sql
mysql> source mysql.sql; mysql> source identity/mysql.sql; mysql> source service-provider/mysql.sql;
Now you have to use this database in the configurations. For the User Store you have to add the following configurations;
In the;
${IS_HOME}/repository/conf/datasources/master-datasources.xml
Have the configuration
WSO2_USERSTORE_DB The datasource used for registry and user manager jdbc/WSO2UserStoreDB jdbc:mysql://localhost:3306/is_user_store root root com.mysql.jdbc.Driver 50 60000 true SELECT 1 30000
And that jndi database reference have to be used in the user-mgt.xml as to use it as the userstore
${IS_HOME}/repository/conf/user-mgt.xml
org.wso2.carbon.user.core.tenant.JDBCTenantManager false 100 false default SHA-256 true true true false ^[\S]{5,30}$ ^[\S]{5,30}$ ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ ^[\S]{3,30}$ ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ ^[\S]{3,30}$ true 100 100 false false jdbc/WSO2UserStoreDB
And for that to be the Primary userstore of the IS that need to be on top in the user-mgt.xml as the first mentioned userstore configuration. Every other userstore configuration you specify will be secondary userstores with a domain name.
and this has to be done in both of the IS nodes.
Now lets create another db and set it as the User Management db. Run the scripts to populate tables and refer it in the master-datasources.xml as following.
WSO2_UM_DB The datasource used for registry and user manager jdbc/WSO2UserMgtDB jdbc:mysql://localhost:3306/is_user_mgt root root com.mysql.jdbc.Driver 50 60000 true SELECT 1 30000
You have to refer this in the user-mgt.xml as in following.
true admin admin admin everyone jdbc/WSO2UserMgtDB
Now the User management related configurations are done. The next step is sharing the config and governance registries among each IS nodes. That is called Registry Mounting.
2. Registry Mounting
Let's create a database to be used in the mount configurations so that it will be the same repository for both IS nodes to share as the Config and Governance collections. That will be called the Mounted db. However for each IS node, the local registry will still be pointed to each and every node's H2 database. That configuration is already there in the master-datasources.xml. That need not to be changed.
You'll have to create a database in mysql and populate the tables. Let's see how it will be refered in the configurations.
First in the;
${IS_HOME}/repository/conf/datasources/master-datasources.xml
WSO2_MOUNT_DB The datasource used for registry and user manager jdbc/WSO2ISMountDB jdbc:mysql://localhost:3306/is_mount_db root root com.mysql.jdbc.Driver 50 60000 true SELECT 1 30000
And now this jndi database reference will be used in both nodes as in;
${IS_HOME}/repository/conf/registry.xml
wso2registry false true / jdbc/WSO2CarbonDB jdbc/WSO2ISMountDB application/xacml-policy+xml
instanceid mounted_registry false true / instanceid /_system/nodes instanceid /_system/governance
Now let's look at the clustering configurations.
3. Clustering of IS nodes
We need to cluster two IS nodes as management nodes, and load balance it with WSO2 ELB.
First let's look at Identity Server configurations.
This is for the IS node 1.
${IS_HOME}/repository/conf/axis2/axis2.xml
There is a section as "clustering". You have to find the place and edit as following.
wka
We have to specify a domain for Identity Server cluster. And this domain name need to be unique from other WSO2 product clusters. Even from ELB domain.
wso2.is.chamara.domain
4001
${IS_HOME}/repository/conf/carbon.xml
1
wso2.is.chamara.com
wso2.is.chamara.com
This hostname will be the one that is used by IS cluster and the ELB. It need to be specified in the;
/etc/hosts
as;
127.0.0.1 wso2.is.chamara.com
In the carbon.xml we are specifying the deployment synchronizer configuration as well. Here I'm using svn based deployment synchronizer. So you'll have to find your own svn server and specify a location. Or else you can use Registry Based Deployment Synchronizer
true true true svn https://svnexample.wso2.com/svn/chamara450 wso2 wso2123 true
I'm going to run ELB on default HTTP/HTTPS ports which are 80/443.
So we have to specify those as proxy ports in the
${IS_HOME}/repository/conf/tomcat/catalina-server.xml
Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="9763" proxyPort="80"
Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="9443" proxyPort="443"
In the IS node 2 the configurations are almost same as for node1. The only differences that need to be changed are; in;
${IS_HOME}/repository/conf/axis2/axis2.xml
4002
and in;
${IS_HOME}/repository/conf/carbon.xml
2
4. Sharing of same keystores in IS cluster and ELB
In this step I'm going to explain how to use the same keystore in three servers and having certificates in the truststores. We can always use the default keystore wso2carbon.jks and it's public certificates. But in this case since we are using ELB in default ports, the servers need to have same keystore with the Common Name as the domain name (CN=wso2.is.chamara.com). So here are the steps to generate your own keystore.
$ keytool -genkey -alias iscarbon -keyalg RSA -keysize 1024 -keypass iscarbon -keystore iscarbon.jks -storepass iscarbon What is your first and last name? [Unknown]: wso2.is.chamara.com What is the name of your organizational unit? [Unknown]: users.wso2 What is the name of your organization? [Unknown]: wso2 What is the name of your City or Locality? [Unknown]: Colombo What is the name of your State or Province? [Unknown]: Western What is the two-letter country code for this unit? [Unknown]: 94 Is CN=wso2.is.chamara.com, OU=users.wso2, O=wso2, L=Colombo, ST=Western, C=94 correct? [no]: yes
Here for local testing purposes it is ok to use self signed certificate. If this is going to be used in production the public certificate need to be signed by Certificate Authority.
Now export the public certificate and import it to the server trust store. Here it need to be imported in two IS nodes and the ELB.
$ keytool -export -alias iscarbon -keystore iscarbon.jks -storepass iscarbon -file iscarbon.pem
$ keytool -import -alias iscarbon -file iscarbon.pem -keystore client-truststore.jks -storepass wso2carbon
Now we need to change the configuration files to use this new keystore as the server keystore. For that following locations needs to be updated accordingly.
identity.xml:${carbon.home}/repository/resources/security/iscarbon.jks identity.xml:iscarbon security/cipher-text.properties: Carbon.Security.KeyStore.Password=[iscarbon] security/cipher-text.properties: Carbon.Security.KeyStore.KeyPassword=[iscarbon] carbon.xml:${carbon.home}/repository/resources/security/iscarbon.jks carbon.xml:iscarbon carbon.xml:iscarbon carbon.xml:iscarbon axis2/axis2.xml:repository/resources/security/iscarbon.jks axis2/axis2.xml:iscarbon axis2/axis2.xml:iscarbon axis2/axis2.xml:iscarbon axis2/axis2.xml:repository/resources/security/iscarbon.jks axis2/axis2.xml:iscarbon axis2/axis2.xml:iscarbon axis2/axis2.xml:iscarbon
5. Configuring the Elastic Load Balancer
We are done with configuring the IS nodes. Lets look at how to configure the ELB
${ELB_HOME}/repository/conf/axis2/axis2.xml
wso2.chamara.lb.domain
this is a individual port unique from is nodes' localMemberPort
4100
For changing Transport ports (Proxy ports in IS nodes)
80
443
In the file
${ELB_HOME}/repository/conf/loadbalancer.conf
Remove all the services entries and add the following.
identity { domains { wso2.is.chamara.domain { tenant_range *; group_mgt_port 4000; mgt { hosts wso2.is.chamara.com; } } } }
In the ELB also you need to specify keystore configurations as above, in order to use the iscarbon.jks. Here you don't have add configure or add any identity.xml.
6. Running the cluster
Now we have come to the last part. First run the ELB. For run that you need to be the superuser of that computer since we are running ELB on default ports.
{ELB_HOME}# ./bin/wso2server.sh
Then run two IS servers.
{IS_HOME}$ ./bin/wso2server.sh
You will see the following logs in ELB while IS nodes joining ELB.
[2013-09-04 08:21:15,211] INFO - HazelcastGroupManagementAgent Member joined [ad2e310c-bf27-4bf3-9e03-afbe2117b6dd]: /127.0.0.1:4001 [2013-09-04 08:21:18,275] INFO - MemberUtils Added member: Host:127.0.0.1, Remote Host:null, Port: 4001, HTTP:9764, HTTPS:9444, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true [2013-09-04 08:21:18,276] INFO - HazelcastGroupManagementAgent Application member Host:127.0.0.1, Remote Host:null, Port: 4001, HTTP:9764, HTTPS:9444, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true joined application cluster
[2013-09-04 08:24:59,428] INFO - HazelcastGroupManagementAgent Member joined [3db96e0f-d4e9-4c45-bbdf-6331682a61cd]: /127.0.0.1:4002 [2013-09-04 08:25:02,493] INFO - MemberUtils Added member: Host:127.0.0.1, Remote Host:null, Port: 4002, HTTP:9765, HTTPS:9445, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true [2013-09-04 08:25:02,494] INFO - HazelcastGroupManagementAgent Application member Host:127.0.0.1, Remote Host:null, Port: 4002, HTTP:9765, HTTPS:9445, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true joined application cluster
And also while IS node joins each other following log will be appeared.
Node 1
[2013-09-04 08:22:15,083] INFO {org.wso2.carbon.core.clustering.hazelcast.util.MemberUtils} - Added member: Host:127.0.0.1, Remote Host:null, Port: 4000, HTTP:-1, HTTPS:-1, Domain: null, Sub-domain:null, Active:true [2013-09-04 08:22:23,314] INFO {org.wso2.carbon.core.clustering.hazelcast.HazelcastClusteringAgent} - Hazelcast initialized in 8228ms [2013-09-04 08:22:23,365] INFO {org.wso2.carbon.core.clustering.hazelcast.HazelcastClusteringAgent} - Local member: [bb0a0482-aea0-4895-a2f1-68ee721a38a5] - Host:127.0.0.1, Remote Host:null, Port: 4001, HTTP:9764, HTTPS:9444, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true [2013-09-04 08:22:23,374] INFO {org.wso2.carbon.core.clustering.hazelcast.util.MemberUtils} - Added member: Host:127.0.0.1, Remote Host:null, Port: 4001, HTTP:9764, HTTPS:9444, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true
[2013-09-04 08:24:59,430] INFO {org.wso2.carbon.core.clustering.hazelcast.wka.WKABasedMembershipScheme} - Member joined [3db96e0f-d4e9-4c45-bbdf-6331682a61cd]: /127.0.0.1:4002 [2013-09-04 08:25:01,494] INFO {org.wso2.carbon.core.clustering.hazelcast.util.MemberUtils} - Added member: Host:127.0.0.1, Remote Host:null, Port: 4002, HTTP:9765, HTTPS:9445, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true
Node 2
[2013-09-04 08:24:53,226] INFO {org.wso2.carbon.core.clustering.hazelcast.util.MemberUtils} - Added member: Host:127.0.0.1, Remote Host:null, Port: 4000, HTTP:-1, HTTPS:-1, Domain: null, Sub-domain:null, Active:true [2013-09-04 08:25:01,451] INFO {org.wso2.carbon.core.clustering.hazelcast.HazelcastClusteringAgent} - Hazelcast initialized in 8223ms [2013-09-04 08:25:01,481] INFO {org.wso2.carbon.core.clustering.hazelcast.util.MemberUtils} - Added member: Host:127.0.0.1, Remote Host:null, Port: 4001, HTTP:9764, HTTPS:9444, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true [2013-09-04 08:25:01,481] INFO {org.wso2.carbon.core.clustering.hazelcast.HazelcastClusteringAgent} - Local member: [3db96e0f-d4e9-4c45-bbdf-6331682a61cd] - Host:127.0.0.1, Remote Host:null, Port: 4002, HTTP:9765, HTTPS:9445, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true [2013-09-04 08:25:01,492] INFO {org.wso2.carbon.core.clustering.hazelcast.util.MemberUtils} - Added member: Host:127.0.0.1, Remote Host:null, Port: 4002, HTTP:9765, HTTPS:9445, Domain: wso2.is.chamara.domain, Sub-domain:mgt, Active:true
Now you can access the IS cluster Management Consoles using following url;
https://wso2.is.chamara.com/carbon/
Login using the default admin user {admin:admin}
Source : https://chamaraanuei.blogspot.com/2013/09/clustering-wso2-identity-server-and.html