Skip to content
A short cloudy-serf lab. In order to watch how both tech are working together
Branch: master
Clone or download
Pull request Compare This branch is even with ismferd:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Firstly, I'm going to describe what is cloudy, Cloudy is a distribution based on Debian GNU/Linux, aimed at end users, to foster the transition and adoption of the Community Network cloud environment.

How it works

Cloudy use Serf in order to add or delete nodes from Cloudy.

What am I going to do?

  • Transform 4 raspberrys pi on Cloudy distro Cloudyning these.
  • Use 1 raspberry as Bootstrap Server.
  • Join the other raspberrys to cluster.
  • Check the resilence.
  • Expose services and watch how Serf through gossip will be able to communicate the changes to other nodes.

Let's do it

1- Cloudynizing raspberrys:

sudo apt-get update; sudo apt-get install -y curl lsb-release
curl -k |sudo  bash -
  • When the process is finished you will be able to connect to
cloudy:~$ nc -zv 7000
Connection to 7000 port [tcp/afs3-fileserver] succeeded!
  • You can check it in your navigator and you should watch something like:


2- Playing with Serf

As I said before, Cloudy uses Serf in order to get Failure detection, Service Discovery with Gossip and Custom Events.

  • First of all, I put the first member of the cluster as Bootsrap Server.
pi@raspberrypi:~ $ serf agent -bind=
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
         Node name: 'raspberrypi'
         Bind addr: ''
          RPC addr: ''
         Encrypted: false
          Snapshot: false
           Profile: lan

==> Log data will now stream in as it occurs:

    2019/03/09 16:46:57 [INFO] agent: Serf agent starting
    2019/03/09 16:46:57 [INFO] serf: EventMemberJoin: raspberrypi
    2019/03/09 16:46:58 [INFO] agent: Received event: member-join
    2019/03/09 16:50:02 [INFO] agent.ipc: Accepted client:
    2019/03/09 16:50:02 [INFO] serf: EventMemberUpdate: raspberrypi
    2019/03/09 16:50:03 [INFO] agent: Received event: member-update

Then, I can see the node inside the cluster:

pi@raspberrypi:~ $ serf members
raspberrypi  alive  
  • Joining more nodes to cluster:
pi@raspberry-1:~ $ serf agent -join= -bind=
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
         Node name: 'raspberry-1'
         Bind addr: ''
          RPC addr: ''
         Encrypted: false
          Snapshot: false
           Profile: lan
==> Joining cluster...(replay: false)
    Join completed. Synced with 1 initial agents

==> Log data will now stream in as it occurs:

    2019/03/09 17:05:36 [INFO] agent: Serf agent starting
    2019/03/09 17:05:36 [INFO] serf: EventMemberJoin: raspberry-1
    2019/03/09 17:05:36 [INFO] agent: joining: [] replay: false
    2019/03/09 17:05:36 [INFO] serf: EventMemberJoin: raspberrypi
    2019/03/09 17:05:36 [INFO] agent: joined: 1 nodes
    2019/03/09 17:05:37 [INFO] agent: Received event: member-join

NOTE: You can see the flag -join in the command, that is the reference to bootstrap server (you could do it from config files too).

pi@raspberrypi:~ $ serf members
raspberrypi  alive
raspberry-1  alive
  • I added the last one:
pi@raspberrypi:~ $ serf members
raspberrypi  alive
raspberry-1  alive
raspberry-1  alive

Before to start to add services I want to test the cluster's resilience.

  • I'm going to stop the node which role is bootstrap server.
    2019/03/10 09:50:30 [INFO] agent: Received event: member-update
^C==> Caught signal: interrupt
==> Gracefully shutting down agent...
    2019/03/10 09:59:41 [INFO] agent: requesting graceful leave from Serf
    2019/03/10 09:59:42 [INFO] serf: EventMemberLeave: raspberrypi
    2019/03/10 09:59:42 [INFO] agent: requesting serf shutdown
    2019/03/10 09:59:42 [INFO] agent: shutdown complete
  • I can see how the node has sent a new event "member-leave" to cluster.
    2019/03/10 09:59:42 [INFO] serf: EventMemberLeave: raspberrypi
    2019/03/10 09:59:43 [INFO] agent: Received event: member-leave
  • Watching members status again:
pi@raspberry-1:~ $ serf members
raspberrypi  left
raspberry-1  alive
raspberry-1  alive
  • Addding again the node to whichever 2 nodes with status alive.
pi@raspberrypi:~ $ serf agent -bind= -join
pi@raspberry-1:~ $ serf members
raspberrypi  alive
raspberrypi  alive
raspberrypi  alive

AWESOME: While a node keep alive, you can add as nodes as you want.

3- Expoxing services through Serf and Cloudy

Thanks to Cloudy and using avahi-ps script I can publish or unpublish service through Serf:

pi@raspberrypi:~ $ avahi-ps
avahi-ps (Avahi Publish and Search) is a system to publish local services and
discover remote ones using Avahi and other available modules plugged-in.

Usage: /usr/sbin/avahi-ps publish|unpublish|search|info <options>


 - Publishing a local service to the network:
   /usr/sbin/avahi-ps publish <description> <type> <port> [txt]
      <description>: a short text describing the service
      <type>: service type
      <port>: service port
      <txt>: additional information, formatted as

 - Unpublishing a local service to the network
   /usr/sbin/avahi-ps unpublish [type] [port]

 - Searching for services on the network:
   /usr/sbin/avahi-ps search [type] [hostname]

 - Showing available information:
   /usr/sbin/avahi-ps info <variable>
       <variable>: ip|cloud|tincdev|communitydev

This script is calling to avahi-ps-serf adding, searching and deleting tags, it's how Cloudy exposes and propagate services to other nodes.

  • I'm going to publish a new service called TEST:
pi@raspberry-1:/etc/init.d $ /usr/sbin/avahi-ps publish TEST TEST TEST TEST
Successfully updated agent tags
  • Cluster gets the new event:
2019/03/10 11:13:22 [INFO] serf: EventMemberUpdate: raspberry-1
2019/03/10 11:13:23 [INFO] agent: Received event: member-update
  • And now the command serf members looks like:
pi@raspberry-1:/etc/init.d $ serf members
raspberry-2  alive  services=QlpoOTFBWSZTWfn5OQ0AABtfgAAQEAcTEAABTQq/p98qIABBEaTNTRoADT1GgxDGExNBgjEMjCZc1Bt4MgWb/IGXhWoBMhGpCJZOxzBYAGrzVDafCo5vimkNvb+qPpelFkCc0O1dTFl4tMWJnkyU1/i7kinChIfPycho
raspberry-1  alive  services=QlpoOTFBWSZTWWfzP3wAAEdfgAAQEAd3cAIBTQq/p98qIACSCVU2h6kwATAQbII9T0EoVNGmT0jIaNqabQE0MU807XzNcXs4kI0gZ4GWa4RLKRRoTiCmgw0rlBNdT0eSoU6Dx48UJCs4FZuYYUYRHBC6AMWCdjhdrHxp6GNHu4fPpgXEB+P54iaIbxE0ZyPmw5QhUKIxahHnFqGG7kOhdyRThQkGfzP3wA==
raspberrypi  alive  services=QlpoOTFBWSZTWYyBIrAAACDfgAAQEAU3cAABTQq/p98qIAB0KmamNQAaA00NGmj1CE1DTTTIDTQD1BoCxgGvU1qSGcNuDVCWkQR6RLEbmWzg5wpel4RESCEcNtwe0nBHN0TiZsGXyr89gMVvEZjdByRAu5E6UKOTFfEn8XckU4UJCMgSKwA=
  • The tag is encoded in base64, I can see what is happening with:
echo "QlpoOTFBWSZTWRYvUqQAAEdfgAAQEAd3cAIBTQq/p98qIACSCVRoeoCYmTAmRtEw1PQShUyaY1DTQNqaPUzSYmmnXgnO/e1xezicmSBlE+ZLGRaCSZCoQU/DDOpQTXU8HcsFOI8ePFCctNpabGGFGERwQugEVgjhuuvV4YZmrB2IPvJcWD50fz1CwQ/Qk0ZwPGw1QhSKIxahHWlaFzd0OxdyRThQkBYvUqQ="|base64 -d - |bunzip2 -
  • Or easier than before, I can check services exposed from Cloudy:


  • I want to comment that you can expose services from Cloudy console but it is really limited.


At this point, I can say that Cloudy and Serf works very well together. With Serf we have a decentralized cluster membership, added failure detection and orchestration. Cloudy is a little wrapper who is making easier our life.

On the other hand, currently Cloudy doesn't have a huge list of services, so you should use the console in order to add more services to your microcloud or your community cloud.

You can’t perform that action at this time.