Mastering Advanced Ansible Playbooks: A Complete Guide (2025)​

Mastering Advanced Ansible Playbooks

Table of Contents

Objectives:

After completing this section, you should be able to write a playbook that uses multiple plays and per-play  privilege escalation and  Effectively use ansible-doc to learn how to use new modules to implement tasks for a play.

Advanced Ansible Playbooks Concept:

A playbook is a YAML file containing a list of one or more plays. Remember that a single play is an ordered list of tasks to execute against hosts selected from the inventory. Therefore, if a playbook contains multiple plays, each play may apply its tasks to a separate set of hosts.

This can be very useful when orchestrating a complex deployment which may involve different tasks on different hosts. You can write a playbook that runs one play against one set of hosts, and when that finishes runs another play against another set of hosts.

Writing a playbook that contains multiple plays is very straightforward. Each play in the playbook is written as a top-level list item in the playbook. Each play is a list item containing the usual play keywords.

The following example shows a simple playbook with two plays. The first play runs against vm2.example.com, and the second play runs against vm3.example.com.

---
  - name: First play
    hosts: vm2.example.com
    tasks:
    - name: First task
      apt:
       name: apache2
       state: present
    - name: Second Task
      service:
       name: apache2
       state: started
       enabled: true
  - name: Second play
    hosts: vm3.example.com
    tasks:
    - name: First Task
      apt:
       name: mysql-server
       state: present

Remote Users And Privilege Escalation In Plays:

Plays can use different remote users or privilege escalation settings for a play than what is specified by the defaults in the configuration file. These are set in the play itself at the same level as the hosts or tasks keywords.

User Attributes:

Tasks in playbooks are normally executed through a network connection to the managed hosts. As with ad hoc commands, the user account used for task execution depends on various keywords in the Ansible configuration file, /etc/ansible/ansible.cfg. The user that runs the tasks can be defined by the remote_user keyword. However, if privilege escalation is enabled, other keywords such as become_user can also have an impact.

If the remote user defined in the Ansible configuration for task execution is not suitable, it can be overridden by using the remote_user keyword within a play.

remote_user: remoteuser

Privilege Escalation Attributes:

Additional keywords are also available to define privilege escalation parameters from within a playbook. The become boolean keyword can be used to enable or disable privilege escalation regardless of how it is defined in the Ansible configuration file. It can take yes or true to enable privilege escalation, or no or false to disable it.

become: true

If privilege escalation is enabled, the become_method keyword can be used to define the privilege escalation method to use during a specific play. The example below specifies that sudo be used for privilege escalation.

become_method: sudo

Additionally, with privilege escalation enabled, the become_user keyword can define the user account to use for privilege escalation within the context of a specific play.

become_user: privileged_user

The following example demonstrates the use of these keywords in a play:

name: /etc/hosts is up to date

  hosts: vm2.example.com

  remote_user: gautam

  become: yes

  tasks:

  name: vm2.example.com in /etc/hosts

    lineinfile:

      path: /etc/hosts

      line: ‘192.168.56.12 vm2.example.com vm2’

      state: present

Finding Module For Tasks:

Module Documentation:

Ansible public documentation URL is https://docs.ansible.com . 
The Module Index on the website is an easy way to browse the list of modules shipped with Ansible. For example, modules for user and service management can be found under Systems Modules and modules for database administration can be found under Database Modules.

For each module, the Ansible documentation website provides a summary of its functions and instructions on how each specific function can be invoked with options to the module.

The documentation also provides useful examples that show you how to use each module and how to set their keywords in a task.
To see a list of the modules available on a control node, run the ansible-doc -l command. This displays a list of module names and a synopsis of their functions.

[student@workstation modules]$ ansible-doc -l
a10_server        Manage A10 Networks ... devices' server object.
a10_server_axapi3 Manage A10 Networks ... devices
zfs_facts         Gather facts about ZFS datasets.
znode             Create, ... and update znodes using ZooKeeper
zpool_facts  Gather facts about ZFS pools.
zypper Manage packages on SUSE and openSUSE
zypper_repository Add and remove Zypper repositories

Use the ansible-doc [module name] command to display detailed documentation for a module.

The following example shows the documentation displayed for the yum module.

Gautams-MacBook-Pro:~ gautamkumar$ ansible-doc yum
> ANSIBLE.BUILTIN.YUM    (/opt/homebrew/Cellar/ansible@9/9.13.0/libexec/lib/python3.12/site-packages/ansible/modules/y>
        Installs, upgrade, downgrades, removes, and lists packages and groups with the `yum'
        package manager. This module only works on Python 2. If you require Python 3 support
        see the [ansible.builtin.dnf] module.
ADDED IN: historical
  * note: This module has a corresponding action plugin.
OPTIONS (= is mandatory):
- allow_downgrade
        Specify if the named package and version is allowed to downgrade a maybe already
        installed higher version of that package. Note that setting allow_downgrade=True can
        make this module behave in a non-idempotent way. The task could end up with a set of

The ansible-doc command also offers the -s option, which produces example output that can serve as a model for how to use a particular module in a playbook. This output can serve as a starter template, which can be included in a playbook to implement the module for task execution.
Comments are included in the output to remind administrators of the use of each option. The following example shows this output for the yum module.

Gautams-MacBook-Pro:~ gautamkumar$ ansible-doc -s yum
- name: Manages packages with the `yum' package manager
yum: allow_downgrade: # Specify if the named package .. autoremove: # If `yes', removes all "leaf" packages ... bugfix: # If set to `yes', ... conf_file:  # The remote yum configuration file ..

Module Maintenance:

Ansible comes with many modules, which are small programs that perform specific tasks (like managing files, users, or services). Each module is developed and maintained by someone in the Ansible community.

You can use the command ansible-doc <module_name> to see details about a module.
At the end of that output, you’ll find a METADATA section and It tells you:

  1. Who maintains the module

  2. What its development status is

The status field records the development status of the module:

• stableinterface: The module’s keywords are stable, and every effort will be made not to remove keywords or change their meaning.

• preview: The module is in technology preview, and might be unstable, its keywords might change, or it might require libraries or web services that are themselves subject to incompatible changes.

• deprecated: The module is deprecated, and will no longer be available in some future release.

• removed: The module has been removed from the release, but a stub exists for documentation purposes to help former users migrate to new modules.

The supported_by field records who maintains the module in the upstream Ansible community.

Possible values are:

core: Maintained by the “core” Ansible developers upstream, and always included with Ansible.

curated: Modules submitted and maintained by partners or companies in the community.

For some module if you run ansible-doc <module-name> , it won’t show you who developed or maintains the module because module  has moved into a collection.  For example Starting with Ansible 2.11, the yum module (and others like dnf, apt, etc.) was moved into a collection called: ansible.builtin and you can see meta data details under ansible-doc ansible.builtin.yum. These modules are part of ansible-core, which is developed and maintained entirely by the official Ansible Core TeamBecause they’re built-in, the documentation no longer show supported_by and status Metadata But you can see AUTHOR name shows who originally wrote or contributed to the module.

IMPORTANT:

Use the ansible-doc command to find and learn how to use modules for your tasks. When possible, try to avoid the command, shell, and raw modules in playbooks, even though they might seem simple to use. Because these take arbitrary commands, it is very easy to write non-idempotent playbooks with these modules. For example, the following task using the shell module is not idempotent. Every time the play is run, it rewrites /etc/resolv.conf even if it already consists of the line nameserver 192.0.2.1.

– name: Non-idempotent approach with shell module
  shell: echo “nameserver 192.0.2.1” > /etc/resolv.conf

There are several ways to write tasks using the shell module idempotently, and sometimes making those changes and using shell is the best approach. A quicker solution may be to use ansible-doc to discover the copy module and use that to get the desired effect.

The following example does not rewrite the /etc/resolv.conf file if it already consists of the correct content:

- name: Idempotent approach with copy module
  copy:
   dest: /etc/resolv.conf
   content: "nameserver 192.0.2.1\n"

The copy module tests to see if the state has already been met, and if so, it makes no changes. The shell module allows a lot of flexibility, but also requires more attention to ensure that it runs idempotently.

Idempotent playbooks can be run repeatedly to ensure systems are in a particular state without disrupting those systems if they already are.

Playbook Syntax Variations:

The last part of this chapter investigates some variations of YAML or Ansible Playbook syntax that you might encounter.

YAML Comments:

In YAML, everything to the right of the hash symbol (#) is a comment.
If there is content to the left of the comment, precede the number symbol with a space.

# This is a YAML comment
some data # This is also a YAML comment
YAML Strings:

Strings in YAML do not normally need to be put in quotation marks even if there are spaces contained in the string. You can enclose strings in either double quotes or single quotes.

this is a string
'this is another string'
"this is yet another a string"

There are two ways to write multiline strings. You can use the vertical bar (|) character to denote that newline characters within the string are to be preserved.

include_newlines: |
Example Company
123 Main Street
Atlanta, GA 30303

You can also write multiline strings using the greater-than (>) character to indicate that newline characters are to be converted to spaces and that leading white spaces in the lines are to be removed. This method is often used to break long strings at space characters so that they can span multiple lines for better readability.

fold_newlines: >
This is an example
of a long string,
that will become
a single sentence once folded.
YAML Dictionaries:

You have seen collections of key-value pairs written as an indented block, as follows:

name: svcrole
svcservice: httpd
svcport: 80

Dictionaries can also be written in an inline block format enclosed in curly braces, as follows:

{name: svcrole, svcservice: httpd, svcport: 80}

In most cases the inline block format should be avoided because it is harder to read. 

YAML Lists:

You have also seen lists written with the normal single-dash syntax:

hosts:
- servera
- serverb
- serverc

Lists also have an inline format enclosed in square braces, as follows:

hosts: [servera, serverb, serverc]

You should avoid this syntax because it is usually harder to read.

Obsolete key=value Playbook Shorthand:

Some playbooks might use an older shorthand method to define tasks by putting the key-value pairs for the module on the same line as the module name. For example, you might see this syntax:

tasks:
- name: shorthand form
service: name=httpd enabled=true state=started

Normally you would write the same task as follows:

tasks:
- name: normal form
service:
name: httpd
enabled: true
state: started

You should generally avoid the shorthand form and use the normal form.

The normal form has more lines, but it is easier to work with. The task’s keywords are stacked vertically and easier to differentiate. Your eyes can run straight down the play with less left-to-right motion. Also, the normal syntax is native YAML; the shorthand form is not. Syntax highlighting tools in modern text editors can help you more effectively if you use the normal format than if you use the shorthand format. You might see this syntax in documentation and older playbooks from other people, and the syntax does still function.

You can also visit ansible official website https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html to know more about Ansible playbook.

You can also visit my official website https://linuxgktech.com/ansible/to know more about Ansible concept.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top