Setting up a RethinkDB Cluster on Docker Swarm Mode

First we need to enable Swarm Mode and create a dedicated network for our RethinkDB cluster:

# initialize swarm
docker swarm init

# create RethinkDB overlay network
docker network create --driver overlay rdb-net

We start building our RethinkDB cluster by running a single RethinkDB server, we will remove this instance later on:

# create and start rethinkdb primary 
docker service create --name rdb-primary --network rdb-net --replicas 1 rethinkdb:latest rethinkdb --bind all --no-http-admin

Now we can create a secondary RethinkDB node that will join the rdb-primary node and form a cluster:

# create and start rethinkdb secondary
docker service create --name rdb-secondary --network rdb-net --replicas 1 rethinkdb:latest rethinkdb --bind all --no-http-admin --join rdb-primary

Scale the secondary node so we can have a minimum of 3 nodes needed for RethinkDB automatic fail-over mechanism:

# up 3 nodes (primary + two secondary) to enable automatic failover
docker service scale rdb-secondary=2

We now have a functional RethinkDB cluster, but we are not done yet. Because we started the primary node without a join command, our cluster has a single point of failure. If for some reason rdb-primary container crashes, the Docker Swarm engine will recreate and start this container, but he can’t join the existing cluster. If we start new rdb-secondary instances, they will join the new rdb-primary container and form another cluster.

To resolve this issue we have to remove the rdb-primary service and recreate it with the join command like so:

# remove primary
docker service rm rdb-primary

# recreate primary with --join flag
docker service create --name rdb-primary --network rdb-net --replicas 1 rethinkdb:latest rethinkdb --bind all --no-http-admin --join rdb-secondary

Now we can also scale the primary node:

# start two rdb-primary instances
docker service scale rdb-primary=2

At this point we have 4 nodes in our cluster, two rdb-primary and two rdb-secondary. We can further scale any of these two services and they will all join our cluster. If a rdb-primary or rdb-secondary instance crashes, the Docker Swarm will automatically start another container that will join our current cluster.

Last step is to create a RethinkDB proxy node, we expose port 8080 for the web admin and port 28015 so we can connect to the cluster from our app:

# create and start rethinkdb proxy 
docker service create --name rdb-proxy --network rdb-net --publish 8080:8080 --publish 28015:28015 rethinkdb:latest rethinkdb proxy --bind all --join rdb-primary

Open a browser and navigate to http://localhost:8080 to check the cluster state. In the servers page you should see 4 servers connected to the cluster.

if we run docker service ls we should get:

ID            NAME           REPLICAS  IMAGE             
157bd7yg7d60  rdb-secondary  2/2       rethinkdb:latest  
41eloiad4jgp  rdb-primary    2/2       rethinkdb:latest  
67oci5m1wksi  rdb-proxy      1/1       rethinkdb:latest 

I’ve compiled all the above commands into a Powershell script that runs the RethinkDB cluster on Docker for Windows. Here is the script:

rethinkdb-swarm-up.ps1

# create and start rethinkdb primary 
docker service create --name rdb-primary --network rdb-net rethinkdb:latest rethinkdb --bind all --no-http-admin

Start-Sleep -s 5

# create and start rethinkdb secondary
docker service create --name rdb-secondary --network rdb-net rethinkdb:latest rethinkdb --bind all --no-http-admin --join rdb-primary

Start-Sleep -s 5

# up 3 nodes (primary + 2 secondary) to enable automatic failover
docker service scale rdb-secondary=2

Start-Sleep -s 5

# remove primary
docker service rm rdb-primary

# recreate primary with --join flag
docker service create --name rdb-primary --network rdb-net rethinkdb:latest rethinkdb --bind all --no-http-admin --join rdb-secondary

Start-Sleep -s 5

# start 2 rdb-primary instances
docker service scale rdb-primary=2

Start-Sleep -s 5

# create and start rethinkdb proxy 
docker service create --name rdb-proxy --network rdb-net --publish 8080:8080 --publish 28015:28015 rethinkdb:latest rethinkdb proxy --bind all --join rdb-primary

And the tear down script:

docker service rm rdb-proxy
docker service rm rdb-primary
docker service rm rdb-secondary

Source code and documentation can be found in github.com/stefanprodan/aspnetcore-dockerswarm repository.

comments powered by Disqus