Chapter 3: Implementing an Ansible Playbook
Exercise: Writing and running playbooks
You will write your first real playbook: one play that installs Apache, deploys a web page and starts the service on two hosts. Then you will syntax-check it, run it, run it again to prove it is idempotent, and test the result with curl.
The project directory ~/playbook-basic already contains an ansible.cfg and an inventory with a web group containing serverc.lab.example.com and serverd.lab.example.com. Your playbook, site.yml, must make sure that on every host in web:
| Requirement | Module |
|---|---|
The httpd package is present | ansible.builtin.dnf |
files/index.html is copied to /var/www/html/index.html | ansible.builtin.copy |
The httpd service is started and enabled at boot | ansible.builtin.service |
Writing and running playbooks
- Write a playbook using correct YAML and playbook structure.
- Validate and run it with ansible-navigator run.
Prerequisites: Complete control-node setup and the preceding lessons in this chapter. Run commands as student on workstation unless a step names another machine.
From the project directory, run the relevant home-lab check. For an exercise with several checkpoints, grade each state before changing or removing it:
lab grade playbook-basicThe grader reads project files and host state. A passing report covers the listed checks; also perform the task’s independent connection, repeat-run, and reboot checks where requested.
Change the page content and predict which task changes on each host before rerunning.
Record the published result first. The grader checks the original requirements, so a changed name or value may intentionally fail those checks.
Publish the provided page on both hosts in web using site.yml.
- Apache must be installed, running, and enabled at boot.
- The provided
files/index.htmlmust be available as/var/www/html/index.html. - HTTP requests from workstation must return the page; account for the home-lab firewall.
- A repeat playbook run must leave the desired state unchanged. Explain the difference between a successful playbook run and a reachable web service.
Move into the project directory
[student@workstation ~]$ cd ~/playbook-basic
[student@workstation playbook-basic]$Start the play
Create site.yml. Begin with the document marker, then a play named Install and start Apache HTTPD that targets the web group. hosts must line up with name.
---
- name: Install and start Apache HTTPD
hosts: webAdd the tasks key and the package task
Add tasks: at the same indentation as hosts. Then add the first task, indented further, that uses ansible.builtin.dnf to make sure httpd is present.
tasks:
- name: Ensure httpd package is present
ansible.builtin.dnf:
name: httpd
state: presentAdd the web page task
Match the format of the previous task. Use ansible.builtin.copy with src and dest.
- name: Correct index.html is present
ansible.builtin.copy:
src: files/index.html
dest: /var/www/html/index.htmlAdd the service task
Use ansible.builtin.service so httpd is started now and enabled at boot.
---
- name: Install and start Apache HTTPD
hosts: web
tasks:
- name: Ensure httpd package is present
ansible.builtin.dnf:
name: httpd
state: present
- name: Correct index.html is present
ansible.builtin.copy:
src: files/index.html
dest: /var/www/html/index.html
- name: Ensure httpd is started
ansible.builtin.service:
name: httpd
state: started
enabled: trueCheck the syntax
Fix anything it reports before continuing.
[student@workstation playbook-basic]$ ansible-navigator run \
> -m stdout site.yml --syntax-check
playbook: /home/student/playbook-basic/site.ymlRun the playbook
[student@workstation playbook-basic]$ ansible-navigator run -m stdout site.yml
...output omitted...
PLAY RECAP *********************************************************************
serverc.lab.example.com : ok=4 changed=3 unreachable=0 failed=0 ...
serverd.lab.example.com : ok=4 changed=3 unreachable=0 failed=0 ...Four tasks ran on each host (Gathering Facts plus your three), and all three of yours changed something.
Run it again
This time nothing should change:
PLAY RECAP *********************************************************************
serverc.lab.example.com : ok=4 changed=0 unreachable=0 failed=0 ...
serverd.lab.example.com : ok=4 changed=0 unreachable=0 failed=0 ...Test the web servers
[student@workstation playbook-basic]$ curl serverc.lab.example.com
This is a test page.
[student@workstation playbook-basic]$ curl serverd.lab.example.com
This is a test page.The home-lab servers run firewalld from the first boot, as a standard RHEL installation does, and this playbook never opens the HTTP port. The play itself succeeds; only the test fails. Add a fourth task and run the playbook again:
- name: firewalld permits http service
ansible.posix.firewalld:
service: http
permanent: true
state: enabled
immediate: trueYou meet this module properly in the next sections. A web server that is running but unreachable is almost always this.
Finish
Check your work with lab grade playbook-basic, then put the exercise away with lab finish playbook-basic.