Expert · Ansible fundamentals · topic 47 of 57 · 35 min
Writing and running playbooks
Explanation
From commands to a playbook
Ad-hoc commands are one-off. A playbook saves the whole procedure in a file you can review, run again, and keep in Git. It is the main way to use Ansible.
---
- name: Set up web servers
hosts: webservers
become: true
tasks:
- name: Install Apache
ansible.builtin.dnf:
name: httpd
state: present
- name: Put the home page in place
ansible.builtin.copy:
content: "Welcome to {{ inventory_hostname }}\n"
dest: /var/www/html/index.html
mode: "0644"
- name: Start and enable Apache
ansible.builtin.service:
name: httpd
state: started
enabled: true
- name: Open HTTP in the firewall
ansible.posix.firewalld:
service: http
permanent: true
immediate: true
state: enabledThe structure
- The file is a LIST of plays (each starts with "- name:").
- A play has hosts (a pattern from the inventory), optional settings such as become, and tasks.
- tasks is a list; each task has a name (say what it ensures, in plain words) and exactly one module with its arguments indented under it.
- Tasks run in order, on all hosts of the play in parallel (5 hosts at a time by default; the forks setting).
- {{ inventory_hostname }} is a variable: the host's name from the inventory. Quote any value that starts with {{.
Running it
$ ansible-playbook web.yml --syntax-check
playbook: web.yml
$ ansible-playbook web.yml -C # check mode: report what WOULD change, change nothing
$ ansible-playbook web.yml
PLAY [Set up web servers] ******************************************************
TASK [Gathering Facts] *********************************************************
ok: [web01.example.com]
TASK [Install Apache] **********************************************************
changed: [web01.example.com]
TASK [Put the home page in place] **********************************************
changed: [web01.example.com]
TASK [Start and enable Apache] *************************************************
changed: [web01.example.com]
TASK [Open HTTP in the firewall] ***********************************************
changed: [web01.example.com]
PLAY RECAP *********************************************************************
web01.example.com : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook web.yml # second run
...
web01.example.com : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Useful options: -v (more detail, up to -vvvv for connection debugging), --limit HOST, --list-hosts and --list-tasks (show what would run), --diff (show file changes), --start-at-task "name" (resume). If a task fails on a host, Ansible stops running further tasks on THAT host and carries on with the others.
ansible-navigator
$ ansible-navigator run web.yml -m stdout # output like ansible-playbook
$ ansible-navigator run web.yml # interactive text UI: drill into plays, tasks, hosts
$ ansible-navigator doc ansible.builtin.dnf -m stdoutWhether you use ansible-playbook or ansible-navigator depends on your environment. Red Hat's automation platform and some exam versions expect navigator; check what your workplace or the current exam objectives use, and practise with that one.
Common mistakes
- Indentation: module arguments must be indented under the module name, which is under the task.
- Two modules in one task: "conflicting action statements". Split them into two tasks.
- Writing yes/no and on/off unquoted where text is meant. YAML may turn them into true/false. Use true/false for booleans and quote text.
- Unquoted {{ var }} at the start of a value: YAML reads { as a dictionary. Write "{{ var }}".
- Never reading the recap. changed on the second run means something is not idempotent (often a command or shell task).
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Writing and running playbooks · 1/6
A playbook saves a whole procedure as YAML. It is a list of plays.
Prefer a video by a teacher? Find free videos on “ansible playbook tutorial for beginners rhel” on YouTube ↗
In real life: Standard setup for every new server at an IT services firm
An IT services firm in Pune sets up dozens of client servers a month. Their baseline.yml playbook installs agreed packages, sets the time zone and NTP, creates admin users with keys, hardens SSH and opens only required ports. A new server is ready in ten minutes, and running the same playbook weekly fixes anything someone changed by hand.
- name: Baseline for all servers
hosts: all
become: true
tasks:
- name: Time zone is Asia/Kolkata
community.general.timezone:
name: Asia/Kolkata
- name: Basic tools are installed
ansible.builtin.dnf:
name: [vim-enhanced, tmux, bash-completion, chrony]
state: presentPractice (0/4 done)
Which command checks a playbook for syntax errors without running it?
Which line has the bug? 1: - name: Install chrony 2: ansible.builtin.dnf: 3: name: chrony 4: state: present
Write parse_recap(line) for one PLAY RECAP line like "web01.example.com : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0". Return (host, counts) where counts is a dict of the numbers as ints. Then write needs_attention(lines) that returns the sorted hosts whose failed or unreachable count is above 0.
Write web.yml from this lesson for your lab (use ansible.builtin.dnf, copy and service; add the firewalld task if the ansible.posix collection is installed). Run --syntax-check, -C, a real run, and a second run. Then curl each web server.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Everyday modules and handlersAnsible fundamentals · same module
- Ansible playbooksDevOps: Git, Docker, Kubernetes and CI/CD · Configuration management with Ansible, and YAML
- Variables, facts and registered resultsAnsible in depth
- Ansible: inventory and ad-hoc commandsDevOps: Git, Docker, Kubernetes and CI/CD · Configuration management with Ansible, and YAML
- Roles, collections and ansible-galaxyAnsible in depth
- RHEL System Roles and Ansible VaultAnsible in depth
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does -C do with ansible-playbook?
Answer: Check mode: predict changes without making them
It is a dry run.
A task fails on one host out of ten. What happens by default?
Answer: That host stops; the others continue
Failed hosts are removed from the rest of the play.
Why quote "{{ inventory_hostname }}" at the start of a YAML value?
Answer: YAML would read { as the start of a dictionary
Quote values starting with {{.
In PLAY RECAP, what does changed=0 on a second run show?
Answer: The playbook is idempotent: everything was already correct
Tasks ran and found nothing to fix.
How many modules may one task call?
Answer: One
One module per task.
What does ansible-playbook site.yml --check --diff do?Related
Answer: Shows what would change, with file differences, without changing anything
Check mode is a dry run; diff shows the before and after of files.
From Ansible playbooks
Which magic variable holds the host's name as written in the inventory?Related
Answer: inventory_hostname
inventory_hostname; ansible_facts['hostname'] is what the host reports itself.
Which package gives you ansible-playbook on RHEL 9?Related
What does --become do in an Ansible command?Related
Answer: Runs the task with higher privileges, by default using sudo
become escalates privileges, usually to root via sudo.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Ansible fundamentals” before its exam: Everyday modules and handlers.
- Module 9 exam: Ansible fundamentals · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Ansible in depth. 57 topics left in the course before the final exam.