blob: 63cd284eacd59c00bb4b04332dbceec60584b35d [file] [log] [blame]
martin f. krafft5ee69b32013-06-24 13:41:06 +02001=============================================================
2 reclass recursive external node classification
3=============================================================
4reclass is © 20072013 martin f. krafft <madduck@madduck.net>
5and available under the terms of the Artistic Licence 2.0
6'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
7
8Please make sure to read the generic information in the README file first, or
9alongside this document.
10
11Quick start with Ansible
12~~~~~~~~~~~~~~~~~~~~~~~~
13The following steps should get you up and running quickly. Generally, we will
14be working in /etc/ansible. However, if you are using a source-code checkout
15of Ansible, you might also want to work inside the ./hacking directory
16instead.
17
18Or you can also just look into ./examples/ansible of your reclass checkout,
19where the following steps have already been prepared.
20
21/…/reclass refers to the location of your reclass checkout.
22
23 1. Symlink /…/reclass/adapters/ansible to /etc/ansible/hosts (or
24 ./hacking/hosts)
25
26 2. Copy the two directories 'nodes' and 'classes' from the example
27 subdirectory in the reclass checkout to /etc/ansible
28
29 If you prefer to put those directories elsewhere, you can create
30 /etc/ansible/reclass-config.yml with contents such as
31
32 storage_type: yaml_fs
33 nodes_uri: /srv/reclass/nodes
34 classes_uri: /srv/reclass/classes
35
36 Note that yaml_fs is currently the only supported storage_type, and it's
37 the default if you don't set it.
38
39 3. Check out your inventory by invoking
40
41 ./hosts --list
42
43 which should return 5 groups in JSON-format, and each group has exactly
44 one member 'localhost'.
45
46 4. See the node information for 'localhost':
47
48 ./hosts --host localhost
49
50 This should print a set of keys and values, including a greeting,
51 a colour, and a sub-class called 'RECLASS'.
52
53 5. Execute some ansible commands, e.g.
54
55 ansible -i hosts \* --list-hosts
56 ansible -i hosts \* -m ping
57 ansible -i hosts \* -m debug -a 'msg="${greeting}"'
58 ansible -i hosts \* -m setup
59 ansible-playbook -i hosts test.yml
60
61 6. You can also invoke reclass directly, which gives a slightly different
62 view onto the same data, i.e. before it has been adapted for Ansible:
63
64 /…/reclass.py --pretty-print --inventory
65 /…/reclass.py --pretty-print --nodeinfo localhost
66
67Integration with Ansible
68~~~~~~~~~~~~~~~~~~~~~~~~
69The integration between reclass and Ansible is performed through an adapter,
70and needs not be of our concern too much.
71
72However, Ansible has no concept of "nodes", "applications", "parameters", and
73"classes". Therefore it is necessary to explain how those correspond to
74Ansible. Crudely, the following mapping exists:
75
76 nodes hosts
77 classes groups
78 applications playbooks
79 parameters host_vars
80
81reclass does not provide any group_vars because of its node-centric
82perspective. While class definitions include parameters, those are inherited
83by the node definitions and hence become node_vars.
84
85reclass also does not provide playbooks, nor does it deal with any of the
86related Ansible concepts, i.e. vars_files, vars, tasks, handlers, roles, etc..
87
88 Let it be said at this point that you'll probably want to stop using
89 host_vars, group_vars and vars_files altogether, and if only because you
90 should no longer need them, but also because the variable precedence rules
91 of Ansible are full of surprises, at least to me.
92
93reclass' Ansible adapter massage the reclass output into Ansible-usable data,
94namely:
95
96 - Every class in the ancestry of a node becomes a group to Ansible. This is
97 mainly useful to be able to target nodes during interactive use of
98 Ansible, e.g.
99
100 ansible debiannode@wheezy -m command -a 'apt-get upgrade'
101 → upgrade all Debian nodes running wheezy
102
103 ansible ssh.server -m command -a 'invoke-rc.d ssh restart'
104 → restart all SSH server processes
105
106 ansible mailserver -m command -a 'tail -n1000 /var/log/mail.err'
107 → obtain the last 1,000 lines of all mailserver error log files
108
109 The attentive reader might stumble over the use of singular words, whereas
110 it might make more sense to address all 'mailserver*s*' with this tool.
111 This is convention and up to you. I prefer to think of my node as
112 a (singular) mailserver when I add 'mailserver' to its parent classes.
113
114 - Every entry in the list of a host's applications might well correspond to
115 an Ansible playbook. Therefore, reclass creates a (Ansible-)group for
116 every application, and adds '_hosts' to the name. This postfix can be
117 configured with a CLI option (--applications-postfix) or in the
118 configuration file (applications_postfix).
119
120 For instance, the ssh.server class adds the ssh.server application to
121 a node's application list. Now the admin might create an Ansible playbook
122 like so:
123
124 - name: SSH server management
125 hosts: ssh.server_hosts ← SEE HERE
126 tasks:
127 - name: install SSH package
128 action: …
129
130
131 There's a bit of redundancy in this, but unfortunately Ansible playbooks
132 hardcode the nodes to which a playbook applies.
133
134 It's now trivial to apply this playbook across your infrastructure:
135
136 ansible-playbook ssh.server.yml
137
138 My suggested way to use Ansible site-wide is then to create a 'site'
139 playbook that includes all the other playbooks (which shall hopefully be
140 based on Ansible roles), and then to invoke Ansible like this:
141
142 ansible-playbook site.yml
143
144 or, if you prefer only to reconfigure a subset of nodes, e.g. all
145 webservers:
146
147 ansible-playbook site.yml --limit webserver
148
149 Again, if the singular word 'webserver' puts you off, change the
150 convention as you wish.
151
152 And if anyone comes up with a way to directly connect groups in the
153 inventory with roles, thereby making it unnecessary to write playbook
154 files (containing redundant information), please tell me!
155
156 - Parameters corresponding to a node become host_vars for that host.
157
158It is possible to include Jinja2-style variables like you would in Ansible,
159in parameter values. This is especially powerful in combination with the
160recursive merging, e.g.
161
162 parameters:
163 motd:
164 greeting: Welcome to {{ ansible_fqdn }}!
165 closing: This system is part of {{ realm }}
166
167Now you just need to specify realm somewhere. The reference can reside in
168a parent class, while the variable is defined e.g. in the node.