Salt support in Apache Brooklyn

Apache Brooklyn has had support for some time for provisioning machines using Chef, but a new feature in the upcoming 0.9.0 release adds the ability to use Salt from SaltStack. This means you can integrate existing deployment specifications that use Salt into an Apache Brooklyn managed operation.

Salt is a new generation orchestration and configuration management system. Much like Puppet and Chef, Salt is designed to work in a master/agent topology , called ‘master/minion’, including a ‘masterless’ mode, but also an ‘agentless’ topology’ similar to its competitor Ansible. In the former, a master server acts as a manager for a number of client nodes, called ‘minions’.  A Salt daemon minion connects back to the master server for its operation, and Salt manages the software on the minion according to a specification of ‘states’ defined in Salt configuration files. In the ‘masterless’ mode the minion has all the information needed locally, allowing it to run locally, without having to hit the master. In the ‘masterless’ mode there is no need for a master, Salt on the minion operates based on the local files on the minion node.  The new Salt support in Apache Brooklyn uses this mode of operation. Brooklyn manages the remote nodes by running ‘agentless’ Salt commands over an ssh connection.

The Brooklyn community is planning to add support for this ‘agentless’ mode soon, as well as support for Ansible, which operates in a similar fashion. One thing worth noting is that Salt is (Apache) licensed, like Puppet and Chef, whereas Ansible, also a popular choice is GPLv3 licensed.

Some Salt Terminology

A ‘State’ in Salt is a specification of a configuration of some aspect of a system, such as what packages are installed, what system services are running, what files exist, etc.  Such states are described in “SLS” files (for SaLt State file). These files are typically written as templates using the Jinja templating engine.  The actual SLS files for the minion are then created by processing the templates using configuration data provided via Salt’s “Pillar” system.

Salt comes with built-in support for many software systems, and has a repository of pre-written Salt states known as ‘formulas‘ on GitHub.

How Brooklyn interacts with Salt

Apache Brooklyn now provides a Salt entity type. An entity of this type can be specified in a blueprint in order to provision the node through Salt. The Salt entity will download Salt and install it on the node. The entity type supports the configuration of Salt formulas and Pillar data to download, and the configuration of what Salt states to apply.  These are managed using Salt in ‘masterless’ mode, as described in the SaltStack quickstart guide, using the ‘salt-call’ command available from  Salt.  Having installed Salt, the Salt entity will now use it to apply the Salt states specified in the blueprint, thereby installing and configuring whatever the states define.

Once the entity is up and running, the Salt ‘highstate’ (the collection of states applied to the system) is exposed as a sensor on the entity.  An effector  is provided on the entity that supports ad-hoc Salt operations.

Using Salt in blueprints

To write a blueprint to use Salt with Brooklyn it will help to have a degree of familiarity with Salt itself. In the sections below, when the Brooklyn configuration is described, the underlying Salt operation is also noted briefly, for clarity for readers who already know Salt.

To manage a node with Salt, create a blueprint containing a service of type org.apache.brooklyn.entity.cm.salt.SaltEntity and define the ‘formulas’ and ‘start_states’ configuration values.

For example:

name: Salt Example setting up Apache httpd
location: my-cloud
services:
- id: httpd-from-salt
  type: org.apache.brooklyn.entity.cm.salt.SaltEntity
  formulas:
  - https://github.com/saltstack-formulas/apache-formula/archive/master.tar.gz
  start_states:
  - apache

This example specifies that Brooklyn should use Salt to download the `apache-formula` from the Saltstack repository on Github. The apache formula contains the Apache web server with a simple “it worked” style index page. To start the entity, Brooklyn will use Salt to apply the `apache` state, which will bring up the web server.

A typical usage of the Salt entity might be to include a formula from the Saltstack repository, such as `apache` above, and another formula created by the blueprint author, with additional states, such as website content for the apache server.

A typical Salt deployment will include both states (provided via Salt formulas) and configuration data, provided through  Salt’s “Pillar” component.  Brooklyn provides configuration keys for the Salt entity to specify where to get the Pillar configuration data.  For example:

name: Salt Example setting up MySQL with a Pillar
location: my-cloud
services:
- id: mysql-from-salt-with-my-pillar
  type: org.apache.brooklyn.entity.cm.salt.SaltEntity
  formulas:
  - https://github.com/saltstack-formulas/mysql-formula/archive/master.tar.gz
  - http://myhost:8080/my-mysql-formula.tar.gz
  start_states:
  - mysql
  stop_states: 
  - mysql.disabled
  pillars: 
  - mysql
  pillarUrls:
  - http://myhost:8080/my-mysql-pillar.tar.gz

This blueprint contains the MySQL database, and includes a formula available from `myhost` which includes the schema information for the DB. The MySQL formula from Saltstack has extensive configurability through Salt Pillars. In the blueprint above, Brooklyn is instructed to apply the pillars defined in the `pillars` configuration key.  (This will add these values to the Salt Pillars `top.sls` file.)  The pillar data must be downloaded; for this, the `pillarUrls` key provides the address of an archive containing the Pillar data.  The contents of the archive will be extracted and put in the `/srv/pillar` directory on the minion, in order to be available to Salt when applying the pillar. For example, the archive above can simply have the structure:

pillar
├── mysql
│ └── init.sls

The init.sls contains the pillar configuration values, such as:

# Manage databases
    database:
      - orders
    schema:
      orders:
        load: True
        source: salt://mysql/files/orders.schema

Meanwhile the `my-mysql-formula.tar.gz` formula archive contains the schema:

my-mysql-formula
├── mysql
│ └── files
│ └── orders.schema

Note that the blueprint above defines an `id` for the Salt entity.  This id, if provided, is set as the minion id in the Salt configuration file.  This is useful particularly for Pillar configuration, as, if there are more than one Salt managed nodes in the application, they can share a common Pillar file, with appropriate subdivisions of pillar data based on minion id.

Highstate Sensors

The Salt entity exposes the Salt “highstate” on the node via Brooklyn sensors.  Firstly a single sensor ‘salt.states’ contains a list of all the top level Salt state ID declarations in the highstate.  For example, for the mysql case above, this might look like:

["mysql_additional_config", 
    "mysql_config", 
    "mysql_db_0", 
    "mysql_db_0_load", 
    "mysql_db_0_schema", 
    "mysql_debconf",
    "mysql_debconf_utils", 
    "mysql_python", 
    "mysql_user_frank_localhost", 
    "mysql_user_frank_localhost_0", 
    "mysql_user_nopassuser_localhost", 
    "mysqld"
   ]

Then, for each ID and each Salt state function in that ID, a Brooklyn sensor is created, containing a map of the data from the highstate.  For example, the `salt.state.mysqld.service.running` sensor might have a value like:

Ad-hoc commands: The Saltcall Effector

The Salt entity includes a general purpose Salt effector, ‘saltCall’, which permits execution of Salt commands via ‘salt-call –local’.  It contains a single parameter, ‘spec’, which specifies the command to invoke.  For example,  invoking the effector with a ‘spec’ value of ‘network.interfaces –out=yaml’ would return a YAML formatted map of the network interfaces on the minion.

Conclusion

Adding support for Salt integration will ease the process of adopting Apache Brooklyn for projects that already use Salt to manage their deployments, so making it easier to take advantage of Apache Brooklyn’s capabilities.  To wrap up, here is a video of one deployment with Brooklyn’s Salt support:

To learn more about Brooklyn and what you can do with it, see the documentation at brooklyn.apache.org.  

If you have questions you can ask on the mailing list at dev@brooklyn.apache.org, or join the IRC chat at #brooklyncentral on Freenode.