WORKSHOP 7: Roles
Tot nu toe creëerden we playbooks
met meerdere taken erin.
Maar we willen graag deeltaken die we in de playbooks gebruikten liefst hergebruiken in meerdere situaties.
Hiervoor kunnen Ansible roles
gebruikt worden.
Doelstelling
In deze workshop leer je:
- de folder-structuur opbouwen van een
Ansible Role
. - hoe een Ansible Role op te bouwen.
- een Ansible
Play
te maken om eenRole
te gebruiken.
Workshop
Bij een Ansible role
gaan we onze playbook
terug uiteen rafelen in kleinere, herbruikbare stukken en in een aparte mappen-structuur plaatsen. Dit is meer in detail besproken in de online documentatie.
Stap 1 - De Ansible Role-structuur
Roles
volgen een heel bepaalde structuur. De naam van de rol
wordt bepaald door de "bovenste" map (top-level directory). Veel van de onderliggende mappen bevatten YAML
-files met de naam main.yml
.
De bestands- en templates-folders bevatten elementen waarnaar in die YAML-files gerefereerd wordt.
Een voorbeeld-structuur van een role
met de naam apache
ziet er als volgt uit:
roles/
apache/
├── defaults/
│ └── main.yml
├── files/
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── README.md
├── tasks/
│ └── main.yml
├── templates/
├── tests/
│ ├── inventory
│ └── test.yml
└── vars/
└── main.yml
De verschillende main.yml
bestanden bevatten inhoud i.f.v. hun locatie in de mappenstructuur. De vars/main.yml
bevat referenties naar variabelen, de handlers/main.yml
beschrijft de handlers
, enzovoort.
In tegenstelling tot playbooks
bevatten de main.yml
-bestanden enkel de specifieke inhoud en niet de klassieke playbook-informatie zoals hosts
, become
,...
Er zijn eigenlijk 2 mappen voorzien voor variabelen: vars
en default
. "default"-variabelen hebben de laagste prioriteit en bevatten meestal enkel variabelen vastgelegd door de role-auteurs
en zullen meestal overschreven worden door specifiekere waarden, meestal in vars/main.yml
(meer info in de documentatie).
Ansible gaat dus standaard zoeken in elke map binnen de role
naar bestanden met de naam main.yml
.
Gebruik van meerdere rollen samen met hun playbooks organiseer je als volgt:
(Ansible verwacht een map roles
onderliggend aan de playbook(s)
waarin de rollen opgenomen werden)
site.yml # main playbook
webservers.yml # playbook for webserver tier
fooservers.yml # playbook for fooserver tier
roles/
common/ # this hierarchy represents a "role"
tasks/
handlers/
files/
templates/
vars/
defaults/
meta/
webservers/
tasks/
handlers/
files/
...
Roles
gebruiken is vrij eenvoudig aan te geven in een playbook
:
---
- name: launch roles
hosts: web
roles:
- common
- webservers
Voor elke rol hierboven onder roles
zullen de tasks
, de handlers
en de vars
van die rol opgenomen worden.
Elk script, elke template, elke... in de rol kan refereren naar relevante bestanden, templates of taken zonder absolute of relatieve paden!
Ansible zal die bestanden automatisch zoeken in de mappen files
,templates
of tasks
van de respectievelijke rol.
Stap 2 - role
mappen-structuur aanmaken
Zoals eerder gezegd zal Ansible zoeken naar roles
in de submappen van de map roles
van je projectmap.
Elke rol heeft dus zijn eigen mappenstructuur en kunnen we makkelijk automatisch aanmaken met de tool ansible-galaxy
.
Ansible Galaxy website is een centrale plaats waar je verschillende Ansible inhoud kan vinden (typisch "roles" en "collections") om veel gebruikte taken uit te voeren.
-
We bouwen nu eerst een rol die Apache zal installeren en configureren om virtuele sites te hosten.\
-
Voer volgende opdrachten uit in je projectfolder
./ansible-files
:[student@ControlHost ansible-files]$ mkdir roles
[student@ControlHost ansible-files]$ ansible-galaxy init roles/apache_vhost -
Bekijk de folder-structuur die Ansible-galaxy aangemaakt heeft:
[student@ControlHost ansible-files]$ tree roles
roles
└── apache_vhost
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
Stap 3 - het Tasks
-bestand in Roles
Het bestand main.yml
in de folder tasks
van deze rol moet het volgende uitvoeren:
- er voor zorgen dat Apache geïnstalleerd is
- er voor zorgen dat Apache gestart is en dat permanent (na reboots)
- HTML-inhoud voorzien in de Apache root-folder
- de voorziene template installeren om een virtuele host (vhost) te configureren.
Zoals eerder al aangegeven kan de main.yml
enkel tasks
bevatten en géén klassieke playbook-informatie.
-
Pas de inhoud van
roles/apache_vhost/tasks/main.yml
aan:main.yml---
# tasks file for roles/apache_vhost
- name: Install Apache2
ansible.builtin.apt:
name: apache2
state: latest
- name: Start and enable Apache2 service
ansible.builtin.service:
name: apache2
state: started
enabled: trueBovenstaande zorgt nu al voor een correct werkende Apache-installatie!
-
Voeg nog 2 extra taken toe die de vhost mappen-structuur voorzien en html-pagina's kopieert.
main.yml- name: Ensure vhost directory is present
ansible.builtin.file:
path: "/var/www/vhosts/{{ ansible_hostname }}"
state: directory
mode: "655"
- name: Deliver html content
ansible.builtin.copy:
src: web.html
dest: "/var/www/vhosts/{{ ansible_hostname }}/index.html"
mode: "644"Bovenstaande gebruikt de module
file
om de mappen-structuur eventueel aan te maken (zie documentatie). Het bestandweb.html
wordt gekopieerd van de control host naar de juiste locatie op de doelhost.
Het bestandweb.html
wordt verder in deze workshop nog aangemaakt. -
een volgende taak die we nog toevoegen aan deze YAML-file gebruikt de
template
module om devhost
-configuratie van de webserver aan te maken en te kopiëren.main.yml- name: Template vhost file
ansible.builtin.template:
src: vhost.conf.j2
dest: "/etc/apache2/sites-available/{{ ansible_hostname }}.conf"
owner: root
group: root
mode: "644"Ook hier moet de template zelf (
vhost.conf.j2
) nog aangemaakt worden. Dit doen we wat verder in deze workshop. De module kopieert de template over het default bestand000-default.conf
om de vhosts te definiëren. -
Na het toevoegen van een virtuele host aan Apache moet deze "enabled" worden. Dit gebeurt met de
apache-tool
a2ensite
. Zoals je hieronder ziet gebruikt deze deeltaak eenhandler
met de naamRestart_apache2
. De handler wordt ook later aangemaakt. -
De volledige
task
binnen deze rol (tasks/main.yml
) ziet er nu als volgt uit:---
# tasks file for roles/apache_vhost
- name: Install Apache2
ansible.builtin.apt:
name: apache2
state: latest
- name: Start and enable Apache2 service
ansible.builtin.service:
name: apache2
state: started
enabled: true
- name: Ensure vhost directory is present
ansible.builtin.file:
path: "/var/www/vhosts/{{ ansible_hostname }}"
state: directory
mode: "655"
- name: Deliver html content
ansible.builtin.copy:
src: web.html
dest: "/var/www/vhosts/{{ ansible_hostname }}/index.html"
mode: "644"
- name: Template vhost file
ansible.builtin.template:
src: vhost.conf.j2
dest: "/etc/apache2/sites-available/{{ ansible_hostname }}.conf"
owner: root
group: root
mode: "644"
- name: Enable new site
ansible.builtin.shell:
cmd: /usr/sbin/a2ensite {{ ansible_hostname }}
notify:
- Restart_apache2
Stap 4 - De handler
voorzien
In het bestand roles/apache_vhost/handlers/main.yml
maken we de handler
aan die Apache zal herstarten als die aangeroepen wordt door een notify
in de "template"-taak.
---
# handlers file for roles/apache_vhost
- name: Restart_apache2
ansible.builtin.service:
name: apache2
state: restarted
Stap 5 - Voorzie een web.html
bestand en vhost.conf.j2
template
-
Maak een bestand
web.html
aan met de HTML-content voor de webserver in de mapfiles
van de rol:<html>
<head>
<title>Welcome to Apache virtual host!</title>
</head>
<body>
<h1>Success! The virtual host is working!</h1>
</body>
</html> -
Maak een template aan met de naam
vhost.conf.j2
in de maptemplates
van de rol:# {{ ansible_managed }}
<VirtualHost *:80>
ServerAdmin webmaster@{{ ansible_hostname }}
ServerName {{ ansible_hostname }}
ErrorLog ${APACHE_LOG_DIR}/{{ ansible_hostname }}-error.log
CustomLog ${APACHE_LOG_DIR}/{{ ansible_hostname }}-common.log common
DocumentRoot /var/www/vhosts/{{ ansible_hostname }}/
<Directory /var/www/vhosts/{{ ansible_hostname }}/>
Options +Indexes +FollowSymlinks +Includes
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Stap 6 - Test de role
We gaan deze role toepassen op node2
. Maar aangezien we een rol niet rechtstreeks kunnen toewijzen aan een node moeten we eerst een playbook
voorzien waarin we de hosts
en de roles
samenbrengen.
-
Maak een playbook aan met de naam
test_apache_role.yml
in je projectmap:test_apache_role.yml---
- name: Use apache_vhost role playbook
hosts: node2
become: true
pre_tasks:
- name: Pre tasks
ansible.builtin.debug:
msg: 'Beginning web server configuration.'
roles:
- apache_vhost
post_tasks:
- name: Post tasks
ansible.builtin.debug:
msg: 'Web server has been configured.'In bovenstaande zie je 2 nieuwe
keywords
⇒pre_tasks
enpost_tasks
. Normaal gesproken worden de taken van rollen uitgevoerd vóór de taken van een playbook. Om de volgorde van uitvoering te controleren, wordenpre_tasks
uitgevoerd voordat rollen worden toegepast.post_tasks
worden uitgevoerd nadat alle rollen zijn voltooid. Hier gebruiken we ze gewoon om beter te markeren wanneer de daadwerkelijke rol wordt uitgevoerd. -
playbook uitvoeren:
[student@ControlHost ansible-files]$ ansible-playbook test_apache_role.yml
-
Controleer of je op node2 de nieuwe virtuele site kan bekijken:
[student@ControlHost ansible-files]$ ansible node2 -m setup | grep ansible_hostname
"ansible_hostname": "iac-Managed-Host-2",
[student@ControlHost ansible-files]$ ansible node2 -m command -a "curl -s http://iac-Managed-Host-2"
node2 | CHANGED | rc=0 >>
<html>
<head>
<title>Welcome to Apache virtual host!</title>
</head>
<body>
<h1>Success! The virtual host is working!</h1>
</body>
</html>
[student@ControlHost ansible-files]$ -
Controleer het verschil met de default site van je webserver:
[student@ControlHost ansible-files]$ ansible node2 -m command -a "curl -s http://localhost"
Aangezien je nu met virtuele sites (vhosts) werkt zou Apache nu bij bovenstaand commando een andere, eerder geconfigureerde, site moeten tonen.
© Deze workshop werd gebaseerd op de informatie van Red Hat Ansible Automation Platform