Lice!

FiFo + 80LOC of Bash = 5 Node Riak Cluster

The reason

The question ‘why would I want at least 5 nodes’ comes up very often in the #riak IRC channel, there is a good explanation. But that’s boring, no one likes reading manuals, we, as engineers, like to try things out (aka. break stuff).

Only downside with that is that we need to set things up before we can break them, or even worst need to un-break it later to try out different things (aka. break it in different ways). Admittedly setting up a riak instance is easy but setting up 5 and connecting them then break them and do all again to break them again, erm… I mean try things out of cause, can get really tedious and I for once am too lazy to bother with that.

The goal

Make setting our breakage, erm test, bed setup as simple as possible, and whipping up things and tearing them down trivial, ideally have one simple command like ./riak.sh setup to do that for us and ./riak.sh delete undo it all for us to get back to a clean state.

The tools

To build anything we’ll need some tools, hammer and nails will not do us much good here so we are going to pick:

  • Project FiFo - my favourite virtualisation tool (I am biassed I wrote it), but it’s very easy to set up and very powerful.
  • The FiFo Console Client - we want to script things, a UI isn’t helpful.
  • bash - the simplest possible scripting tool.
  • curl - since riak offers a http fronted it’s a wonderful way to check if the system is up.
  • jsontool - a nifty utility to traverse JSON documents.

With that we should be set and good to go.

The steps

We’ll have to perform multiple steps to build our wracking ground for riak lets look at them one by one:

Preparing the environment

Before we can begin we’ve to set up a few things, I’ll not go into detail how to set up FiFo, there is a [good manual] for that with only like 5 steps required. So lets start at some of the script’s variables:

1
2
3
4
#/usr/bin/env bash
PACKAGE="small"
DATASET="base64-1.9.1"
NET="7df94bc3-6a9f-4c88-8f80-7a8f4086b79d"
  • smal is the name of the package created in FiFo, I picked something with 512MB of memory since that should be enough for now.
  • base64-1.9.1 is the dataset it means things are running in a solaris zone this also can be installed from the FiFo UI.
  • 7df94bc3-6a9f-4c88-8f80-7a8f4086b79d is the UUID of the network you can find that with fifo networks list
1
2
3
4
5
6
7
8
9
10
11
12
schroedinger:fifopy heinz [master] $ fifo packages list
                                UUID Name       RAM        CPU cap    Quota
------------------------------------ ---------- ---------- ---------- ----------
5f9f6c41-d700-4b4f-80f1-7350a71ed2e6 small      512 MB     100%       10 GB
schroedinger:fifopy heinz [master] $ fifo networks list
                                UUID Name       Tag                  First            Last
------------------------------------ ---------- ---------- --------------- ---------------
7df94bc3-6a9f-4c88-8f80-7a8f4086b79d test       admin        192.168.0.210   192.168.0.220
schroedinger:fifopy heinz [master] $ fifo datasets list
                                UUID Name       Version Type  Description
------------------------------------ ---------- ------- ----- ----------
60ed3a3e-92c7-11e2-ba4a-9b6d5feaa0c4 base       1.9.1   zone  A SmartOS ...

Creating a VM with riak installed

Creating a VM is rather simple we need a little JSON and pipe it to fifo with a cat. Please note the section reading user-script here we make the setup. Here is how it looks.

1
2
3
4
5
6
7
cat <<EOF | fifo vms create -p $PACKAGE -d $DATASET
{
  "alias": "riak1",
  "networks": {"net0": "$NET"},
  "metadata": {"user-script": "/opt/local/bin/sed -i.bak \\"s/pkgsrc/pkgsrc-eu-ams/\\" /opt/local/etc/pkgin/repositories.conf; /opt/local/bin/pkgin update; /opt/local/bin/pkgin -y install riak; export IP=\`ifconfig net0 | head -n 2 | tail -n 1 | awk '{print \$2}'\`; /opt/local/bin/sed -i.bak \\"s/127.0.0.1/\$IP/\\" /opt/local/etc/riak/app.config; /opt/local/bin/sed -i.bak \\"s/127.0.0.1/\$IP/\\" /opt/local/etc/riak/vm.args; svcadm enable epmd riak"}
}
EOF

To get a bit better look user script section and remove the escape things:

1
2
3
4
5
6
7
8
9
10
11
12
# We configure pkgin to use the european mirror you might not need to do that.
/opt/local/bin/sed -i.bak "s/pkgsrc/pkgsrc-eu-ams/" /opt/local/etc/pkgin/repositories.conf;
# We update the pkgin database and install riak
/opt/local/bin/pkgin update;
/opt/local/bin/pkgin -y install riak;
# We find out what IP our VM has from within the VM.
export IP=`ifconfig net0 | head -n 2 | tail -n 1 | awk '{print $2}'`;
# We update the app.config and vm.args to use the 'public' ip instead of the 127.0.0.1
/opt/local/bin/sed -i.bak "s/127.0.0.1/$IP/" /opt/local/etc/riak/app.config;
/opt/local/bin/sed -i.bak "s/127.0.0.1/$IP/" /opt/local/etc/riak/vm.args;
# Start epmd and riak
svcadm enable epmd riak

Waiting for riak

Now that is the first zone set up next we’ll want to wait for riak to properly start up. This is needed since the commands are asynchronous and installing the packages can be a tad slow. But we can just to curl the http interface to check for this, so it’s rather simple:

1
2
3
4
5
6
7
8
9
10
11
12
# We'll ask fifo for the IP of our first zone.
IP1=`fifo vms get riak1 | json networks[0].ip`
# Print some info so waiting is not so boring
echo -n 'Waiting until riak is up and running on the primary node.'
# now we curl the http interface every second to see if things are good.
until curl http://${IP1}:8098 2>/dev/null >/dev/null
do
  sleep 1
  echo -n '.'
done
# and we're done!
echo " done."

Setting up the remaining zones

We’re not going to get into too much details with this since it is pretty much working the same as the first VM with the only difference that the user-script holds two more lines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for i in 2 3 4 5
do
  cat <<EOF | fifo vms create -p $PACKAGE -d $DATASET
  {
    "alias": "riak${i}",
    "networks": {"net0": "$NET"},
    "metadata": {"user-script": "/opt/local/bin/sed -i.bak \\"s/pkgsrc/pkgsrc-eu-ams/\\" /opt/local/etc/pkgin/repositories.conf; /opt/local/bin/pkgin update; /opt/local/bin/pkgin -y install riak; export IP=\`ifconfig net0 | head -n 2 | tail -n 1 | awk '{print \$2}'\`; /opt/local/bin/sed -i.bak \\"s/127.0.0.1/\$IP/\\" /opt/local/etc/riak/app.config; /opt/local/bin/sed -i.bak \\"s/127.0.0.1/\$IP/\\" /opt/local/etc/riak/vm.args; svcadm enable epmd riak; sleep 10; /opt/local/bin/sudo -uriak /opt/local/sbin/riak-admin cluster join riak@${IP1}; /opt/local/bin/sudo -uriak /opt/local/sbin/riak-admin cluster plan; /opt/local/bin/sudo -uriak /opt/local/sbin/riak-admin cluster commit"}
  }
EOF
  IP=`fifo vms get riak$i | json networks[0].ip`
  echo -n "Waiting untill riak is up and running on the node $i."
  until curl http://${IP}:8098 2>/dev/null >/dev/null
  do
      sleep 1
      echo -n '.'
  done
  echo " done."

done

The two new lines are joining the node to the existing riak node which is quite easy, we can use $IP1 we generated in the first step too:

1
2
3
/opt/local/bin/sudo -uriak /opt/local/sbin/riak-admin cluster join riak@${IP1}
/opt/local/bin/sudo -uriak /opt/local/sbin/riak-admin cluster plan
/opt/local/bin/sudo -uriak /opt/local/sbin/riak-admin cluster commit

This is run that up and you’ve a 5 node riak cluster, and it’s quick at last if you’re in the US and have a good connection to the package repository.

Here is this all slapped together.

Comments