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