As we already learn in the other lessons, playbooks are yaml files where we group tasks.
A playbook starts with an hosts mark specifying the hosts to run the playbook to.
# Yaml files usually start with 3 dashes: ---
# It's just a separator.
---
- hosts: web
tasks:
...
In yaml, a playbook is a list of hosts
entries.
- hosts: localhost
tasks:
- name: one or more tasks to be run on localhost
...
- hosts: web
tasks:
- name: followed by tasks to be run on web hostgroup
...
We can even pick a single element in an host group, or add tags
entries to restrict executions
- hosts: db[0]
tags: beware
tasks:
- name: .. and then on the first db node ;)
...
- name: run many tasks...
You can limit execution of a single task on a single host within a group using run_once
.
- hosts: db
tags: beware
tasks:
- name: Only this task is run on one of the db nodes
run_once: yes
- name: Other tasks are run on all nodes!
We can even delegate the execution on a given host (eg. the ansible one)
- hosts: db
tasks:
- name: run this task from the local ansible host
run_once: yes
delegate_to: localhost
shell: |
remove a node from the balancer
In [ ]:
cd /notebooks/exercise-07
When run, a playbook gathers facts about hosts (remember the setup module?).
Gathering facts may be time-consuming, so you can tune it via ansible.cfg or disable it
- hosts: web
gather_facts: no
tasks:
...
We can use the predefined variables too:
In [ ]:
!ansible-playbook debug.yml --tags gather_facts
modify debug.yml to disable fact gathering and use the following cell to test it
In [ ]:
# Test the exercise here
In [ ]:
!ansible-playbook debug.yml --tags hostvars
Answer: they are related to the setup
module output
We can process hostvars using jinja filters (see the facts and variable lesson).
Here is a list of useful filters
Remember: a filter is essentially a function returning a function, like a python lambda.
int_filter = lambda x: int(x)
A more complex filter:
- name: This is a getter
debug:
msg: >
{{ ['host1', 'host2'] |
map('extract', hostvars, ['key1', .. , 'keyN'])
}}
where
hostvars_getter = lambda host: hostvars[host]['key1'][..]['keyN']
You can pipeline filters and test incrementally.
In [ ]:
!ansible-playbook debug.yml --tags filters
In [ ]:
!cat package-user.yml
In [ ]:
!ansible-playbook package-user.yml
In [ ]:
!tree /tmp/fetched/
In [ ]:
!cat files-content.yml
In [ ]:
!ansible-playbook -i inventory files-content.yml
In [ ]:
!cat shell-output-01.yml
In [ ]:
!ansible-playbook shell-output-01.yml
This approach has its limits.
modify shell-output-01.yml so that:
--- START COMMAND: cat /etc/resolv.conf --
nameserver 172.17.0.1
-- END COMMAND: cat /etc/resolv.conf
HINTS:
register
In [ ]:
!ansible-playbook shell-output-02.yml -i ../web
In ansible, shell
and command
calls:
ansible-playbook --check
to avoid accidental modifications.If you know a task is not modifying the host (eg. pgrep, ls) you can set changed_when: no
.
If you want to run a shell|command
task when --check
, disable the check_mode
control.
Here's a full example!
- name: This shell task will not modify the system
shell: |
pgrep -fa tomcat
changed_when: no
check_mode: no
Write the changed-when.yml playbook which:
/tmp/didit.txt
file--check
--check
Does changed_when
changes ansible behavior when a command fails?
In [ ]:
!ansible-playbook --check changed-when.yml
In [ ]:
!ansible-playbook changed-when.yml
Server configuration modules include:
- systemd
- service
- mount
service manages and enables services
- name: Restart httpd
service:
name: httpd
state: restarted
enabled: true
systemd manages and enables services with systemd. It can reload systemd configuration too
- name: Reload docker with new systemd config
systemd:
state: restarted
name: docker
daemon_reload: yes
mount populates entries in /etc/fstab and mounts associate filesystem.
- name: Check if mongod LUN is mounted
register: mongod_on_storage
mount:
path: /var/lib/mongo
src: /dev/sdc
fstype: xfs
state: present # creates an entry in /etc/fstab. `mounted` does the actual mount.
Write the mount-bind.yml playbook which:
/etc/fstab
, eventually creating /mnt/bind
--check
This playbook is expected to fail in this course environment: try to understand why.
In [ ]:
!ansible-playbook --check mount-bind.yml
In [ ]:
!ansible-playbook -v mount-bind.yml
In [ ]: