4
Here are some tips for making the most of Ansible playbooks.
6
You can find some example playbooks illustrating these best practices in our `ansible-examples repository <https://github.com/ansible/ansible-examples>`_. (NOTE: These may not use all of the features in the latest release, but are still an excellent reference!).
11
.. _content_organization:
14
++++++++++++++++++++++
16
The following section shows one of many possible ways to organize playbook content. Your usage of Ansible should fit your needs, however, not ours, so feel free to modify this approach and organize as you see fit.
18
(One thing you will definitely want to do though, is use the "roles" organization feature, which is documented as part
19
of the main playbooks page. See :doc:`playbooks_roles`).
26
The top level of the directory would contain files and directories like so::
28
production # inventory file for production servers
29
stage # inventory file for stage environment
32
group1 # here we assign variables to particular groups
35
hostname1 # if systems need specific variables, put them here
38
site.yml # master playbook
39
webservers.yml # playbook for webserver tier
40
dbservers.yml # playbook for dbserver tier
43
common/ # this hierarchy represents a "role"
45
main.yml # <-- tasks file can include smaller files if warranted
47
main.yml # <-- handlers file
48
templates/ # <-- files for use with the template resource
49
ntp.conf.j2 # <------- templates end in .j2
51
bar.txt # <-- files for use with the copy resource
52
foo.sh # <-- script files for use with the script resource
54
main.yml # <-- variables associated with this role
56
webtier/ # same kind of structure as "common" was above, done for the webtier role
62
How to Arrange Inventory, Stage vs Production
63
`````````````````````````````````````````````
65
In the example below, the *production* file contains the inventory of all of your production hosts. Of course you can pull inventory from an external data source as well, but this is just a basic example.
67
It is suggested that you define groups based on purpose of the host (roles) and also geography or datacenter location (if applicable)::
86
# webservers in all geos
91
# dbservers in all geos
96
# everything in the atlanta geo
101
# everything in the boston geo
107
.. _groups_and_hosts:
109
Group And Host Variables
110
````````````````````````
112
Now, groups are nice for organization, but that's not all groups are good for. You can also assign variables to them! For instance, atlanta has its own NTP servers, so when setting up ntp.conf, we should use them. Let's set those now::
115
# file: group_vars/atlanta
116
ntp: ntp-atlanta.example.com
117
backup: backup-atlanta.example.com
119
Variables aren't just for geographic information either! Maybe the webservers have some configuration that doesn't make sense for the database servers::
122
# file: group_vars/webservers
123
apacheMaxRequestsPerChild: 3000
124
apacheMaxClients: 900
126
If we had any default values, or values that were universally true, we would put them in a file called group_vars/all::
129
# file: group_vars/all
130
ntp: ntp-boston.example.com
131
backup: backup-boston.example.com
133
We can define specific hardware variance in systems in a host_vars file, but avoid doing this unless you need to::
136
# file: host_vars/db-bos-1.example.com
142
Top Level Playbooks Are Separated By Role
143
`````````````````````````````````````````
145
In site.yml, we include a playbook that defines our entire infrastructure. Note this is SUPER short, because it's just including
146
some other playbooks. Remember, playbooks are nothing more than lists of plays::
150
- include: webservers.yml
151
- include: dbservers.yml
153
In a file like webservers.yml (also at the top level), we simply map the configuration of the webservers group to the roles performed by the webservers group. Also notice this is incredibly short. For example::
156
# file: webservers.yml
162
.. _role_organization:
164
Task And Handler Organization For A Role
165
````````````````````````````````````````
167
Below is an example tasks file that explains how a role works. Our common role here just sets up NTP, but it could do more if we wanted::
170
# file: roles/common/tasks/main.yml
172
- name: be sure ntp is installed
173
yum: pkg=ntp state=installed
176
- name: be sure ntp is configured
177
template: src=ntp.conf.j2 dest=/etc/ntp.conf
182
- name: be sure ntpd is running and enabled
183
service: name=ntpd state=running enabled=yes
186
Here is an example handlers file. As a review, handlers are only fired when certain tasks report changes, and are run at the end
190
# file: roles/common/handlers/main.yml
192
service: name=ntpd state=restarted
194
See :doc:`playbooks_roles` for more information.
197
.. _organization_examples:
199
What This Organization Enables (Examples)
200
`````````````````````````````````````````
202
Above we've shared our basic organizational structure.
204
Now what sort of use cases does this layout enable? Lots! If I want to reconfigure my whole infrastructure, it's just::
206
ansible-playbook -i production site.yml
208
What about just reconfiguring NTP on everything? Easy.::
210
ansible-playbook -i production site.yml --tags ntp
212
What about just reconfiguring my webservers?::
214
ansible-playbook -i production webservers.yml
216
What about just my webservers in Boston?::
218
ansible-playbook -i production webservers.yml --limit boston
220
What about just the first 10, and then the next 10?::
222
ansible-playbook -i production webservers.yml --limit boston[0-10]
223
ansible-playbook -i production webservers.yml --limit boston[10-20]
225
And of course just basic ad-hoc stuff is also possible.::
227
ansible -i production -m ping
228
ansible -i production -m command -a '/sbin/reboot' --limit boston
230
And there are some useful commands to know (at least in 1.1 and higher)::
232
# confirm what task names would be run if I ran this command and said "just ntp tasks"
233
ansible-playbook -i production webservers.yml --tags ntp --list-tasks
235
# confirm what hostnames might be communicated with if I said "limit to boston"
236
ansible-playbook -i production webservers.yml --limit boston --list-hosts
240
Deployment vs Configuration Organization
241
````````````````````````````````````````
243
The above setup models a typical configuration topology. When doing multi-tier deployments, there are going
244
to be some additional playbooks that hop between tiers to roll out an application. In this case, 'site.yml'
245
may be augmented by playbooks like 'deploy_exampledotcom.yml' but the general concepts can still apply.
247
Consider "playbooks" as a sports metaphor -- you don't have to just have one set of plays to use against your infrastructure
248
all the time -- you can have situational plays that you use at different times and for different purposes.
250
Ansible allows you to deploy and configure using the same tool, so you would likely reuse groups and just
251
keep the OS configuration in separate playbooks from the app deployment.
253
.. _stage_vs_production:
258
As also mentioned above, a good way to keep your stage (or testing) and production environments separate is to use a separate inventory file for stage and production. This way you pick with -i what you are targeting. Keeping them all in one file can lead to surprises!
260
Testing things in a stage environment before trying in production is always a great idea. Your environments need not be the same
261
size and you can use group variables to control the differences between those environments.
268
Understand the 'serial' keyword. If updating a webserver farm you really want to use it to control how many machines you are
269
updating at once in the batch.
271
See :doc:`playbooks_delegation`.
273
.. _mention_the_state:
275
Always Mention The State
276
++++++++++++++++++++++++
278
The 'state' parameter is optional to a lot of modules. Whether 'state=present' or 'state=absent', it's always best to leave that
279
parameter in your playbooks to make it clear, especially as some modules support additional states.
286
A system can be in multiple groups. See :doc:`intro_inventory` and :doc:`intro_patterns`. Having groups named after things like
287
*webservers* and *dbservers* is repeated in the examples because it's a very powerful concept.
289
This allows playbooks to target machines based on role, as well as to assign role specific variables
290
using the group variable system.
292
See :doc:`playbooks_roles`.
296
Operating System and Distribution Variance
297
++++++++++++++++++++++++++++++++++++++++++
299
When dealing with a parameter that is different between two different operating systems, the best way to handle this is
300
by using the group_by module.
302
This makes a dynamic group of hosts matching certain criteria, even if that group is not defined in the inventory file::
306
# talk to all hosts just so we can learn about them
310
- group_by: key={{ ansible_distribution }}
312
# now just on the CentOS hosts...
317
- # tasks that only happen on CentOS go here
319
If group-specific settings are needed, this can also be done. For example::
322
# file: group_vars/all
326
# file: group_vars/CentOS
329
In the above example, CentOS machines get the value of '42' for asdf, but other machines get '10'.
331
.. _ship_modules_with_playbooks:
333
Bundling Ansible Modules With Playbooks
334
+++++++++++++++++++++++++++++++++++++++
336
.. versionadded:: 0.5
338
If a playbook has a "./library" directory relative to its YAML file, this directory can be used to add ansible modules that will
339
automatically be in the ansible module path. This is a great way to keep modules that go with a playbook together.
343
Whitespace and Comments
344
+++++++++++++++++++++++
346
Generous use of whitespace to break things up, and use of comments (which start with '#'), is encouraged.
353
It is possible to leave off the 'name' for a given task, though it is recommended to provide a description
354
about why something is being done instead. This name is shown when the playbook is run.
361
When you can do something simply, do something simply. Do not reach
362
to use every feature of Ansible together, all at once. Use what works
363
for you. For example, you will probably not need 'vars',
364
'vars_files', 'vars_prompt' and '--extra-vars' all at once,
365
while also using an external inventory file.
372
Use version control. Keep your playbooks and inventory file in git
373
(or another version control system), and commit when you make changes
374
to them. This way you have an audit trail describing when and why you
375
changed the rules that are automating your infrastructure.
380
Learn about YAML syntax
382
Review the basic playbook features
384
Learn about available modules
385
:doc:`developing_modules`
386
Learn how to extend Ansible by writing your own modules
387
:doc:`intro_patterns`
388
Learn about how to select hosts
389
`Github examples directory <https://github.com/ansible/ansible/tree/devel/examples/playbooks>`_
390
Complete playbook files from the github project source
391
`Mailing List <http://groups.google.com/group/ansible-project>`_
392
Questions? Help? Ideas? Stop by the list on Google Groups