This packages Erlang/OTP for 18.3 the development environment for building distributed real-time high-availability systems.
The patches within the patches/
sub-directory is primarily to get
ssl working, although in future it'll host some optimizations as
discussed in Unoptimized Memory Allocation subsection.
github: neeraj9, igalic
The Erlang build is tested (though limited) with both openssl and libressl. Needless to say the official Erlang document does not mention libressl, although from a cursory look at the api of both it appears compatible and safe to be used with Erlang. The default setting in the rumprun-packages is libressl and in case you want to change then edit ../config.mk and set RUMPRUN_SSL to openssl.
Run this make
from a user account, not the root account. At the end of the
installation, the Makefile will build two variants of the build. One is
required for a host, so that the erlang code can be compiled on this
host (.erl) to .beam. There is another one which can be baked for rumprun
kernel.
The build script requires genisoimage
to create erlang.iso
image.
Run make
from the erlang package directory:
cd rumprun-packages/erlang
make
There are sample erlang applications (echoserver and helloworld) which can
be built via the make examples
. The details of the build are captured in
the Makefile.
make examples
Next you'll need a baked image which can be run on qemu (or kvm or xen).
The following build command will generate an image for non-smp, while using
hw
as the platform.
rumprun-bake hw_virtio beam.hw.bin bin/beam
The above can be either used in qemu or kvm. In case you want to use xen then the following commands can be used towards the same.
Note that the build commands in turn use rumprun-bake internally, so be sure that you have built the appropriate platform for it to work. Additionally rumprun-bake with xen_pv is used in the Makefile.
rumprun-bake xen_pv bin/beam.xen_pv.bin bin/beam
Now you've got a baked unikernel image.
Setup the networking as follows (if not done already). You can also use our
network.sh
script:
$ sudo ./network.sh
You are now ready to run your first erlang unikernel. To run the rumpkernel
using qemu, erlrun.sh
:
$ ./erlrun.sh --virt=kvm
Please peruse the top part of the shell-script for further options.
You should see Echo server started
text printed to your screen.
Now you can connect to the server via telnet as shown below:
$ telnet 10.0.120.101 8080
Trying 10.0.120.101...
Connected to 10.0.120.101.
Escape character is '^]'.
GET /
GET /
hello there!
hello there!
^]
telnet> quit
Connection closed.
You should replace qemu
with kvm
to run under kvm. For xen there will be
equivalent variation and additionally use xen baked unikernel as well.
You can do clustering by using an alternative form of the rumprun command.
Notice that when passing --epmd
, "-no_epmd" is removed and few more arguments
are added ("-s erlpmd_ctl start -s setnodename start ${name}@${ip} ${cookie}".
n.b.: Because erlang is operating in rumprun, a restricted environment,
we cannot simply pass -name ${name}@${ip} -setcookie ${cookie}
in our
erlrun.sh
script, and have to resort to using the simple wrapper module
example/setnodename
.
It is important to note the name (--name
) given along with the ip address
(--ip
). The ip address must be the same as given to the guest vm otherwise
things will not work. Additionally, the --cookie
and --name
are important
as well, as you can see the workflow to connect to this new node (running in
rumprun unikernel).
$ ./erlrun.sh --epmd --cookie=mycookie
Please peruse the top part of the shell-script for further options.
The node "[email protected]" is now ready, which also runs the echo server. The following sequence of steps demonstrate it's workability. Note that while building the target, a local copy of erlang is also built which can be used for testing on the host. Having said that you can always install erlang on your host and use it as well (in fact that is better because then your ctrl-keys and other completion will work which are disabled in local copy).
Assuming you are in rumprun-packages/erlang subdirectory.
Start the erlang shell.
./build/bin/erl
Eshell V7.3.1 (abort with ^G)
1>
And start a local epmd, so that you can talk to the remote (rumprun) node.
erlpmd_ctl:start().
You would see the following traces indicating that epmd started successfully.
=INFO REPORT==== 4-Sep-2015::09:21:10 ===
ErlPMD: started.
=WARNING REPORT==== 4-Sep-2015::09:21:10 ===
ErlPMD: info: notify_init while {argv,[{0,0,0,0}],4369,false,false,0,0,0}.
=INFO REPORT==== 4-Sep-2015::09:21:10 ===
ErlPMD listener: started at Ip: 0.0.0.0:4369
Now connect to the local instance of epmd while setting name and cookie, which is required for authentication with the remote rumprun erlang node. Notice that the cookie used is the same here as well.
The local ip address is 10.0.120.100, which is as per the initial configuration when the tap0 interface was created. In case your configuration is different then use that ip address instead.
net_kernel:start(['[email protected]', longnames]).
true = erlang:set_cookie(node(), mycookie).
You will see some more traces.
=INFO REPORT==== 4-Sep-2015::09:21:21 ===
ErlPMD: alive request from 127.0.0.1:18262 PortNo: 9156, NodeType: 77, Proto: 0, HiVer: 5, LoVer: 5, NodeName: 'linux', Extra: <<>>, Creation: 2.
{ok,<0.40.0>}
Or, alternatively, use your own erlang installation and its convenient erl
options:
$ erl -setcookie mycookie -name [email protected]
Starlng/OTP 18 [erts-7.1] [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false]
Eshell V7.1 (abort with ^G)
([email protected])1>
The node is now ready to talk to the remote rumprun erlang node. The following sequence of steps demonstrate the connection, where the rpc:multicall() is used to run commands on nodes, while local commands are run directly. Additionally, the first command ping, is needless to say very important and must return "pong" as the reply otherwise there is an issue in the connection/configuration. Also notice that the erlang shell prompt is different now indicating distribution mode.
([email protected])5> net_adm:ping('[email protected]').
pong
([email protected])6> inet:gethostname().
{ok,"linuxhost"}
([email protected])7> rpc:multicall(['[email protected]'], inet, gethostname, []).
{[{ok,"rumprun"}],[]}
([email protected])8> erlang:system_info(system_architecture).
"x86_64-unknown-linux-gnu"
([email protected])9> rpc:multicall(['[email protected]'], erlang, system_info, [system_architecture]).
{["x86_64-rumprun-netbsd"],[]}
([email protected])10> erlang:memory().
[{total,29547272},
{processes,3967984},
{processes_used,3967984},
{system,25579288},
{atom,202481},
{atom_used,188308},
{binary,30744},
{code,4690909},
{ets,292808}]
([email protected])11> rpc:multicall(['[email protected]'], erlang, memory, []).
{[[{total,10866312},
{processes,4211520},
{processes_used,4211520},
{system,6654792},
{atom,194289},
{atom_used,161956},
{binary,33528},
{code,3908903},
{ets,249320}]],
[]}
Now you can quit the shell as follows, unless you'd like to play more.
q().
You can start multiple Erlang-rumprun unikernels and play if you like.
There are tons of things that you could do, but then this is just a small demonstration to show that distributed erlang cluster will work on rumprun unikernel now.
In case you want to change the /opt/erlang path then you'll have to change the Makefile, erl_inetrc and all the manual instructions mentioned in this document.
At present the erlang configuration inet configuration is tuned to use file and DNS as a source of resolving ip/host, though untested.
The generated erlang iso is huge (~152MB), which can easily be cut down and is planned as well in the spirit of rumprun unikernel.
At present there is an unoptimal allocation of memory as a consequence of erlang alloc interacting with rumprun. This will be fixed in the near future, but something to be aware of in case you care. The exact amount of memory wasted is not quantified, because it needs to be fixed anyways.
SMP binary though available is useless, since rumprun doesn't support it.
The rumpkernel supports SMP, but since rumprun won't support in the forceable future, so it wont't work.