11.1 Event Driven Ansible - Basics
In this lab we are going to learn how to use Event Driven Ansible. For the following tasks, server node1
and node2
act as webservers. You can use Lab 4.0 as a guideline.
Task 1
- Point your webbrowser to the official documentation of
ansible-rulebook
. - Install and configure everything needed to run ansible-rulebook and source plugins.
- Check the version of
ansible-rulebook
Solution Task 1
https://ansible-rulebook.readthedocs.io/en/stable/index.html
Fedora 36+:
1
2
3
4
| sudo dnf --assumeyes install java-17-openjdk python3-pip
export JAVA_HOME=/usr/lib/jvm/jre-17-openjdk
pip install ansible ansible-rulebook
ansible-galaxy collection install ansible.eda
|
Enterprise Linux 9:
1
2
3
4
5
6
7
8
9
10
11
12
13
| sudo dnf install java-17-openjdk
export JAVA_HOME=/usr/lib/jvm/jre-17-openjdk
sudo dnf install python3-pip
python3 -m venv ~/python
. ~/python/bin/activate
pip install --upgrade pip
pip install ansible ansible-rulebook
ansible-galaxy collection install ansible.eda
sudo dnf install systemd-devel gcc python3-devel
pip install -r ~/.ansible/collections/ansible_collections/ansible/eda/requirements.txt
|
1
| ansible-rulebook --version
|
Output on EL9:
1
2
3
4
5
6
| version__ = '1.0.0'
Executable location = /home/ansible/python/bin/ansible-rulebook
Drools_jpy version = 0.3.4
Java home = /usr/lib/jvm/java-17-openjdk-17.0.7.0.7-3.el9.x86_64
Java version = 17.0.7
Python version = 3.9.16 (main, Dec 8 2022, 00:00:00) [GCC 11.3.1 20221121 (Red Hat 11.3.1-4)]
|
Task 2
- Write a playbook
webserver.yml
that installs the servers in group web
as webservers. See Lab 4.0 for guidelines. - Ensure that the playbook also sets a webpage at
/var/www/html/index.html
. - Ensure that the inventory file
hosts
in the folder inventory has the group web
with node1
and node2
as members. - Run the playbook
webserver.yml
and check that the webservers are up and running.
Solution Task 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| ---
- hosts: web
become: true
tasks:
- name: install httpd
ansible.builtin.dnf:
name:
- httpd
- firewalld
state: installed
- name: start and enable httpd
ansible.builtin.service:
name: httpd
state: started
enabled: yes
- name: put default webpage
ansible.builtin.copy:
content: "Ansible Labs by Puzzle ITC"
dest: /var/www/html/index.html
owner: root
group: root
- name: start and enable firewalld
ansible.builtin.service:
name: firewalld
state: started
enabled: yes
- name: open firewall for http
firewalld:
service: http
state: enabled
permanent: yes
immediate: yes
|
1
2
3
4
5
6
| [controller]
control0 ansible_host=<ip-of-control0>
[web]
node1 ansible_host=<ip-of-node1>
node2 ansible_host=<ip-of-node2>
|
1
2
3
4
| ansible-playbook -i inventory/hosts webserver.yml
sudo dnf install -y lynx
lynx http://<ip-of-node1>
lynx http://<ip-of-node2>
|
Task 3
- Write a rulebook
webserver_rulebook.yml
that checks if the webpages on node1
and node2
are up and running. - If the webpages are not available anymore, the
webserver.yml
playbook should be re-run. - Use
url_check
from the ansible.eda
collection as the source plugin in your rulebook. - Check the availability of the websites every 8 seconds.
Note
If you don’t have the ansible.eda
collection installed yet, ansible-rulebook
would start, but fail because the url_check
source plugin cannot be found.Solution Task 3
1
| cat webserver_rulebook.yml
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| ---
- name: rebuild webservers if site down
hosts: web
sources:
- name: check webserver
ansible.eda.url_check:
urls:
- http://<ip-of-node1>:80/
- http://<ip-of-node2>:80/
delay: 8
rules:
- name: check if site down and rebuild
condition: event.url_check.status == "down"
action:
run_playbook:
name: webserver.yml
|
Task 4
- Start
webserver_rulebook.yml
in verbose mode. - Stop the httpd service on
node1
with ansible from another terminal on control0
and see how the playbook webserver.yml
is re-run. (You could also just stop the service directly on node1
.)
Solution Task 4
1
2
3
| ansible-rulebook --rulebook webserver_rulebook.yml -i inventory/hosts --verbose
ansible node1 -i inventory/hosts -b -m service -a "name=httpd state=stopped"
|
Task 5
- Write the rulebook
webhook_rulebook.yml
that opens a webhook on port 5000 of the control node control0
. - The rulebook should re-run the playbook
webserver.yml
if the webhook receives a message matching exactly the string “webservers down”. - Use
webhook
from the ansible.eda
collection as the source plugin in your rulebook.
Solution Task 5
1
| cat webhook_rulebook.yml
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| ---
- name: rebuild webserver if webhook receives message that matches rule condition
hosts: web
sources:
- name: start webhook and listen for messages
ansible.eda.webhook:
host: 0.0.0.0
port: 5000
rules:
- name: rebuild webserver if monitoring tool sends alert
condition: event.payload.message == "webservers down"
action:
run_playbook:
name: webserver.yml
|
Task 6
- Run the rulebook
webhook_rulebook.yml
in verbose mode. - Send the string “webservers running” to the webhook.
- You can do this by issuing:
curl -H 'Content-Type: application/json' -d "{\"message\": \"webservers running\"}" 127.0.0.1:5000/endpoint
- See how the message is received, processed, but no actions are taken since the message doesn’t match the condition defined.
- Now send the message “webservers down” to the webhook. See how the playbook
webserver.yml
is run.
Solution Task 6
1
| ansible-rulebook --rulebook webhook_rulebook.yml -i inventory/hosts --verbose
|
1
| curl -H 'Content-Type: application/json' -d "{\"message\": \"webservers running\"}" 127.0.0.1:5000/endpoint
|
1
| curl -H 'Content-Type: application/json' -d "{\"message\": \"webservers down\"}" 127.0.0.1:5000/endpoint
|
Task 7
- Write the rulebook
complex_rulebook.yml
. It has to meet the following requirements: - It should check for three things:
- check if the website on one of the two webservers is down. (Same as Task 3 above)
- check if the message matches exactly the string “webservers down” (Same as Task 5 above)
- check if the message contains the string “ERROR” or “error”
- If one of the criterias above are met, do two things:
- run the ansible shell module to print the string “WEBSERVER ISSUES, REMEDIATION IN PROGRESS.” into the journald log. (Use the command
systemd-cat echo "WEBSERVER ISSUES, REMEDIATION IN PROGRESS."
) - run playbook
webservers.yml
- Start the rulebook
complex_rulebook.yml
and send the message “webservers down” to the webhook again.
Solution Task 7
1
| cat complex_rulebook.yml
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| ---
- name: rebuild webserver if webhook receives message that matches rule condition
hosts: web
sources:
- name: check webserver
ansible.eda.url_check:
urls:
- http://<ip-of-node1>:80/
- http://<ip-of-node2>:80/
delay: 8
- name: start webhook and listen for messages
ansible.eda.webhook:
host: 0.0.0.0
port: 5000
rules:
- name: rebuild webserver if any source reports an alert
condition:
any:
- event.url_check.status == "down"
- event.payload.message == "webservers down"
- event.payload.message is search("ERROR",ignorecase=true)
actions:
- run_module:
name: ansible.builtin.shell
module_args:
cmd: "systemd-cat echo \"WEBSERVER ISSUES, REMEDIATION IN PROGRESS.\""
- run_playbook:
name: webserver.yml
|
1
| ansible-rulebook --rulebook complex_rulebook.yml -i inventory/hosts --verbose
|
1
| curl -H 'Content-Type: application/json' -d "{\"message\": \"webservers down\"}" 127.0.0.1:5000/endpoint
|
Note, that you would have to open port 5000 on the firewall if the curl command is not sent from the controller itself.
Task 8
Solution Task 8
Event Driven Ansible on Github
All done?