Learning objectives
By the end of this module, you should be able to:
- Explain play, task and module relationships.
- Write and run a small playbook.
- Use syntax check, check mode and limited targeting before broad execution.
Playbooks are automation blueprints
A play maps a group of hosts to an ordered list of tasks. Each task invokes a module. A playbook can contain one or more plays and is executed with ansible-playbook.
Use descriptive names for plays and tasks. Clear names make output easier to audit and failures easier to locate.
Describe intent, not a transcript
A playbook should model the state you want: package present, configuration deployed, service enabled and started. Avoid converting every manual shell command into a command task when a dedicated module exists.
Use a cautious execution sequence
A practical workflow is syntax-check → list hosts → check mode where supported → one limited host → broader group. Check mode is a simulation and not every module can predict every effect, so it complements rather than replaces testing.
Worked examples
See the idea in practice.
Basic web playbook
- name: Configure web servers
hosts: web
become: true
tasks:
- name: Ensure nginx is installed
ansible.builtin.package:
name: nginx
state: present
- name: Ensure nginx is enabled and running
ansible.builtin.service:
name: nginx
enabled: true
state: started
- hosts chooses the inventory group.
- become requests privilege escalation for tasks in the play.
- Tasks are executed in order.
- FQCN module names make the content source explicit.
Safe pre-run sequence
ansible-playbook -i inventory.ini web.yml --syntax-check
ansible-playbook -i inventory.ini web.yml --list-hosts
ansible-playbook -i inventory.ini web.yml --check --limit web01
ansible-playbook -i inventory.ini web.yml --limit web01
- Validate syntax first.
- Confirm target resolution.
- Simulate on one host where supported.
- Then execute against the canary host.
Hands-on lab
Lab — Build and rerun your first playbook
Goal: Configure nginx on the web group and observe idempotence on a second run.
STEP 1Create web.yml
- name: Configure web servers
hosts: web
become: true
tasks:
- name: Install nginx
ansible.builtin.package:
name: nginx
state: present
- name: Enable and start nginx
ansible.builtin.service:
name: nginx
enabled: true
state: started
STEP 2Validate
ansible-playbook -i inventory.ini web.yml --syntax-check
ansible-playbook -i inventory.ini web.yml --list-hosts
STEP 3Run it
ansible-playbook -i inventory.ini web.yml
STEP 4Run it again
ansible-playbook -i inventory.ini web.yml
Verify
- nginx is installed on each intended host.
- The service is enabled and running.
- The second run normally reports no changes if the desired state is already satisfied.
Expected outcome
- A successful play recap with no unreachable or failed hosts.
- The learner can explain why the second run should be quieter.
If it fails
- If package installation fails, verify repository access and package naming on the managed OS.
- If service management fails, verify the service unit name and init system.
Real-world connectionThe second-run test is a simple but powerful way to expose automation that is not truly idempotent.
Avoid these traps
Common mistakes
- Running a new playbook against the entire fleet before testing a limited host.
- Using vague task names such as 'do config'.
- Assuming --check is a perfect prediction of every module's behaviour.
Knowledge check
Can you explain it without looking back?
Open each answer only after you have tried to answer the question yourself.
1What is a play?
A mapping between a set of managed hosts and an ordered set of tasks.
2Why use --limit on a first production-style run?
To reduce blast radius by testing a controlled subset or canary host.
3What does a clean second run suggest?
That the desired state is already satisfied and the tasks are behaving idempotently.