Now that data center are software driven, it is crucial to have a single source of truth, a kind of know all inventory about your resources, your nodes, their functions and their associated parameters, which describe everything and store it in a single location. Welcome reclass which use Class inheritance to define nodes roles and avoid duplication by gathering all important datacenter parameters in a central location. All of this will then be used by your automation tools like Salt, Ansible or Puppet to bootstrap your infrastructure as a software. In other words, reclass can be classified as a hierarchical inventory management solution. Let see how we could use it with Salt.
reclass is an open source software released by Martin F. Krafft under the Artistic License 2.0. It can be categorized as an External Node Classifier and it provides information about your nodes, such as variables and the application they should be running. reclass has the ability to merge data sources hierarchically, it allow us to say, this node has this behaviour, or this node has a certain number of classes and these parameters.
Configuration Management System use the following Data:
- What application should a role have ?
- How does this node differ from all other nodes that have the same application (parameters) ?
- Which nodes belong to a group (nodegroup, clusters) ?
reclass help to organize and store all of this without having to rely on any specific configuration management features but plug into them and provide the data they need to let them provision your infrastructure.
Installation
reclass is packaged for Debian/Ubuntu, so the installation is as simple as
apt-get install reclass reclass-doc
But it could also be installed from source on other operating systems.
Configuration
reclass configure is stored in ~/reclass-config.yml
, the main thing you have to configure is the inventory directory
inventory_base_uri: /srv/salt/reclass
If not specified reclass will look for nodes and classes directories into /etc/reclass/
but when running reclass command line, you can also use the following argument instead -b inventory_base_uri
.
Concepts
The main reclass concept are
- node - usually a server in your infrastructure
- class - A category, tag, feature, or role that applies to a node. Classes may be nested, form a class hierarchy
- application - behaviour to apply to a node
- parameter - Node-specific variables, with inheritance throughout the class hierarchy
When asked for information, reclass will parse the class or node definition and recurses to his parent before anything else and then merge everything. Because the merging happens late in the process, a node or any class may override any of the data defined by its ancestors.
data structure
By default, reclass store all the required information in YAML files by leveraging its yaml_fs storage backend. But the storage backend is pluggable. Remote FS is another example of a different backend contributed by Michael Kutý.
keywords
reclass YAML files contains the following keywords that implement the above concepts
- classes - a list of parent class (e.g. web_server, debian_server).
- applications - list of applications to append to applications defined in ancestors, ~remove this application from the list (e.g. nginx, ssh_client).
- parameters - key-value pairs which set defaults in class definitions (e.g. ipaddr = 192.0.2.1, nginx_port = 8080).
- environment - only relevant for nodes, this allows to specify an “environment” into which the node definition is supposed to be place (e.g. production, staging, devel).
directories structure
reclass store all of its files in two directories below the inventory root
- /srv/salt/reclass/nodes - node definition
- /srv/salt/reclass/classes - classes definition
inheritance
Nodes and classes files may specify classes to inherit. To give you an example, let me rewrite the etcd cluster example I used in my previous article about Salt formulas. Instead of relying on Pillar and Top files, lets create classes and nodes YAML file to describe our cluster.
A etcd node declaration looks like that
nodes/saltstack-m01.yml
#!yaml
environment: base
classes:
- common
- etcd-cluster
parameters:
hostname: saltstack-m01
ip_address: 172.16.52.101
Create the same for both saltstack-m02, saltstack-m03 nodes with updated IP and hostname.
classes/common.yml
#!yaml
applications:
- hostfile
- tools
parameters:
linux:
system:
name: ${hostname}
In the classe above I declare that the nodes that inherit from it will have 2 applications and one parameters available to them.
classes/etcd-cluster.yml
#!yaml
applications:
- etcd
parameters:
etcd:
server:
enabled: true
bind:
host: ${ip_address}
token: $(uuidgen)
members:
- host: 172.16.52.101
name: saltstack-m01
port: 4001
- host: 172.16.52.102
name: saltstack-m02
port: 4001
- host: 172.16.52.103
name: saltstack-m03
port: 4001
Parameters can also be overwritten, the last evaluated classe can redefine any previously defined ones.
namespaces
reclass files are stored in directories that can reflect namespaces for classes. For example, a class named ssh.server will be read from ssh/server.yaml, if you specify only ssh, the lookup will happen for ssh/init.yaml or ssh.yml, but only one of the two can exist.
parameter interpolation
In our class definition above, ${ip_address}
will be interpolated at merging time from the information available in the node declaration.
Merging
Before running the above example, one more thing, keep in mind that:
- List are append only
- Dictionaries are merged deeply
- Only scalars are replaced, the one which stay is the one which comes the last.
Lets now run our example with
#!yaml
$ reclass -n saltstack-m01
__reclass__:
environment: base
name: saltstack-m01
node: ./saltstack-m01
timestamp: Thu Oct 6 14:48:20 2016
uri: yaml_fs:///srv/salt/reclass/nodes/./saltstack-m01.yml
applications:
- hostfile
- tools
- etcd
classes:
- common
- etcd-cluster
environment: base
parameters:
etcd:
server:
bind:
host: 172.16.52.101
enabled: true
members:
- host: 172.16.52.101
name: saltstack-m01
port: 4001
- host: 172.16.52.102
name: saltstack-m02
port: 4001
- host: 172.16.52.103
name: saltstack-m03
port: 4001
token: $(uuidgen)
hostname: saltstack-m01
ip_address: 172.16.52.101
linux:
system:
name: saltstack-m01
As you can confirm above, ip_address and hostname parameters have been interpolated.
To get the overall inventory use
$ reclass -i
You can also look at a provided inventory exemple
$ reclass -b /usr/share/doc/reclass/examples/ --inventory
salt adapters
reclass Adapters interface between configuration management system and reclass. Such an adapter exist for Salt, this adapter has been integrated to Salt as a module since release 0.16.0. The module provides top and Pillar data. On a Debian system installed from packages, you’ll find both adapters at the following location
/usr/lib/python2.7/dist-packages/salt/tops/reclass_adapter.py
/usr/lib/python2.7/dist-packages/salt/pillar/reclass_adapter.py
.
You can check the exact location on your debian master with
dpkg -S reclass_adapter.py
By using these two bundled reclass adapters, Salt can retrieve Salt States for each host by querying Reclass applications instead of a top.sls file. Salt can also retrieve Pillar data from reclass parameters.
So here is a corresponding map between reclass concepts and Salt ones
- reclass nodes -> salt minion
- reclass applications -> Salt States
- reclass parameters -> Salt Pillars
- environment -> environment
Installation
To ease the troubleshooting you can create a symlink to use a python module in charge of converting reclass data to salt data structure
ln -s /usr/lib/python2.7/dist-packages/reclass/adapters/salt.py /usr/local/sbin/salt-reclass
chmod +x /usr/lib/python2.7/dist-packages/reclass/adapters/salt.py
Let’s try it
$ salt-reclass --top
base:
saltstack-m01:
- hostfile
- tools
- etcd
saltstack-m02:
- hostfile
- tools
- etcd
saltstack-m03:
- hostfile
- tools
- etcd
And to get Pillar data
$ salt-reclass --pillar saltstack-m01
__reclass__:
applications:
- hostfile
- tools
- etcd
classes:
- common
- etcd-cluster
environment: base
nodename: saltstack-m01
etcd:
server:
bind:
host: 172.16.52.101
enabled: true
members:
- host: 172.16.52.101
name: saltstack-m01
port: 4001
- host: 172.16.52.102
name: saltstack-m02
port: 4001
- host: 172.16.52.103
name: saltstack-m03
port: 4001
token: $(uuidgen)
hostname: saltstack-m01
ip_address: 172.16.52.101
linux:
system:
name: saltstack-m01
The output looks pretty much the same as the one obtained from reclass cli but the parameters are in the beginning now, this is what expect Salt and the adapter makes sure everything looks good to salt by massaging data.
Configure your Salt Master to use reclass
To tell your Salt Master to use reclass as its external inventory, add the following line in its configuration file
$ vi /etc/salt/master
reclass: &reclass
storage_type: yaml_fs
inventory_base_uri: /srv/salt/reclass
ext_pillar:
- reclass: *reclass
master_tops:
reclass: *reclass
Restart your salt-master
service salt-master restart
You also need to make sure that you don’t have any more top.sls file in your Salt root directory. Also make sure you comment out the pillar_roots section in the master configuration file.
You should be able to see reclass information from salt
$ salt \*m01 state.show_top
saltstack-m01:
----------
base:
- hostfile
- tools
- etcd
$ salt \*m01 pillar.items
saltstack-m01:
[...]
etcd:
----------
server:
----------
bind:
----------
host:
172.16.52.101
enabled:
True
members:
|_
----------
host:
172.16.52.101
name:
saltstack-m01
port:
4001
|_
----------
host:
172.16.52.102
name:
saltstack-m02
port:
4001
|_
----------
host:
172.16.52.103
name:
saltstack-m03
port:
4001
token:
$(uuidgen)
hostname:
saltstack-m01
ip_address:
172.16.52.101
linux:
----------
system:
----------
name:
saltstack-m01
Congrat, you’ve connected reclass and Salt !!!
Apply the state
The last step is now to apply the states inherited from reclass applications to our minion, it’s just a standard salt state.apply command
salt \*m0* state.apply
[...]
------------
Succeeded: 6
Failed: 0
------------
Total states run: 6
Total run time: 30.248 s
You should now have a working etcd cluster.
Conclusion
Parametrisation of your infrastructure is key, if you can extract the difference between your nodes and store it within reclass, it will help when you’ll have to change servers, reinstall your application on a new infrastructure, etc…
reclass just assemble and provide the data, it doesn’t do any modification on your hosts which aren’t even aware of its existence. It is actually just on abstraction layer on top of other configuration management systems. It is a single data source that can be used with multiple systems. So you can easily switch from one technology to another, from Puppet to Salt, all your data stays within reclass. You can also use the same data with multiple systems at the same time.
reclass was originally written for Puppet and is pretty much similar to Hiera a key/value lookup tool for configuration data. But it was rewritten from scratch in 2013, so now there isn’t any adapter for it but you can easily use it with Salt (adapter module) or Ansible (script).
Links
Video
- Recursive inventory management presentation from Martin F. Krafft the creator of reclass.
- Hierarchical infrastructure description for your system management needs presentation - pretty similar to the previous one.
Documentation
- reclass documentation
- reclass manpage
- Salt Pillar reclass adapter