Ansible Essentials Workshop

What You Will Learn

Ansible is capable of handling many powerful automation tasks with the flexibility to adapt to many environments and workflows. With Ansible, users can very quickly get up and running to do real work.

What is Ansible? / "The Ansible Way"

How Ansible Works and its Key Components

Automating with Ad-Hoc Commands

Writing Playbooks / Playbook Basics

Reuse and Redistribution of Ansible Content with Roles

This deck is designed to provide students with direct introductory instruction and guidance to beginning to automate with Ansible. It is the starting point for students intent on becoming more proficient with Ansible through other Lightbulb modules and their own usage.

This deck supports lecture and hands-on forms of presenting this material.

Allow 2 hours to deliver the lecture-based form and 4 hours for stopping to do the workshop assignments. To access the additional slides for delivering the workshops, navigate down when available.

What is Ansible?

It's a simple automation language that can perfectly describe an IT application infrastructure in Ansible Playbooks.

It's an automation engine that runs Ansible Playbooks.

Ansible is an automation platform:

Playbooks make up the automation language

The code base is the automation engine.

Ansible Tower manages existing automation

What is Ansible Tower?

Ansible Tower is an enterprise framework for controlling, securing and managing your Ansible automation with a UI and RESTful API.

Ansible is an automation platform:

Playbooks make up the automation language

The code base is the automation engine.

Ansible Tower manages existing automation

Why Ansible? What Sets Ansible Apart?

Ansible has a number of qualities that make it the most rapidly growing automation platform in the world.

What is it about Ansible that makes it worth talking about?

Why Ansible? What Sets Ansible Apart?

Ansible is simple. Playbooks are human and machine readable, no special coding skills required – and even people in your IT organization that don’t know Ansible can read an Ansible playbook and understand what’s happening.

This simplicity also means that it’s easy to install and get started to do real work with it quickly – usually in just minutes.

Ansible also works like you think – tasks are always executed in order. All together, the simplicity ensures that you can get started quickly.

Why Ansible? What Sets Ansible Apart?

Ansible is powerful. Simplicity is great, but to be really useful, you also need the powerful features that ensure you can model even the most complex of IT workflows.

Ansible is complete automation, able to deploy apps, manage orchestration, and configure the infrastructure, networks, operating systems, and services that you’re already using today.

Together, Ansible’s capabilities allow you to orchestrate the entire application and environment lifecycle, regardless of where It's deployed.

Why Ansible? What Sets Ansible Apart?

Ansible is Agentless. Ansible relies on industry-standard and trusted SSH and WinRM protocols to automate. There are no agents or other software to install, and no additional firewall ports to open. With no need to separately stand up a management infrastructure, Ansible further reduces the activation energy required from your team to start automating today.

In a world where IT complexity stymies even the most basic of IT tasks, Ansible provides a much needed respite – and path forward enabling teams to crush productivity-stealing complexity and overhead.

Ansible Provides End To End Goodness

What can you do with Ansible? Nearly anything. Ansible is the Swiss Army knife of DevOps, capable of handling many powerful automation tasks with the flexibility to adapt to many environments and workflows.

Many folks like to categorize Ansible as a configuration manager, and although yes, Ansible can do that, it"s just the tip of the iceberg. When you couple configuration management with orchestration, you can start to model complicated multi-tier deployments with ease.

With Ansible, once someone on your team automates something, everyone on the team now knows how to do it.

Batteries Included

Ansible comes bundled with hundreds of modules for a wide variety of automation tasks

cloud

containers

database

files

messaging

monitoring

network

notifications

packaging

source control

system

testing

utilities

web infrastructure

Ansible Modules control the things that you’re automating. They can do everything from acting on system files, installing packages, or making API calls to a service framework. Ansible ships with around 2100+ today -- and this number is always expanding with every release.

Ansible: The Language of DevOps

COMMUNICATION IS THE KEY TO DEVOPS.

Ansible is the first automation languagethat can be read and written across IT.

Ansible is the only automation enginethat can automate the entire application lifecycleand continuous delivery pipeline.

DevOps is a verb. Rather than think of "DevOps" as an object, think of it as the effort that holds pieces together from the first moment a server is racked to the end user's session.

With DevOps being the effort in the middle of it all, consider how Ansible can act as the catalyst to empower every department... every step of the way.

Ansible can be a powerful COLLABORATION TOOL

Ansible: Endless Use Cases

Ansible fills virtually countless use cases with its versatility.

✾ Ansible is NOT just a Config Management Tool.

☇ Ansible is NOT just an Application Deployment Tool.

☁ Ansible is NOT just a Provisioning Tool.

☡ Ansible is NOT just a CI/CD Tool.

✎ Ansible is NOT just an Audit and Compliance Tool.

➰ Ansible is NOT just an Orchestration Tool.

Ansible is a powerful automation engine...

with strong use cases for all of the above tasks.

Stuff Goes Here

PEOPLE LOVE ANSIBLE.

Ansible is taking the world by storm with unbelievable popularity.

Ansible is open source. Created with contributions from an active open source community and built for the people who use it every day. At its heart, Ansible was made to help more people experience the power of automation so they could work better and faster together.

33,500+

Stars on GitHub

2100+

Ansible Modules

500,000+

Downloads Per Month

Ansiblefest!!!!

Ansible is open source. Created with contributions from an active open source community and built for the people who use it every day. At its heart, Ansible was made to help more people experience the power of automation so they could work better and faster together.

Ansible is open source. Created with contributions from an active open source community and built for the people who use it every day. At its heart, Ansible was made to help more people experience the power of automation so they could work better and faster together.

Simple: Installing Ansible

The diagram on this slide shows the relationship between all the key components of Ansible starting with the user who writes an Ansible playbook.

HOW ANSIBLE WORKS

Let's Take A Look At The Technology

Ansible

How Ansible Works

The diagram on this slide shows the relationship between all the key components of Ansible starting with the user who writes an Ansible playbook.

Plays & Playbooks

Playbooks are written in YAML and are used to invoke Ansible modules to perform tasks that are executed sequentially i.e top to bottom. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT workflow. Playbooks are like an instruction manual and describe the state of environment.

Modules & Tasks

If playbooks are the instruction manual for setting up and managing your infrastructure, Ansible modules are the tools in your toolkit.

Modules are executable bits of code that operate on hosts; however, we don’t need to understand the underlying implementation to get them to work. Modules do the heavy-lifting in Ansible and abstract users from the complexity of the underlying details.

Inventory

Your inventory of hosts are your raw material. They are a list of nodes and associated meta data that Ansible can automate.

Inventory lists can be built and stored several different ways, including static files, or can be dynamically-generated from an external source.

You can also specify variables as part of an inventory list. For instance, set a particular host key that’s needed to log into that system remotely. Inventories are ultimately lists of things you want to automate across.

Here in this slide was see an example of a simple static inventory list of three hosts (webserver1, webserver2 and dbserver1) in two groups (web and db).

Inventory

In large-scale environment subject to constant change, synchronizing and maintaining inventory statically is tedious and error prone endeavor. That is why Ansible includes support of external sources such as public and private cloud providers and configuration management database (CMDB) systems.

Modules Documentation

> COPY (/usr/lib/python2.7/site-packages/ansible/modules/files/copy.py)
The `copy' module copies a file from the local or remote machine to a
location on the remote machine. Use the [fetch] module to copy files
from remote locations to the local box. If you need variable
interpolation in copied files, use the [template] module. For Windows
targets, use the [win_copy] module instead.
* note: This module has a corresponding action plugin.
OPTIONS (= is mandatory):
- attributes
Attributes the file or directory should have. To get supported flags
look at the man page for `chattr' on the target system. This string
should contain the attributes in the same order as the one displayed by
`lsattr'.
(Aliases: attr)[Default: (null)]
version_added: 2.3
- backup
Create a backup file including the timestamp information so you can get
the original file back if you somehow clobbered it incorrectly.
[Default: no]
type: bool
version_added: 0.7
- checksum
SHA1 checksum of the file being transferred. Used to validate that the
copy of the file was successful.
If this is not provided, ansible will use the local calculated checksum
of the src file.
[Default: (null)]
version_added: 2.5
- content
When used instead of `src', sets the contents of a file directly to the
specified value. For anything advanced or with formatting also look at
the template module.
[Default: (null)]
version_added: 1.1
- decrypt
This option controls the autodecryption of source files using vault.
[Default: Yes]
type: bool
version_added: 2.4
= dest
Remote absolute path where the file should be copied to. If `src' is a
directory, this must be a directory too. If `dest' is a nonexistent path
and if either `dest' ends with "/" or `src' is a directory, `dest' is
created. If `src' and `dest' are files, the parent directory of `dest'
isn't created: the task fails if it doesn't already exist.
- directory_mode
When doing a recursive copy set the mode for the directories. If this is
not set we will use the system defaults. The mode is only set on
directories which are newly created, and will not affect those that
already existed.
[Default: (null)]
version_added: 1.5
- follow
This flag indicates that filesystem links in the destination, if they
exist, should be followed.
[Default: no]
type: bool
version_added: 1.8
- force
the default is `yes', which will replace the remote file when contents
are different than the source. If `no', the file will only be
transferred if the destination does not exist.
(Aliases: thirsty)[Default: yes]
type: bool
version_added: 1.1
- group
Name of the group that should own the file/directory, as would be fed to
`chown'.
[Default: (null)]
- local_follow
This flag indicates that filesystem links in the source tree, if they
exist, should be followed.
[Default: yes]
type: bool
version_added: 2.4
- mode
Mode the file or directory should be. For those used to `/usr/bin/chmod'
remember that modes are actually octal numbers. You must either specify
the leading zero so that Ansible's YAML parser knows it is an octal
number (like `0644' or `01777') or quote it (like `'644'' or `'0644'' so
Ansible receives a string and can do its own conversion from string into
number. Giving Ansible a number without following one of these rules
will end up with a decimal number which will have unexpected results.
As of version 1.8, the mode may be specified as a symbolic mode (for
example, `u+rwx' or `u=rw,g=r,o=r'). As of version 2.3, the mode may
also be the special string `preserve'. `preserve' means that the file
will be given the same permissions as the source file.
[Default: (null)]
- owner
Name of the user that should own the file/directory, as would be fed to
`chown'.
[Default: (null)]
- remote_src
If `no', it will search for `src' at originating/master machine.
If `yes' it will go to the remote/target machine for the `src'. Default
is `no'.
Currently `remote_src' does not support recursive copying.
`remote_src' only works with `mode=preserve' as of version 2.6.
[Default: no]
type: bool
version_added: 2.0
- selevel
Level part of the SELinux file context. This is the MLS/MCS attribute,
sometimes known as the `range'. `_default' feature works as for
`seuser'.
[Default: s0]
- serole
Role part of SELinux file context, `_default' feature works as for
`seuser'.
[Default: (null)]
- setype
Type part of SELinux file context, `_default' feature works as for
`seuser'.
[Default: (null)]
- seuser
User part of SELinux file context. Will default to system policy, if
applicable. If set to `_default', it will use the `user' portion of the
policy if available.
[Default: (null)]
- src
Local path to a file to copy to the remote server; can be absolute or
relative. If path is a directory, it is copied recursively. In this
case, if path ends with "/", only inside contents of that directory are
copied to destination. Otherwise, if it does not end with "/", the
directory itself with all contents is copied. This behavior is similar
to Rsync.
[Default: (null)]
- unsafe_writes
Normally this module uses atomic operations to prevent data corruption
or inconsistent reads from the target files, sometimes systems are
configured or just broken in ways that prevent this. One example are
docker mounted files, they cannot be updated atomically and can only be
done in an unsafe manner.
This boolean option allows ansible to fall back to unsafe methods of
updating files for those cases in which you do not have any other
choice. Be aware that this is subject to race conditions and can lead to
data corruption.
[Default: no]
type: bool
version_added: 2.2
- validate
The validation command to run before copying into place. The path to the
file to validate is passed in via '%s' which must be present as in the
example below. The command is passed securely so shell features like
expansion and pipes won't work.
[Default: (null)]
NOTES:
* The [copy] module recursively copy facility does not scale to lots
(>hundreds) of files. For alternative, see [synchronize] module,
which is a wrapper around `rsync'.
* For Windows targets, use the [win_copy] module instead.
AUTHOR: Ansible Core Team, Michael DeHaan
METADATA:
status:
- stableinterface
supported_by: core

TO Make This List SCROLL, click anywhere on the terminal window

TO Make This List STOP, click the "Ansible Terminal" text on top of the console

Modules Documentation

Also displays usable copy / paste examples of working functional tasks with this module.

Modules Documentation

- name: Copies files to remote locations
copy:
attributes: # Attributes the file or directory should have. To get supported flags look at the man page for `chattr' on the target system. This string
should contain the attributes in the same order as the one displayed by `lsattr'.
backup: # Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.
checksum: # SHA1 checksum of the file being transferred. Used to validate that the copy of the file was successful. If this is not provided, ansible
will use the local calculated checksum of the src file.
content: # When used instead of `src', sets the contents of a file directly to the specified value. For anything advanced or with formatting also
look at the template module.
decrypt: # This option controls the autodecryption of source files using vault.
dest: # (required) Remote absolute path where the file should be copied to. If `src' is a directory, this must be a directory too. If `dest' is a
nonexistent path and if either `dest' ends with "/" or `src' is a directory, `dest' is created. If `src'
and `dest' are files, the parent directory of `dest' isn't created: the task fails if it doesn't already
exist.
directory_mode: # When doing a recursive copy set the mode for the directories. If this is not set we will use the system defaults. The mode is only set on
directories which are newly created, and will not affect those that already existed.
follow: # This flag indicates that filesystem links in the destination, if they exist, should be followed.
force: # the default is `yes', which will replace the remote file when contents are different than the source. If `no', the file will only be
transferred if the destination does not exist.
group: # Name of the group that should own the file/directory, as would be fed to `chown'.
local_follow: # This flag indicates that filesystem links in the source tree, if they exist, should be followed.
mode: # Mode the file or directory should be. For those used to `/usr/bin/chmod' remember that modes are actually octal numbers. You must either
specify the leading zero so that Ansible's YAML parser knows it is an octal number (like `0644' or
`01777') or quote it (like `'644'' or `'0644'' so Ansible receives a string and can do its own conversion
from string into number. Giving Ansible a number without following one of these rules will end up with a
decimal number which will have unexpected results. As of version 1.8, the mode may be specified as a
symbolic mode (for example, `u+rwx' or `u=rw,g=r,o=r'). As of version 2.3, the mode may also be the
special string `preserve'. `preserve' means that the file will be given the same permissions as the
source file.
owner: # Name of the user that should own the file/directory, as would be fed to `chown'.
remote_src: # If `no', it will search for `src' at originating/master machine. If `yes' it will go to the remote/target machine for the `src'. Default
is `no'. Currently `remote_src' does not support recursive copying. `remote_src' only works with
`mode=preserve' as of version 2.6.
selevel: # Level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the `range'. `_default' feature works as for
`seuser'.
serole: # Role part of SELinux file context, `_default' feature works as for `seuser'.
setype: # Type part of SELinux file context, `_default' feature works as for `seuser'.
seuser: # User part of SELinux file context. Will default to system policy, if applicable. If set to `_default', it will use the `user' portion of
the policy if available.
src: # Local path to a file to copy to the remote server; can be absolute or relative. If path is a directory, it is copied recursively. In this
case, if path ends with "/", only inside contents of that directory are copied to destination. Otherwise,
if it does not end with "/", the directory itself with all contents is copied. This behavior is similar to
Rsync.
unsafe_writes: # Normally this module uses atomic operations to prevent data corruption or inconsistent reads from the target files, sometimes systems are
configured or just broken in ways that prevent this. One example are docker mounted files, they cannot be
updated atomically and can only be done in an unsafe manner. This boolean option allows ansible to fall
back to unsafe methods of updating files for those cases in which you do not have any other choice. Be
aware that this is subject to race conditions and can lead to data corruption.
validate: # The validation command to run before copying into place. The path to the file to validate is passed in via '%s' which must be present as
in the example below. The command is passed securely so shell features like expansion and pipes won't
work.

TO Make This List SCROLL, click anywhere on the terminal window

TO Make This List STOP, click the "Ansible Terminal" text on top of the console

Modules Documentation

Modules: Run Commands

If Ansible doesn't have a module that suits your needs there are the “run command” modules:

command: Takes the command and executes it on the host. The most secure and predictable.

shell: Executes through a shell like /bin/sh so you can use pipes etc. Be careful.

raw: Executes a command without going through the Ansible module subsystem.

NOTE: Unlike standard modules, run commands have no concept of desired state and should only be used as a last resort.

"Run commands" are what we collectively call these modules that enable users to do command-line operations in different ways. They’re a great catch all mechanism for getting things done, but they should be used sparingly and as a last resort. The reasons are many and varied.

The overuse of run commands is common amongst those just becoming familiar with Ansible for automating their work. They use shell to fire off a bash command they already know without stopping to look at the Ansible docs. That works well enough initially, but it undermines the value of automating with Ansible and sets things up for problems down the road. As a best practice, always check the hundreds of Ansible shipping modules for what you need and use those first and run commands as a last resort.

NOTE:shell allows for IO redirection such as pipes. This is why It's best practice to use command unless they need to pipe something. It also best practice to never pass user input or variables thru a run command.

INVENTORY

Define hosts on which the playbook will run.

Ansible

Inventory

Inventory is a collection of hosts (nodes) with associated data and groupings that Ansible can connect and manage.

Inventory consists of hosts, groups, inventory specific data. Inventory can either be static or dynamic.

Inventory is a collection of the hosts (nodes) with associated metadata and groupings that Ansible can connect and manage. An inventory source can be static files or dynamically retrieved from an external system.

You can specify a different inventory file using the -i <path> option on the command-line or your Ansible configuration file.

Static Inventory Example

Static inventory is the easiest source to get started with. This example shows a static inventory source in It’s simplest form – a single file with a list of IP addresses or hostnames.

NOTE: Ansible infers a localhost is present even if it is not explicitly listed. This is why you can actually run Ansible without a inventory source. Ansible will only be able to operate on the localhost where it is being run.

The example shown here is a more practical and common example of a static inventory file.

Static inventory files are expressed in INI format. The headings in brackets are group names, which are used in classifying systems and deciding what systems you are controlling at what times and for what purpose. Hosts can belong to multiple groups and groups can be members of other groups. (The latter is not shown here.)

NOTE: This example contains variables, a topic we haven't touched on just yet. We'll go into them on the next slide.

Other noteworthy attributes in our example:

ansible_host is an example of a host variable.

Hosts can be assigned arbitrary human-meaningful names or aliases such as "control" and "haproxy". Ansible will instead use the value of ansible_host (one of several "magic" inventory variables) as the network address to connect.

Static inventory files can support character ranges such as "node-[1:3]"

Like localhost, Ansible infers an "all" group is present. As its name implies, all inventory hosts are members of this group.

The heading "all:vars" is an example of group variable assignment using two more "magic" variables, ansible_ssh_private_key_file and ansible_user.

The example shown here is a more practical and common example of a static inventory file.

Static inventory files are expressed in INI format. The headings in brackets are group names, which are used in classifying systems and deciding what systems you are controlling at what times and for what purpose. Hosts can belong to multiple groups and groups can be members of other groups. (The latter is not shown here.)

NOTE: This example contains variables, a topic we haven't touched on just yet. We'll go into them on the next slide.

Other noteworthy attributes in our example:

ansible_host is an example of a host variable.

Hosts can be assigned arbitrary human-meaningful names or aliases such as "control" and "haproxy". Ansible will instead use the value of ansible_host (one of several "magic" inventory variables) as the network address to connect.

Static inventory files can support character ranges such as "node-[1:3]"

Like localhost, Ansible infers an "all" group is present. As its name implies, all inventory hosts are members of this group.

The heading "all:vars" is an example of group variable assignment using two more "magic" variables, ansible_ssh_private_key_file and ansible_user.

The example shown here is a more practical and common example of a static inventory file.

Static inventory files are expressed in INI format. The headings in brackets are group names, which are used in classifying systems and deciding what systems you are controlling at what times and for what purpose. Hosts can belong to multiple groups and groups can be members of other groups. (The latter is not shown here.)

NOTE: This example contains variables, a topic we haven't touched on just yet. We'll go into them on the next slide.

Other noteworthy attributes in our example:

ansible_host is an example of a host variable.

Hosts can be assigned arbitrary human-meaningful names or aliases such as "control" and "haproxy". Ansible will instead use the value of ansible_host (one of several "magic" inventory variables) as the network address to connect.

Static inventory files can support character ranges such as "node-[1:3]"

Like localhost, Ansible infers an "all" group is present. As its name implies, all inventory hosts are members of this group.

The heading "all:vars" is an example of group variable assignment using two more "magic" variables, ansible_ssh_private_key_file and ansible_user.

The example shown here is a more practical and common example of a static inventory file.

Static inventory files are expressed in INI format. The headings in brackets are group names, which are used in classifying systems and deciding what systems you are controlling at what times and for what purpose. Hosts can belong to multiple groups and groups can be members of other groups. (The latter is not shown here.)

NOTE: This example contains variables, a topic we haven't touched on just yet. We'll go into them on the next slide.

Other noteworthy attributes in our example:

ansible_host is an example of a host variable.

Hosts can be assigned arbitrary human-meaningful names or aliases such as "control" and "haproxy". Ansible will instead use the value of ansible_host (one of several "magic" inventory variables) as the network address to connect.

Static inventory files can support character ranges such as "node-[1:3]"

Like localhost, Ansible infers an "all" group is present. As its name implies, all inventory hosts are members of this group.

The heading "all:vars" is an example of group variable assignment using two more "magic" variables, ansible_ssh_private_key_file and ansible_user.

AD-HOC COMMANDS

An ad-hoc command is a single Ansible task to perform quickly, but don’t want to save for later.

Ansible ad-hoc commands is a good place to start to understand the basics of what Ansible can do before learning how to use playbooks – ad-hoc commands can also be used to do quick things that you might not necessarily want to write a full playbook for.

Generally speaking, the true power of Ansible lies in playbooks. So why would you use ad-hoc tasks versus playbooks?

For instance, if you wanted to restart a service on all of your lab nodes, you could execute a quick one-liner in Ansible without writing a playbook.

Ad-Hoc Commands: Common Options

-m MODULE_NAME, --module-name=MODULE_NAMEModule name to execute the ad-hoc command

The second ad-hoc command example from the prior slide provides the following JSON output of a localhost facts run.

Facts are bits of information derived from examining a host systems that are stored as variables for later use. An example of this might be the IP address of the host, or what operating system it is running. The facts Ansible will discover about a host is extensive. What's shown here is just a small sample. Run ansible localhost -m setup for a more complete representation.

Ansible collects facts using the setup module. By default, Ansible will run the setup module before any other tasks are executed in a playbook. These facts can be referenced by subsequent automation tasks on a per host-basis during the playbook run.

VARIABLES:

What are they?

How do they work for me?

What can I do with them?

How do I override or redefine them in flight?

Let's talk about what they are, how they work, and some of the ways we can use them.

Variables

Ansible can work with metadata from various sources and manage their context in the form of variables.

Command line parameters

Plays and tasks

Files

Inventory

Discovered facts

Roles

While automation exists to make it easier to make things repeatable, all of your systems are not exactly alike.

Variables are used to store metadata for each host drawing from numerous sources. For example variable may be for things like facts or file paths or package versions.

Variable Precedence

The order in which the same variable from different sources will override each other.

extra vars

task vars (only for the task)

block vars (only for tasks in block)

role and include vars

play vars_files

play vars_prompt

play vars

set_facts

registered vars

host facts

playbook host_vars

playbook group_vars

inventory host_vars

inventory group_vars

inventory vars

role defaults

If variables of the same name are defined in multiple sources, they get overwritten in a certain and specific order. This is why this variable precedence is important to understand.

There are 16 levels of variable precedence as of Ansible 2.x. The extra_vars (passed thru the command-line) always take precedence vs. role defaults which will always get overridden by any other source. The previous inventory example defines vars at 13 and 14 (highlighted in the list) in the variable precedence chain.

It's a good idea to limit the different sources where a specific variable is being set. While Ansible's variable precedence handling is comprehensive and well-defined, it can laborious to keep the resolution of multiple sources straight.

NOTE: The inventory variables sources showed in the static inventory example a couple of slides back are in bold type.

Tasks in a Play

Tasks are the powerful pieces within a playbook that state paremeters and instruct the Ansible engine

Tasks

Tasks are the application of a module to perform a specific unit of work.

file: A directory should exist

yum: A package should be installed

service: A service should be running

template: Render a configuration file from a template

get_url: Fetch an archive file from a URL

git: Clone a source code repository

We've already reviewed modules, the batteries and tools Ansible provides. Tasks are the specific application of a module to perform a unit of automation.

Here we see a list of examples of common modules being applied to do something.

ANATOMY OF A PLAYBOOK

Let's dissect the basics of a playbook and make sure we understand the core components.

Plays & Playbooks

Plays are ordered sets of tasks to execute against host selections from your inventory. A playbook is a file containing one or more plays.

Playbooks are text files that contain one or more plays that are expressed in YAML. A play defines target hosts and a task list that are executed sequentially (i.e top to bottom) to achieve a certain state on those hosts.

Ansible allows you to "become" another user or with elevated rights to execute a task or an entire play (shown above). This is done using existing privilege escalation tools, which you probably already use or have configured, like sudo (the default), su, pfexec, doas, pbrun, dzdo, ksu and others.

Here we see modules, such as yum, being applied to a to perform a unit of automation such as to assure the latest httpd package is present on a host.

DO MORE.

Let's get a bit more advanced with some rich functionality that Ansible provides.

Doing More with Playbooks

Here are some more essential playbook features that you can apply:

Templates

Loops

Conditionals

Tags

Blocks

We only have covered the most essential capabilities of what can be done with a playbook so far.

Here we list a few more though this is still far from all there is. There's many other powerful playbook features for handling less common though vital automation workflows. No need to learn everything at once. You can start small and pick up more features over time as you need them.

Templates

Templates are a vital feature provided by the Jinja2 template engine, a powerful piece of software independent of Ansible. Ansible makes this usage as seamless and transparent as possible. Most will not realize they are doing templating when they develop plays with Ansible.

We don't show any specific template examples at the moment because we'll have plenty of opportunity to see templates in action as we cover other topics.

In all actuality, what is covered here only touches upon a few of its most basic features. To go deeper see these docs:

This example demonstrates a basic loop with with_items. The loop sets a variable called "item", a template variable courtesy of the embedded Jinja2 template engine, with the list value that is in context.

There are many different and specialized types of task loops to work with. See the Loops documentation to go deeper.

WORKING WITH CONDITIONALS

Ansible supports the conditional execution of a task based on the run-time evaluation of variable, fact, or previous task result.

Ansible Terminal

- yum:
name: httpd
state: latest
when: ansible_os_family == "RedHat"

Conditionals are another instance of Jinja2 in action within Ansible plays themselves. In the provided example "ansible_os_family" is a fact variable Ansible will set.

There are other forms of conditional clauses, but when is usually all that is needed.

NOTE: Conditional clauses are considered to be raw Jinja2 expression without double curly braces.

In the provided example, if the playbook were run with --tags "packages" the yum task would execute and the template task would be skipped. If the playbook were run with --tags "configuration" the opposite would happen. Without a --tags both tasks would execute like normal.

Tags can be seen as a simple though specialized form of conditional statement designed to enable the execution of a subset tasks. Tags are a bit more than simple boolean flags though. To dig deeper see the playbook Tags documentation.

WORKING WITH BLOCKS

Blocks cut down on repetitive task directives, allow for logical grouping of tasks and even in play error handling.

In the provided example we use a block to group two tasks that are to be conditional executed if a host is running a Red Hat family linux using one conditional clause. In practice, we could have copied the when clause onto each task and gotten same result. Using a block, there is less clutter thereby less to maintain and nothing to keep in sync. The utility of using a block increases the more tasks and clauses are in use.

Blocks have a play in error handling and automating roll backs that we won't get into here given the scope of that topic.

ANSIBLE VAULT: COMPLETE ENCRYPTED FILE

ANSIBLE VAULT: COMPLETE ENCRYPTED FILE

Editing an encrypted file with Ansible Vault.

Ansible Terminal

~~~~~~~~~~~~~~~~~~~~
"/tmp/tmpQD4uZF.yml" 0L, 0C

This example demonstrates a basic loop with with_items. The loop sets a variable called "item", a template variable courtesy of the embedded Jinja2 template engine, with the list value that is in context.

There are many different and specialized types of task loops to work with. See the Loops documentation to go deeper.

ANSIBLE VAULT: COMPLETE ENCRYPTED FILE

Editing an encrypted file with Ansible Vault.

Ansible Terminal

movie_title: Ronin
movie_phrase: 'Whenever there is any doubt, there is no doubt'
movie_actor: Robert De Niro
movie_character: Sam
~~~~~~~~~~~~~~~~
:wq

This example demonstrates a basic loop with with_items. The loop sets a variable called "item", a template variable courtesy of the embedded Jinja2 template engine, with the list value that is in context.

There are many different and specialized types of task loops to work with. See the Loops documentation to go deeper.

Copy the encrypted string and paste it into a non-encrypted YAML file.

ANSIBLE VAULT: ENCRYPTED VARIABLE

Including an encrypted variable in a plaintext playbook.

Ansible Terminal

---
- hosts: localhost
connection: local
vars:
fonzie_show: Happy Days
fonzie_transport: Motorcycle
fonzie_stunt: !vault |
$ANSIBLE_VAULT;1.1;AES256
35613061636564623138646464393731633534343261393532343263633763356364633366636633
6430663339613762306235323035326663363665316234650a303434333462343731356632333136
37393966336465386131666635333537636133313864383865303138303262343939326563373730
3063376263303037340a356263333131626239316630653465313931353863623237666464613030
37346537336430386265633239346566313466323764336234346361626666643334
fonzie_office: Mens room at Arnold's Diner
fonzie_jacket: Leather
fonzie_phrase: Aaaaaaayyyyyyyy
tasks:
- name: prove that we can read the variables within the encrypted string
debug:
msg: |
Fonzie is a character from the TV show, {{ fonzie_show }}. He rides a {{ fonzie_transport }},
wears a {{ fonzie_jacket }} jacket, and has an office in the {{ fonzie_office }}.
Fonzie is most famous for his stunt where he {{ fonzie_stunt }}, after which,
he said {{ fonzie_phrase }}!

Stuff goes here

ANSIBLE VAULT: ENCRYPTED VARIABLE

Including an encrypted variable in a plaintext playbook.

Ansible Terminal

---
- hosts: localhost
connection: local
vars:
fonzie_show: Happy Days
fonzie_transport: Motorcycle
fonzie_stunt: !vault |
$ANSIBLE_VAULT;1.1;AES256
35613061636564623138646464393731633534343261393532343263633763356364633366636633
6430663339613762306235323035326663363665316234650a303434333462343731356632333136
37393966336465386131666635333537636133313864383865303138303262343939326563373730
3063376263303037340a356263333131626239316630653465313931353863623237666464613030
37346537336430386265633239346566313466323764336234346361626666643334
fonzie_office: Mens room at Arnold's Diner
fonzie_jacket: Leather
fonzie_phrase: Aaaaaaayyyyyyyy
tasks:
- name: prove that we can read the variables within the encrypted string
debug:
msg: |
Fonzie is a character from the TV show, {{ fonzie_show }}. He rides a {{ fonzie_transport }},
wears a {{ fonzie_jacket }} jacket, and has an office in the {{ fonzie_office }}.
Fonzie is most famous for his stunt where he {{ fonzie_stunt }}, after which,
he said {{ fonzie_phrase }}!

Stuff goes here

ANSIBLE VAULT: ENCRYPTED VARIABLE

Including an encrypted variable in a plaintext playbook.

Ansible Terminal

[ansible@redhat] $ ansible-playbook --ask-vault-pass fonzie_playbook.yml
Vault password:
PLAY [localhost] *************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************
ok: [localhost]
TASK [prove that we can read the variable within the encrypted string] *******************************************************
ok: [localhost] => {
"msg": "Fonzie is a character from the TV show, Happy Days. He rides a Motorcycle,
wears a Leather jacket, and has an office in the Mens room at Arnold's Diner.
Fonzie is most famous for his stunt where he Jumped The Shark, after which,
he said Aaaaaaayyyyyyyy!"
}
PLAY RECAP *******************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0

The role, by default, creates a directory with its own name, then subdirectories below that. When you call this role within an Ansible playbook, you use this directory name as the name of the role to include.

The VARIABLES and DEFAULTS in a role are essentially the same type of information. But remember in the variable order of precedence, once is the highest and one is the lowest.

For example, any variables we put in the DEFAULTS main.yml file will be overwritten anywhere else they are defined. This is because DEFAULTS is the lowest order of precedence for variables. We put in default values here, knowing they can and possibly will be overwritten at some point.

On the other hand, the VARS are the highest level of precedence, aside from extra variables fed into the role at run-time. These can only be overridden by passing variables at the command line or Tower "extra vars" or, by re-declaring them with different values in the playbook itself.

A real-world example might be a role with predefined defaults but a user who wants to overwrite their stored version of the role by adding new variables into vars/main.yml. These new variables will override the role defaults without having to delete or edit that file.

This directory commonly contains files intended to copy to a remote system or an entire directory structure to sync remotely. In the playbook, we can refer to these source files simply as the relative path files/filename (files slash filename)

This is mostly important for GIT communication and publishing to galaxy. The metadata is crucial for ansible galaxy to be able to search and filter on the metadata you include. The README is helpful for users who want to pull your code from a public git source. The README commonly includes examples of a playbook to run your role or specific variables that can / should be overwitten.

TASKS is possibly the most important location. Ansible looks inside tasks/main.yml first to determine what to do in a role. You can have all of your role's tasks in-line or your main.yml can conditionally (or statically) include additional files to separate and extend your tasks for organizational purposes.

Similar to files, this is a directory where your templates are stored. Unlike files, templates likely include a jinja2 syntax or variables inside them to make them dynamically change as they're copyied by Ansible.

INITIALIZING A ROLE

This slide shows an example file system with a top-level playbook (site.yml) and two sample roles (common and apache) embedded in the project. Notice how the file structure under each role are similar to what we find in a play. Role deconstruct the content we'd put in a play and package it up in such a way that it is portable and easily shared and reused.

This slide shows an example file system with a top-level playbook (site.yml) and two sample roles (common and apache) embedded in the project. Notice how the file structure under each role are similar to what we find in a play. Role deconstruct the content we'd put in a play and package it up in such a way that it is portable and easily shared and reused.

This slide shows an example file system with a top-level playbook (site.yml) and two sample roles (common and apache) embedded in the project. Notice how the file structure under each role are similar to what we find in a play. Role deconstruct the content we'd put in a play and package it up in such a way that it is portable and easily shared and reused.

PLAYBOOKS WITH ROLES

This slide shows the site.yml playbook using the roles in our example project. Notice that it is much more concise than what we've seen.

SHARING YOUR CONTENT WITH OTHER TEAMS:

Publishing a catalog of roles

Creating best practices for use of roles

Roles as collaboration

Style guide

Code review

Galaxy or GIT?

requirements.yml and including roles

Let's talk about what they are, how they work, and some of the ways we can use them.

Ansible Galaxy

http://galaxy.ansible.com

Ansible Galaxy is a hub for finding, reusing and sharing Ansible content.

Jump-start your automation project with content contributed and reviewed by the Ansible community.

Ansible is open source. Created with contributions from an active open source community and built for the people who use it every day. At its heart, Ansible was made to help more people experience the power of automation so they could work better and faster together.

Next Steps

It's easy to get startedansible.com/get-started

Join the Ansible communityansible.com/community

Would you like to learn a lot more?redhat.com/en/services/training/do407-automation-ansible