Operations 15 min read

Master Ansible Playbooks: From Basics to Advanced Automation

This article provides a comprehensive guide to Ansible Playbooks, covering their purpose, how they work, YAML basics, core components, directory structure, hosts, remote users, tasks, variables, templates, handlers, tags, and command‑line usage with practical code examples.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Master Ansible Playbooks: From Basics to Advanced Automation

1. Introduction to Ansible

Ansible Playbooks offer a repeatable, reusable, and simple configuration‑management and multi‑host deployment system, ideal for deploying complex applications. A Playbook is a blueprint for automating IT operations without (or with minimal) human intervention, executed against groups of hosts defined in an inventory.

Playbooks are essentially frameworks—pre‑written code that can be used ad‑hoc or as templates. They are frequently employed to automate infrastructure (e.g., operating systems, Kubernetes), networks, security systems, and developer workflows such as Git.

Using Playbooks, IT staff can program applications, services, servers, or devices without manually creating everything from scratch; the Playbook, its variables, conditions, and tasks can be stored, shared, and reused indefinitely.

A playbook consists of a list of one or more plays.

Each play groups hosts and applies roles defined by tasks, which ultimately invoke Ansible modules.

Playbooks are written in YAML.

2. How Ansible Playbooks Work

Ansible modules perform tasks. Multiple modules can be combined into tasks, and multiple tasks can be combined into plays, forming a Playbook that runs automatically against the hosts in your inventory.

Each module carries metadata that determines when, where, and as which user the task runs. Thousands of modules exist to handle a wide range of IT operations.

3. What Is YAML?

YAML is a human‑readable data‑serialization format often used for configuration files in operations and development, such as Kubernetes manifests, GitLab CI/CD pipelines, Python config files, and JSON‑to‑YAML conversions.

4. Features of YAML

High readability

Good interoperability with scripting languages

Uses native data types of the implementation language

Consistent data model

Easy to implement

Stream‑based processing

Strong expressive power and extensibility

5. Core Components of Ansible Playbooks

Hosts : List of remote machines the play targets.

Tasks : Set of actions to perform.

Variables : Built‑in or custom variables referenced in the Playbook.

Templates : Files processed with Jinja2 to replace variables and add simple logic.

Handlers and notify : Conditional actions triggered by tasks, e.g., service restarts.

Tags : Labels that allow selective execution of specific tasks.

5.1 Project Directory Structure

<code>[root@ayunw ansible-project]# ll
total 28
- rw-r--r--. 1 root root 122 Jul  8 10:14 00_setup.yml
- rw-r--r--. 1 root root  84 Jul  7 14:42 01_publish_ssh_key.yml
- rw-r--r--. 1 root root  78 Jul  8 14:11 02_common.yml
- rw-r--r--. 1 root root  85 Jul  8 10:34 03_install_docker.yml
drwxr-xr-x. 3 root root 124 Jul 11 09:15 files
drwxr-xr-x. 2 root root  80 Jul  8 15:26 inventory
- rw-r--r--. 1 root root 778 Jul  7 15:16 README.md
drwxr-xr-x. 5 root root  57 Jul  7 18:30 roles

[root@ayunw ansible-project]# tree roles/ -L 3
roles/
├── docker
│   ├── defaults
│   │   └── main.yml
│   ├── handlers
│   │   └── main.yml
│   ├── meta
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   ├── daemon.json.j2
│   │   └── docker-ce.repo.j2
│   └── vars
│       └── main.yml
</code>

The directory follows a conventional layout for a Docker installation role, but not every

main.yml

file must contain content; some may be unused.

5.2 Hosts (Remote Host List)

The

/etc/ansible/hosts

file defines host groups used by Playbooks.

<code>[root@ayunw ansible-example]# cat /etc/ansible/hosts
[websrvs]
10.10.108.[30:33]

[dbsrvs]
10.10.108.30

[appsrvs]
10.10.108.[30:33]
</code>

5.3 remote_user (Remote User)

Can be set at the play or task level, optionally using

sudo_user

for privilege escalation.

<code>[root@ayunw ansible-example]# cat demo-playbook.yml
- hosts: dbsrvs
  remote_user: root
  tasks:
    - name: pingtest
      ping:
      remote_user: ayunw
      sudo: yes  # default sudo is root
      sudo_user: root
</code>

5.4 Tasks

Tasks are ordered modules combined to achieve a goal. Each task should have a descriptive

name

. Modules are idempotent, meaning repeated runs produce the same result.

Two task syntax styles are supported:

key=value
key: value

(note the space after the colon)

<code>---
- hosts: dbsrvs
  remote_user: root
  tasks:
    - name: install httpd  # description
      yum: name=httpd   # module call
    - name: start httpd
      service: name=httpd state=started enabled=yes
</code>

5.5 Variables

Variables are typically stored in

roles/vars/main.yml

:

<code>EMQXNAME: emq_perf

DEPEND_PKG:
  - yum-utils
  - device-mapper-persistent-data
  - lvm2
  - bridge-utils

DOCKER_PKG:
  - containerd.io-1.6.6
  - docker-ce-20.10.17
  - docker-ce-cli-20.10.17
</code>

5.6 Templates

Templates use the Jinja2 language and have a

.j2

extension. Example

daemon.json.j2

:

<code>{
    "exec-opts": ["native.cgroupdriver=systemd"],
    "log-driver": "json-file",
    "log-level": "warn",
    "log-opts": {
        "max-size": "1g",
        "max-file": "4"
    },
    "data-root": "/data/docker",
    "storage-driver": "overlay2"
}
</code>

5.7 Handlers and Notify

Handlers are tasks that run only when notified by other tasks, typically used for actions like service restarts after configuration changes.

<code>---
- name: Verify apache installation
  hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
    - name: Ensure apache is at the latest version
      ansible.builtin.yum:
        name: httpd
        state: latest
    - name: Write the apache config file
      ansible.builtin.template:
        src: /srv/httpd.j2
        dest: /etc/httpd.conf
      notify:
        - Restart apache
    - name: Ensure apache is running
      ansible.builtin.service:
        name: httpd
        state: started
  handlers:
    - name: Restart apache
      ansible.builtin.service:
        name: httpd
        state: restarted
</code>

5.8 Tags

Tags can be attached to individual tasks to allow selective execution using the

-t

option.

<code>ansible-playbook -t ayunw install_docker.yml
</code>

6. Ansible-Playbook Command

Basic syntax:

ansible-playbook <filename.yml> [options]

Common options include:

<code>-C --check       # only check what would change, do not execute
--list-hosts      # list target hosts
--limit           # limit execution to specific hosts
-v -vv -vvv       # increase verbosity
</code>

Example execution:

<code>ansible-playbook -C install_httpd.yaml
</code>

Running a simple copy task:

<code>---
- hosts: dbsrvs
  tasks:
    - name: copy multi files
      copy:
        src: "{{ item }}"
        dest: "/etc/yum.repos.d/"
        owner: root
        group: root
        mode: 0644
      with_items:
        - "files/CentOS-Base.repo"
        - "files/epel.repo"
</code>

Executing the playbook produces output showing task results and a final recap.

automationConfiguration ManagementdevopsyamlAnsiblePlaybooks
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.