Intro
In my previous post, we covered setting up a fresh EOS node step by step, and hooking it into a testnet. It's a great way to learn what's involved by setting up a server from scratch, but what if you want to experiment with several machines, deploy different configurations or run multiple testnets? Manual setup of multiple servers can become cumbersome and difficult to manage, and its inherently difficult to document.
Configuration Management
Thankfully there are some great tools out there to document and automate server configuration. Personally, i've had great experience with Ansible because it has some strong benefits:
- It's open source
- It doesn't require any software to be installed on the target machines
- Uses SSH for server communication
- Low barrier to entry, simple syntax
Example
Let's say we wanted to setup a simple EOS producing node on a remote server, create a relevant configuration, and automatically hook it into the Jungle testnet.
Inventory
With Ansible its possible to work with multiple servers, you can group them to perform actions across a range of related machines at the same time and if you work in the cloud its possible to have dynamic configurations.
For this example, lets just setup a single server hosted in Digital Ocean:
[digitalocean]
165.227.238.243
Tasks
Now that we can connect to a server, we want to define the tasks we want to complete. Ansible has various modules pre-baked into the application that allow you to dive in without having to write any boilerplate. It's also possible to just execute raw shell commands by specifying the shell
module:
- name: clone repo eos
shell: git clone https://github.com/eosio/eos --recursive /opt/eos
Variables
To ensure we don't duplicate configurations, Ansible allows you to define variables. So you could use different credentials based on whether you are deploying to staging vs production, or it can pick up command line parameters passed at runtime. For the EOS project, the git tag is updated frequently, so this is something that could be captured into a variable, allowing us to easily deploy newer versions without a change being made to the generic task:
- git:
repo: 'https://github.com/EOSIO/eos.git'
dest: /opt/eos
version: {{ version }}
Interactive response
As you probably know, when building the EOS project it asks you whether you want to install missing dependencies. This can be problematic for some automation tools, but thankfully Ansible has an expect
module for this. You simply pass the regex to match the prompt you want to answer:
- name: exec eosio_build.sh
expect:
chdir: /opt/eos
command: /bin/bash /opt/eos/eosio_build.sh
responses:
\?: 1
Playbooks
Now we have a bunch of tasks, we can use a playbook to execute them in order on the targeted host. Within a playbook we can also define some of the global variables that we want to apply in the execution:
- hosts: digitalocean
roles:
- requirements
- deploy
- testnet
vars:
producer_name: blockmatrix
p2p_address: bm-testnet.blockmatrix.network
version: DAWN-2018-04-27-ALPHA
The Code
It's one thing reading about it, but it's way more fun running it for yourself! I have whipped this up into a simple git repo so you can try it out, i tried to be as verbose as possible in the code and stay away from some of the more complex module commands so that it's easier to follow for newcomers to Ansible.
Github: https://github.com/BlockMatrixNetwork/eos-testnet
Moving Forward
For our initial production Block Producer setup, we are using Ansible to help in various way, some examples:
- Provisioning producer and full nodes
- Running frequent
cleos
commands - Performing system and application updates
- Assisting with disaster recovery
It's a great tool that offers a lot of flexibility, but configuration management is a fast moving space! There's already new kids on the block in the "infrastructure-as-code" realm such as Terraform, however they aren't necessarily mutually exclusive - it's important to trial these tools to find the best mix for your workflow.