Ansible Playbooks offer a repeatable, re-usable, simple configuration management and multi-machine deployment system, one that is well suited to deploying complex applications. If you need to execute a task with Ansible more than once, write a playbook and put it under source control. Then you can use the playbook to push out new configuration or confirm the configuration of remote systems. Playbooks can:
declare configurations
orchestrate steps of any manual ordered process, on multiple sets of machines, in a defined order
launch tasks synchronously or asynchronouslyPlaybooks are expressed in YAML format with a minimum of syntax. If you are not familiar with YAML, look at our overview of YAML Syntax and consider installing an add-on for your text editor (see Other Tools and Programs) to help you write clean YAML syntax in your playbooks.
A playbook is composed of one or more ‘plays’ in an ordered list. The terms ‘playbook’ and ‘play’ are sports analogies. Each play executes part of the overall goal of the playbook, running one or more tasks. Each task calls an Ansible module.
A playbook is composed of one or more ‘plays’ in an ordered list. The terms ‘playbook’ and ‘play’ are sports analogies. Each play executes part of the overall goal of the playbook, running one or more tasks. Each task calls an Ansible module.
By default, Ansible executes each task in order, one at a time, against all machines matched by the host pattern. Each task executes a module with specific arguments. When a task has executed on all target machines, Ansible moves on to the next task. You can use strategies to change this default behavior. Within each play, Ansible applies the same task directives to all hosts. If a task fails on a host, Ansible takes that host out of the rotation for the rest of the playbook.
When you run a playbook, Ansible returns information about connections, the name lines of all your plays and tasks, whether each task has succeeded or failed on each machine, and whether each task has made a change on each machine. At the bottom of the playbook execution, Ansible provides a summary of the nodes that were targeted and how they performed. General failures and fatal “unreachable” communication attempts are kept separate in the counts.
Most Ansible modules check whether the desired final state has already been achieved, and exit without performing any actions if that state has been achieved, so that repeating the task does not change the final state. Modules that behave this way are often called ‘idempotent.’ Whether you run a playbook once, or multiple times, the outcome should be the same. However, not all playbooks and not all modules behave this way. If you are unsure, test your playbooks in a sandbox environment before running them multiple times in production.
A playbook runs in order from top to bottom. Within each play, tasks also run in order from top to bottom. Playbooks with multiple ‘plays’ can orchestrate multi-machine deployments,
1. Ansible Terms
Control Node: the machine where Ansible is installed, responsible
for running the provisioning on the servers you are managing.
Inventory: an INI file that contains information about the servers
you are managing.
Playbook: a YAML file containing a series of procedures that
should be automated.
Task: a block that defines a single procedure to be executed, e.g.:
install a package.
Module: a module typically abstracts a system task, like dealing
with packages or creating and changing files. Ansible has a
multitude of built-in modules, but you can also create custom ones.
2. Role: a set of related playbooks, templates and other files,
organized in a pre-defined way to facilitate reuse and share.
Play: a provisioning executed from start to finish is called a
play.
Facts: global variables containing information about the
system, like network interfaces or operating system.
Handlers: used to trigger service status changes, like restarting
or reloading a service.
3. Task Format
A task defines a single automated step that should be executed
by Ansible. It typically involves the usage of a module or the
execution of a raw command. This is how a task looks:
- name: This is a task
apt: name=vim state=latest
The name part is actually optional, but recommended, as it
shows up in the output of the provisioning when the task is
executed.
The apt part is a built-in Ansible module that abstracts the
management of packages on Debian-based distributions.
This example task tells Ansible that the package vim should
have its state changed to latest, which will cause the package
4. Playbooks
Playbooks are YAML files containing a series of directives to
automate the provisioning of a server. The following example is
a simple playbook that perform two tasks: updates the apt
cache and installs vim afterwards:
---
- hosts: all
become: true
tasks:
- name: Update apt-cache
apt: update_cache=yes
- name: Install Vim
apt: name=vim state=latest
YAML relies on indentation to serialize data structures.
7. Using Conditions
- name: Shutdown Debian Based Systems
command: /sbin/shutdown -t now
when: ansible_os_family == "Debian"
A common use case for conditionals in IT automation is when
the execution of a task depends on the output of a command.
With Ansible, the way we implement this is by registering a
variable to hold the results of a command execution, and then
testing this variable in a subsequent task.
We can test for the command’s exit status (if failed or
successful).
We can also check for specific contents inside the output,
although this might require the usage of regex expressions and
string parsing commands.
8. ---
- hosts: web_host1
tasks:
- name: Check if PHP is installed
register: php_installed
command: php -v
ignore_errors: true
- name: This task is only executed if PHP is
9. Using templates
vhost.tpl
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot {{ doc_root }}
<Directory {{ doc_root }}>
AllowOverride All
Require all granted
</Directory>
11. Roles
Roles are a level of abstraction on top of tasks and playbooks
that let you structure your Ansible configuration in a modular
and reusable format.
Playbooks can become complex when they are responsible for
configuring many different systems with multiple tasks for each
system, so Ansible also lets you organize tasks in a directory
structure called a Role.
With this configuration, playbooks invoke roles instead of tasks,
so you can still group tasks together and then reuse roles in
other playbooks
Roles also allow you to collect templates, static files, and
variables along with your tasks in one structured format.
12. roles
apache
defaults files handlers meta tasks templates vars
defaults: This directory lets you set default variables for included or
dependent roles. Any defaults set here can be overridden in
playbooks or inventory files.
files: This directory contains static files and script files that might be
copied to or executed on a remote server.
handlers: All handlers that were in your playbook previously can now
be added into this directory.
13. meta: This directory is reserved for role
metadata, typically used for dependency
management.. For example, you can define a
list of roles that must be applied before the
current role is invoked.
templates: This directory is reserved for
templates that will generate files on remote
hosts. Templates typically use variables defined
on files located in the vars directory, and on
host information that is collected at runtime.
tasks: This directory contains one or more files
17. Variables
In Ansible, variables provide the much-needed flexibility in
Playbooks, templates and inventories as we shall later see in
this tutorial.
Built-in variables can be used to provide system information
such as hostname, system architecture, interfaces etc.
Variables can also be used to replace strings and also in loops
to loop through a given set of values.
18. A valid variable name is made of the following characters
Letters
Numbers
Underscores
A combination of any two or all of the above
A variable SHOULD ALWAYS START WITH A LETTER and SHOULD
NOT CONTAIN ANY SPACES.
19. Assigning a value to a variable in a playbook is quite easy and
straightforward.
Begin by calling the vars keyword then call the variable name
followed by the value as shown.
---
- hosts: all
vars:
salutations: Hello guys!
tasks:
- name: Ansible Variable Basic Usage
debug:
msg: "{{ salutations }}"
20. Variables with array
You can use arrays and assign them to variables as shown in
the syntax below:
vars:
arrayname:
– value1
– value2
21. - hosts: all
vars:
students:
- Mark
- Melisa
- Arthur
- Kevin
- Lisa
26. Although you can specify variables in the inventory file, standard practice
discourages storing variables in the inventory file. This is where the host and
group variable files come in.
In a host variable file, the variable applier only to one host system in the
inventory file. The host variable file is usually stored in the host_vars
directory which is usually specified in /etc/ansible/ path.
Consider the inventory file below where we have 2 servers each using
different ntp servers
[web_servers]
webserver_1 ntp_server=uk.pool.ntp.org
webserver_2 ntp_server=de.pool.ntp.org
# vim /etc/ansible/host_vars/webserver_1
---