Home

Awesome

bootstrap

The bootstrap application is a simple, yet poweful application to bootstrap an Erlang cluster without having to know the exact nodenames or hostnames in advance. It automates the process of dynamically populating the cluster with new nodes. There's also a Java implementation of the bootstrap protocol based on Jinterface which adds bootstrap support to Java nodes.

Features

How it works

The node discovery process is based on a simple, distributed P2P protocol defining two PDUs, the bootstrap PING and PONG messages. As mentioned earlier, these messages are distributed via either UDP broadcast or multicast. All nodes in the cluster must run the same protocol. See below for the representation of the messages.

%% PING:
term_to_binary({bootstrap, {ping, PingNode :: node(), PingAddr :: inet:ip4_address()}}).

%% PONG:
term_to_binary({bootstrap, {pong, PongNode :: node(), PingNode :: node()}}).

It's well known that broadcast as well as multicast can load a network pretty heavy. Therefore, the bootstrap application takes measures to reduce the network traffic to a minimum using strategies known from P2P overlay protocols designed for the use in mobile Ad-hoc networks (which are very sensitive to extensive medium usage).

Most of the ideas behind the bootstrap protocol are inspired by the Local Broadcast Cluster concept described in [1]. PING and PONG messages are distributed as broadcast/multicast. This makes it possible to have only one active instance of the protocol at a time. To ensure this, the bootstrap protocol will detect and solve PING collisions. Furthermore, it will use information from PONG messages to make distributed decisions whether to ping or not to ping. All traffic will be stopped as soon as all nodes in the cluster meet their connectivity needs.

TODO make more detailed description (e.g. with figures)

Configuration

The bootstrap application already comes with sensible defaults (except for the regex used to decide whether to connect to a certain node or not). However, many things can be customized if desired. For this purpose the following configuration options are available and can be configured in the application environment:

The default configuration can be used to form an unbounded, mesh-connected Erlang cluster utilizing the UDP broadcast protocol. Please note that to be able to connect to other Erlang nodes, these nodes must have the same Erlang cookie configured.

Notifications

If you use bootstrap to automatically establish connections between nodes, configuring and starting the application on all nodes is basically all you need. However, some use cases may make it necessary to get notified whenever a matching connection is established or lost.

For this purpose the bootstrap application provides the monitor_nodes/1 function that manages bootstrap handler registrations (for the calling process). Bootstrap handlers will get initial notifications for all matching nodes that are currently connected.

The net_kernel module also allows registration of processes for node up/down messages. However, there are some major advantages when using the bootstrap notification system:

The bootstrap application defines two messages that are sent to handlers using ordinary Erlang messaging (corresponding defines can be found in the bootstrap.hrl header file):

The example directory contains a simple example of a gen_server subscribing for bootstrap notifications. For more information, please refer to the edoc of the bootstrap module.

Security

The bootstrap application is insecure. This means everyone with access to the used broadcast/multicast domain can send, receive and read bootstrap packets. However, to be able to connect to any of the gathered nodenames an attacker must know the used Erlang cookie. The bootstrap application will never transmit cookies over the wire in any form.

Examples

This section gives some configuration examples along with respective resulting topologies. A small note to the used figures:

Mesh Topology

This is the basic setup you get when connecting to other nodes. Every node is connected with every other node in the cluster. The view for bootstrap handlers does not differ from the net_kernel view:

<img src="https://cloud.githubusercontent.com/assets/404313/4612211/6bcf65ee-52c4-11e4-9f73-943de74796f6.png" alt="Mesh Topology with visible connections." />

The sys.config configuration to build a topology like this would look like the following:

%% on all nodes:
[{bootstrap, [{connect_regex, ".*"}, {min_connections, 1}]}].

Star Topology

This example shows the difference between visible and hidden connections. While visible connections (default Erlang) always build a mesh connected cluster (from the net_kernel view), hidden connections allow building custom cluster topologies. However, global name registration cannot be used in this case!

The left figure shows the visible connection example. In this case the bootstrap filters connection notifications according to the configured connect_regex. This means when connecting the cluster bootstrap handlers will only get notifications for the nodes part of the bootstrap view of the cluster (top of the figure), although other connections may be established automatically by the kernel application.

The right figure shows the star topology forced to the net_kernel using hidden node connections that may not be used by the kernel to connect to other nodes automatically.

<img src="https://cloud.githubusercontent.com/assets/404313/4612210/6bcdb30c-52c4-11e4-9295-53110a29e9b9.png" alt="Star Topology with visible and hidden connections." />

The sys.config configuration to build a topology as shown in the left example would look like the following:

%% master node:
[{bootstrap, [{connect_regex, "slave@.*"},  {min_connections, 1}]}].

%% slave node:
[{bootstrap, [{connect_regex, "master@.*"}, {min_connections, 1}]}].

The sys.config configuration to build a topology as shown in the right example would look like the following:

%% master node:
[{bootstrap, [{connect_regex, "slave@.*"},  {connect_mode, hidden}, {min_connections, 1}]}].

%% slave node:
[{bootstrap, [{connect_regex, "master@.*"}, {connect_mode, hidden}, {min_connections, 1}]}].

Tree Topology

This is a more complex example using hidden connections. The configurations not only differ from level to level, beginning at level two, a node must additionally decide to which branch of the tree it wants to connect. As can be seen in the configurations below, level one nodes use a combined regular expression to match root and level2 nodes. A regular expression matching only root nodes would be sufficient to connect the tree, however, in this case level one nodes would not get notifications about connected level two nodes.

<img src="https://cloud.githubusercontent.com/assets/404313/4612212/6bd808ca-52c4-11e4-8ceb-02cefbf6cd5e.png" alt="Tree Topology with hidden connections." />

The sys.config configuration to build a topology like this would look like the following:

%% root node:
[{bootstrap, [{connect_regex, "level1.*"}, {connect_mode, hidden}, {min_connections, 1}]}].

%% level1 nodes:
[{bootstrap, [{connect_regex, "(root|level2)@.*"}, {connect_mode, hidden}, {min_connections, 2}]}].

%% level2 nodes (depending on which part of the tree a node should connect to):
[{bootstrap, [{connect_regex, "level1a@.*"}, {connect_mode, hidden}, {min_connections, 1}]}].
%% or
[{bootstrap, [{connect_regex, "level1b@.*"}, {connect_mode, hidden}, {min_connections, 1}]}].

History

Master

No changes

Version 1.1.0

Version 1.0.0

Version 0.0.2

Version 0.0.1

References

[1] Basissoftware für drahtlose Ad-hoc- und Sensornetze, P. Baumung and M. Zitterbart, 2009 Universitätsverlag Karlsruhe