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.
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.ymlfile must contain content; some may be unused.
5.2 Hosts (Remote Host List)
The
/etc/ansible/hostsfile 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_userfor 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
.j2extension. 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
-toption.
<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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.