↓ Naar de hoofdinhoud gaan

Ansible Commando's

·4864 woorden·23 mins
Inhoudsopgave

Ad-hoc-commando’s
#

Ansible ad-hoc-commando’s zijn eenmalige commando’s die op een of meer externe machines worden uitgevoerd, zonder dat daarvoor een volledig playbook hoeft te worden gemaakt. Deze commando’s worden uitgevoerd met het ansible-commando, gevolgd door een doelhost of -groep, en een module met bijbehorende argumenten.

Ad-hoc-commando’s worden doorgaans gebruikt om snel en eenvoudig eenvoudige taken uit te voeren, maar ze kunnen ook worden ingezet om informatie over externe machines te verzamelen, updates en onderhoud uit te voeren, en nog veel meer.

Het is belangrijk op te merken dat bij ad-hoc-commando’s een groot risico op menselijke fouten bestaat; ze worden daarom niet aanbevolen voor complexe taken of taken die herhaalbaar moeten zijn.

De basissyntaxis van een ad-hoc-commando ziet er als volgt uit:

ansible <hostname/groep> -m <module> -a <module-argumenten>
  • hostname/groep: De doelhost of groep hosts waarop het commando wordt uitgevoerd.
  • -m module: De uit te voeren module. Ansible beschikt over een breed scala aan ingebouwde modules voor uiteenlopende taken, zoals bestandsbeheer, pakketbeheer, servicebeheer, enzovoort.
  • -a module-argumenten: De argumenten die aan de module worden meegegeven. Deze argumenten variëren afhankelijk van de module die wordt uitgevoerd. Dit is een optionele parameter.

Voorbeelden
#

Het volgende commando dient als voorbeeld:

ansible all -m ping

In dit voorbeeld wordt de ping-module gebruikt om de connectiviteit met alle servers in het inventory-bestand te controleren. De optie -m geeft aan welke module moet worden gebruikt; in dit geval is dat de ping-module. Omdat er bij ping geen argumenten hoeven te worden meegegeven, is de optie -a niet nodig. Laten we nog een voorbeeld bekijken:

ansible all -m shell -a '/bin/echo hello'

Dit commando gebruikt de shell-module om het commando ’/bin/echo hello’ uit te voeren op alle servers in het inventory-bestand; dit resulteert in de uitvoer ‘hello’ op alle servers.

Herinner je je de ‘Ansible Facts’ waar we het over hadden nog? Je kunt alle details over een host (of dat nu je localhost of een doelhost is) opvragen met dit commando:

ansible -m setup <target>

Dit commando toont alle standaardparameters die Ansible verzamelt over de doelhost.

Om ‘Facts’ over je Ansible-controller te verzamelen, voer je het volgende commando uit:

ansible -m setup localhost

Je krijgt dan een uitvoer te zien die er ongeveer zo uitziet:

ansible

Praktische toepassingen
#

Probleemoplossing (troubleshooting)
#

Een collega kan je vragen om snel de status van een service op specifieke servers te controleren. Bijvoorbeeld: “Kun je even kijken of de webserver op server X, Y en Z draait?”

Dit is een eenvoudige taak waarvoor geen gedetailleerd plan of uitgebreide instructies nodig zijn; dit is vergelijkbaar met hoe een ad-hoc-commando in Ansible wordt gebruikt om snel en eenvoudig een simpele taak uit te voeren.

Hiervoor kun je het volgende commando gebruiken:

ansible web-server -m shell -a 'systemctl status apache2'

Gebruikers aanmaken
#

Om een ​​gebruiker aan te maken met een ad-hoc-commando, moet je eerst het wachtwoord hashen. Dit kan met het commando mkpasswd. Voer vervolgens het volgende commando uit:

ansible all -m user -a 'name=<NAME-OF-USER> password="<HASHED-PW-OF-MKPASSWD>"' -k -b -K

Een praktisch voorbeeld hiervan is:

ansible all -m user -a 'name=james password="$y$j9T$pKYQTlln/gQtf.YQffQZ.1$E0.mDXGMPBI3qbTyxZ3sHoNoAniyxsuS2Wmoc4y5I83"' -k -b -K

Dit is een Ansible-commando dat wordt gebruikt om een ​​gebruiker genaamd “james” met een specifiek wachtwoord aan te maken op alle doelmachines die in de Ansible-inventory zijn opgegeven. Hier volgt een uitleg van de verschillende opties en vlaggen (flags) die in dit commando worden gebruikt:

  • ansible: Dit is het commando om Ansible uit te voeren, gevolgd door de lijst met doelmachines waarop het commando moet draaien (in dit geval betekent “all” alle machines in de inventory).
  • -m user: Hiermee wordt de te gebruiken module opgegeven; in dit geval is dat de “user"-module. De “user”-module wordt gebruikt om gebruikers op doelmachines te beheren.
  • -a ’name=james password="<hashed password>”’: Dit is het argument voor de “user”-module. Hiermee worden de parameters opgegeven voor het aanmaken van de gebruiker “james”. De parameters omvatten de naam en het wachtwoord van de gebruiker. Het wachtwoord is een gehashte tekenreeks (hash), en daarom staat het tussen aanhalingstekens.
  • -k: Hiermee wordt de gebruiker gevraagd om een ​​wachtwoord in te voeren voor authenticatie bij de doelmachines.
  • -b: Hiermee wordt aangegeven dat de gebruiker met beheerdersrechten moet worden aangemaakt op de doelmachines.
  • -K: Hiermee wordt de gebruiker gevraagd om het sudo-wachtwoord voor de doelmachines in te voeren, aangezien er beheerdersrechten nodig zijn om een ​​nieuwe gebruiker aan te maken. # Uw eerste ad-hocverbinding tot stand brengen

In dit voorbeeld doorlopen we stap voor stap hoe u een host aan uw inventory-bestand toevoegt en een “ping”-test uitvoert naar de doelhost.

Dit is geen ICMP-gebaseerde ping, maar een SSH-verbindingstest.

Een host aanmaken in onze inventory
#

Het standaard inventory-bestand bevindt zich in de volgende map: /etc/ansible/

Dit bestand heet ‘hosts’. Laten we het bewerken!

sudo nano /etc/ansible/hosts

Merk op dat we dit met sudo-rechten doen, aangezien onze standaardgebruiker geen schrijfrechten heeft voor dit bestand.

Laten we een host genaamd ‘KASM’ toevoegen.

[TMLab]
kasm ansible_host=192.168.1.1 ansible_user=davy.cavens ansible_password=DavysSecretPassword ansible_become_password=DavysSecretRootPassword

Laten we dit stap voor stap doornemen:

  • \[TMLab\]: Dit geeft een groep aan in het inventory-bestand. Deze groep heet TMLab. Als we later meer hosts toevoegen, kunnen we op alle hosts tegelijkertijd commando’s uitvoeren door de groepsnaam te gebruiken.
  • De volgende regel bevat verschillende parameters; we zullen deze stuk voor stuk uitleggen.
  • kasm: dit is een label/alias die we aan de host toevoegen om deze eenvoudig te kunnen aanspreken. Deze naam mag geen koppelteken (-) bevatten, maar wel underscores ( _ ).
  • ansible_host=192.168.1.1: Deze parameter vertelt Ansible met welk IP-adres verbinding moet worden gemaakt om de doelhost te bereiken.
  • ansible_user=davy.cavens: Deze parameter stelt de gebruikersnaam in die Ansible gebruikt bij het opzetten van de verbinding.
  • ansible_password=DavysSecretPassword: Deze parameter stelt het wachtwoord in dat wordt gebruikt om verbinding te maken met de host. Dit kan ook een SSH-sleutelpaar zijn, maar in dit voorbeeld gebruiken we een wachtwoord. - ansible_become_password: dit is het wachtwoord dat wordt gebruikt wanneer een taak als root wordt uitgevoerd.

Zo, we zijn klaar met het inventory-bestand! Sla het bestand op en sluit het af (als je nano gebruikt: druk op CTRL + C en sla het bestand onder dezelfde naam op wanneer daarom wordt gevraagd).

We kunnen nu ons eerste ad-hoccommando testen.

Verbinding maken met de host
#

Voer het volgende commando in om verbinding te maken met de host:

ansible kasm -m ping

Laten we dit even ontleden:

  • ansible: dit is het commando dat wordt gebruikt om ad-hoccommando’s uit te voeren.
  • kasm: dit is de naam van ons doel (zie het inventory-bestand dat we zojuist hebben bewerkt).
  • -m ping: hiermee geven we aan Ansible door welke module we op de host willen gebruiken; we gebruiken hier de module ‘ping’. Zoals eerder vermeld, voert dit een SSH-verbindingstest uit.

Verwachte uitvoer:
#

Als alles goed gaat en de host bereikbaar is (en je de juiste parameters hebt ingevoerd), zou je de volgende uitvoer moeten zien:

ansible

Ansible Facts
#

Wat zijn Ansible Facts? ‘Facts’ in Ansible zijn systeemspecifieke gegevens die worden verzameld van beheerde nodes. Deze informatie wordt opgeslagen in variabelen die Ansible kan uitlezen en gebruiken in playbooks.

Hoe verzamel je facts? Wanneer je een playbook uitvoert, verzamelt Ansible standaard facts over de externe host met behulp van de setup-module.

---
- hosts: all
tasks:
- debug:
var: ansible_distribution

Bij het uitvoeren van dit playbook wordt de naam van de distributie (zoals Ubuntu, CentOS, enz.) van de beheerde node weergegeven. Enkele veelvoorkomende ‘facts’ zijn:

  • ansible_os_family: De OS-familie (zoals RedHat, Debian)
  • ansible_distribution: De naam van de distributie (zoals CentOS, Ubuntu)
  • ansible_distribution_version: De specifieke versie van de distributie
  • ansible_interfaces: Lijst met netwerkinterfaces

Je kunt de volledige lijst met ‘facts’ ophalen met het volgende commando:

ansible all -m setup

Dit commando toont de ‘facts’ die zijn verzameld voor alle hosts die in je inventory-bestand staan ​​vermeld.

De uitvoer ziet er ongeveer zo uit als in het onderstaande voorbeeld:

ansible

Overzicht van playbooks
#

Stel dat je meerdere acties tegelijkertijd op meerdere systemen wilt uitvoeren. Je zou een ad-hoc commando kunnen gebruiken en je op meerdere hosts richten… maar zou het niet veel eenvoudiger zijn om een ​​reeks commando’s in één bestand te combineren en deze op zoveel doelen als je wilt uit te voeren… allemaal tegelijk?!

Zoek niet verder! Een Ansible-playbook is een set instructies in YAML-formaat die een reeks taken en de volgorde waarin ze moeten worden uitgevoerd op een of meer externe hosts definieert. Met playbooks kun je repetitieve taken automatiseren, zoals serverconfiguratie, software-installatie en applicatie-deployment. Ze bieden ook een manier om de gewenste status van een systeem te beheren en ervoor te zorgen dat die status in de loop van de tijd behouden blijft.

Wacht even… YAML?!
#

YAML staat voor “YAML Ain’t Markup Language” en is een voor mensen leesbaar formaat voor dataserialisatie. Het wordt vaak gebruikt bij softwareontwikkeling en configuratiebeheer voor het opslaan en uitwisselen van gegevens. Het is zo ontworpen dat het gemakkelijk te lezen en te schrijven is voor mensen, en eenvoudig te verwerken (parsen) door machines.

YAML is een tekstformaat dat inspringing gebruikt (spaties, GEEN tabs!) en speciale tekens om de structuur van de gegevens aan te geven. Het wordt vaak gebruikt om complexe datastructuren weer te geven, zoals lijsten, dictionaries en geneste structuren. Hier zijn enkele basisconcepten van YAML:

  • Datatypen: YAML ondersteunt diverse datatypen, waaronder strings (tekstreeksen), getallen, booleans en null-waarden. Strings kunnen tussen aanhalingstekens staan ​​of zonder aanhalingstekens worden geschreven als ze geen speciale tekens bevatten. Getallen kunnen worden geschreven in decimale, hexadecimale of wetenschappelijke notatie.
  • Lijsten: Lijsten in YAML worden aangegeven met een koppelteken (-) gevolgd door een spatie; elk item in de lijst springt in. Bijvoorbeeld:
- item 1
- item 2
- item 3
  • Dictionaries: Dictionaries in YAML worden weergegeven als sleutel-waardeparen, gescheiden door een dubbele punt ( : ) en ingesprongen. Bijvoorbeeld:
key1: value1
key2: value2
key3: value3
  • Commentaar: Commentaar in YAML begint met het teken # en loopt door tot het einde van de regel. Commentaar wordt door de parser genegeerd en kan worden gebruikt voor uitleg of context.
  • Meerregelige strings: YAML maakt het mogelijk dat strings over meerdere regels lopen door gebruik te maken van het teken |. Bijvoorbeeld:
long_string: | 
Dit is een lange string
die over meerdere regels loopt
zonder speciale tekens.

Structuur van een playbook
#

De structuur van een Ansible-playbook ziet er als volgt uit:

  • Name: Een (voor mensen leesbare) naam voor het playbook.
  • Hosts: De lijst met hosts of groepen hosts waarop het playbook gericht moet zijn. - Variabelen: Alle variabelen die nodig zijn voor de taken die in het playbook zijn gedefinieerd. Deze kunnen inline, in een apart variabelenbestand of in een inventory-bestand worden gedefinieerd.
  • Taken (Tasks): De lijst met taken die op de doelhosts moeten worden uitgevoerd. Elke taak definieert een reeks acties die op de hosts moeten worden uitgevoerd.
  • Handlers: Handlers zijn vergelijkbaar met taken, maar worden alleen geactiveerd wanneer ze door een andere taak worden aangeroepen (via een notificatie). Ze worden doorgaans gebruikt om een ​​service te herstarten of een configuratiebestand opnieuw te laden nadat dit is gewijzigd.
  • Rollen (Roles): Een verzameling taken, handlers en variabelen die is georganiseerd als een herbruikbaar geheel en in meerdere playbooks kan worden opgenomen.
  • Includes: Hiermee kan het ene playbook een ander playbook of een takenlijst opnemen. Dit kan worden gebruikt om grote playbooks op te splitsen in kleinere, beter beheersbare delen.

De basisopzet van de structuur is als volgt:

---
- name: Example playbook
hosts: target_hosts
vars:
variable1: value1
variable2: value2
tasks:
- name: Task 1
<task_definition>
- name: Task 2
<task_definition>
handlers:
- name: Handler 1
<handler_definition>
- name: Handler 2
<handler_definition>

In dit voorbeeld heeft het playbook de naam “Example playbook” en is het gericht op de hosts die in de groep “target_hosts” zijn gedefinieerd. Het definieert twee variabelen, “variable1” en “variable2”, en bevat twee taken en twee handlers. Elke taak en handler krijgt een naam voor eenvoudige identificatie, en de definities staan ​​eronder vermeld.

In een Ansible-playbook zijn diverse elementen optioneel. Dit zijn onder andere:

  • Variabelen: Playbooks kunnen worden uitgevoerd zonder dat er variabelen worden gedefinieerd. Variabelen worden echter vaak gebruikt om waarden vast te leggen die door de taken worden gebruikt; ze maken het playbook flexibeler en herbruikbaarder.
  • Handlers: Handlers zijn optioneel; niet elk playbook heeft ze nodig. Handlers worden gebruikt om op specifieke gebeurtenissen te reageren; als er geen gebeurtenissen zijn die een reactie vereisen, kunnen handlers worden weggelaten.
  • Roles: Roles zijn optioneel en worden gebruikt om taken en handlers te organiseren in herbruikbare modules. Als een playbook geen hergebruik van een set taken en handlers vereist, kunnen roles worden weggelaten.
  • Includes: Includes zijn optioneel; een playbook kan worden uitgevoerd zonder extra playbooks of takenlijsten te includen. Includes worden gebruikt om grote playbooks op te splitsen in kleinere, beter beheersbare delen.

Het playbook uitvoeren
#

Zodra het YAML-bestand met alle relevante taken is aangemaakt, kun je het playbook uitvoeren. Dit doe je met het volgende commando:

ansible-playbook <pad naar playbook .yml-bestand>

Voorbeeld-playbook (Debian)
#

Laten we eens een pakket installeren! In dit voorbeeld maken we een playbook aan met de naam ‘apache-playbook.yml’

  1. 1

    Maak een nieuw bestand aan met nano of vi:

    nano apache-playbook.yml
  2. 2

    Voer de volgende inhoud in het bestand in:

    ---
    - name: Install and start Apache
    hosts: webserver
    become: true
    tasks:
    - name: Install Apache
    apt:
    name: apache2
    state: present
    - name: Start Apache
    service:
    name: apache2
    state: started

    Dit playbook gaat ervan uit dat er een groep hosts of een specifieke host met de naam ‘webserver’ beschikbaar is. Aan dit playbook is de naam “Install and start Apache” gegeven en het is gericht op een groep hosts genaamd “webserver”. Om iets op een Linux-host te installeren, heb je verhoogde rechten (oftewel root-rechten) nodig. Het trefwoord become is ingesteld op true om aan te geven dat de taken moeten worden uitgevoerd met verhoogde rechten (bijv. uitgevoerd als root).

    • De eerste taak, “Install Apache”, gebruikt de apt-module om het Apache-pakket te installeren met behulp van de parameters name en state. De parameter name specificeert het te installeren pakket en de parameter state geeft aan of het pakket aanwezig (present), afwezig (absent) of bijgewerkt (updated) moet zijn.
    • De tweede taak, “Start Apache”, gebruikt de service-module om de Apache-service te starten met behulp van de parameters name en state. De parameter name specificeert de naam van de te starten service en de parameter state geeft aan of de service gestart, gestopt of opnieuw gestart moet worden.

    Stel dat we een pakket willen verwijderen, dan kunnen we een taak als volgt definiëren:

    - name: Install Apache
    apt:
    name: apache2
    state: absent

    ‘Absent’ betekent dat het pakket (indien aanwezig) van het systeem wordt verwijderd.

    Als we willen controleren of het pakket is bijgewerkt naar de nieuwste versie, kunnen we de status “updated” gebruiken:

    - name: Install Apache
    apt:
    name: apache2
    state: updated
  3. 3

    Sla het bestand op.

  4. 4

    Het playbook kan worden uitgevoerd met het volgende commando (ervan uitgaande dat je je in dezelfde map bevindt als het yaml-bestand):

    ansible-playbook apache-playbook.yml

Voorbeeld-playbook (CentOS / RHEL)
#

Waar de apt-module wordt gebruikt voor pakketbeheer op Debian-gebaseerde systemen, wordt de yum-module gebruikt voor pakketbeheer op Red Hat-gebaseerde systemen, zoals CentOS en Fedora. Hier zijn enkele voorbeelden van het gebruik van de yum-module in Ansible-playbooks:

Een pakket installeren met yum:

- name: Install the Apache web server
yum:
name: httpd
state: present

In dit voorbeeld wordt de yum-module gebruikt om het httpd-pakket (de Apache-webserver) te installeren en wordt de status ingesteld op present. Dit betekent dat de yum-module ervoor zorgt dat het httpd-pakket op het systeem wordt geïnstalleerd.

Een pakket verwijderen met yum:

- name: Remove the Apache web server
yum:
name: httpd
state: absent

In dit voorbeeld wordt de yum-module gebruikt om het httpd-pakket (de Apache-webserver) te verwijderen en wordt de status ingesteld op absent. Dit betekent dat de yum-module ervoor zorgt dat het httpd-pakket van het systeem wordt verwijderd.

Een pakket bijwerken met yum:

- name: Update the Apache web server
yum:
name: httpd
state: latest

In dit voorbeeld wordt de yum-module gebruikt om het httpd-pakket (de Apache-webserver) bij te werken en wordt de status ingesteld op latest. Dit betekent dat de yum-module ervoor zorgt dat de nieuwste versie van het httpd-pakket op het systeem wordt geïnstalleerd.

Zoals je ziet, is de syntaxis identiek aan die van de APT-module. Let altijd goed op naar welke Linux-distributie je pakketten pusht!

Variabelen in playbooks
#

Laten we het nu hebben over variabelen. Variabelen in Ansible-playbooks worden gebruikt om waarden op te slaan die in meerdere taken kunnen worden hergebruikt, of om taken flexibeler en aanpasbaarder te maken. Hier is een voorbeeld van een playbook dat gebruikmaakt van variabelen:

---
- name: Hello World
hosts: localhost
vars:
hello_there: "Hello, world!" 
tasks:
- name: show variable
debug:
var: hello_there

In dit voorbeeld wordt de debug-module gebruikt om de waarde van de variabele hello_there weer te geven. Wanneer het playbook wordt uitgevoerd, toont de uitvoer de inhoud van de variabele:

TASK [Debug my_variable] *********************************************************************
ok: [localhost] => {
"my_variable": "Hello, world!"
}

Een ander voorbeeld is het volgende:

---
- name: Install and configure nginx
hosts: webserver
become: true
vars:
nginx_version: "1.21.0"
nginx_config_path: "/etc/nginx/nginx.conf"
tasks:
- name: Install nginx
apt:
name: nginx={{ nginx_version }}
state: present
- name: Copy nginx configuration file
copy:
src: files/nginx.conf
dest: "{{ nginx_config_path }}"

In dit playbook definiëren we twee variabelen: nginx_version en nginx_config_path. De variabele nginx_version bepaalt welke versie van nginx moet worden geïnstalleerd, en de variabele nginx_config_path geeft het pad aan waarheen het nginx-configuratiebestand moet worden gekopieerd.

In de eerste taak, “Install nginx”, wordt de apt-module gebruikt om nginx te installeren, en wordt de variabele nginx_version gebruikt om de te installeren versie op te geven.

In de tweede taak, “Copy nginx configuration file”, wordt de copy-module gebruikt om een ​​configuratiebestand van de lokale machine naar de externe host te kopiëren, en wordt de variabele nginx_config_path gebruikt om het doelpad voor het bestand op te geven.

Een voorbeeld voor een Cisco-switch:

---
- hosts: switches
vars:
vlan_id: 20
vlan_name: Ansible_VLAN

tasks:
- name: Ensure Fa2/0/5 is configured for access vlan 20
cisco.ios.ios_l2_interface:
name: FastEthernet2/0/5
mode: access
access_vlan: { { vlan_id } }

Dit playbook maakt verbinding met een switch en configureert VLAN 20 op poort fa2/0/5. Ook wordt de poort in de ‘access’-modus gezet. Mooi, toch?

Handlers
#

Handlers zijn speciale soorten taken die alleen worden geactiveerd wanneer ze door een andere taak worden aangestuurd (via een ’notification’). Met andere woorden: ze worden één keer uitgevoerd, nadat alle taken in een bepaalde ‘play’ zijn voltooid, maar alleen als ze door een andere taak zijn aangestuurd of ‘genotificeerd’.

Handlers worden vaak gebruikt voor taken die moeten worden uitgevoerd als gevolg van een wijziging. Een typisch voorbeeld is het herstarten van een service nadat het bijbehorende configuratiebestand is aangepast.

Hier volgt een basisuitleg van de werking van handlers:

  1. Notificatiemechanisme: Wanneer een taak de status van een systeem wijzigt (bijv. door een configuratiebestand aan te passen), kan deze een handler ’notificeren’ (aansturen).
  2. Uitvoering slechts één keer: Ongeacht hoeveel taken een bepaalde handler aansturen, wordt die handler slechts één keer uitgevoerd (na afloop van alle taken in de play).
  3. Volgorde: Handlers worden uitgevoerd in de volgorde waarin ze zijn gedefinieerd, niet in de volgorde waarin ze worden aangestuurd.
  4. Handlers forceren (flushing): Als je wilt afdwingen dat handlers vóór het einde van de play worden uitgevoerd, kun je de taak meta: flush_handlers gebruiken. Hier is een eenvoudig voorbeeld om het concept van een ‘handler’ te verduidelijken:
---
- hosts: webserver
tasks:
- name: Install nginx
apt:
name: nginx
state: present

- name: Copy nginx configuration
copy:
src: /path/to/my/nginx.conf
dest: /etc/nginx/nginx.conf
notify: Restart nginx

handlers:
- name: Restart nginx
service:
name: nginx
state: restarted

In het bovenstaande voorbeeld:

  • Kan de taak “Copy nginx configuration” het nginx-configuratiebestand op de doelmachine wijzigen.
  • Als er een wijziging optreedt (d.w.z. de inhoud van het configuratiebestand verschilt van de bron), geeft de taak een melding (notify) aan de handler “Restart nginx”.
  • Nadat alle taken zijn uitgevoerd, controleert Ansible of de handler “Restart nginx” een melding heeft ontvangen.
  • Als de handler een melding heeft ontvangen, wordt deze uitgevoerd en wordt de nginx-service herstart. Als er geen melding is ontvangen (d.w.z. geen wijziging in het configuratiebestand), wordt de handler niet uitgevoerd.

Door handlers te gebruiken, zorgen we ervoor dat services of applicaties alleen worden herstart wanneer dat nodig is, waardoor mogelijke downtime of verstoring van de dienstverlening tot een minimum wordt beperkt.

Een playbook ontleed – stap-voor-stapvoorbeeld
#

In dit hoofdstuk leggen we stap voor stap uit hoe een playbook is opgebouwd. Om dit te kunnen doen, hebben we natuurlijk een voorbeeld nodig!

Dit wordt ons voorbeeld-playbook:
#

---
- name: Install a webserver
hosts: webservers
become: yes

tasks:
- name: Install HTTPD
yum:
name: httpd
state: latest

- name: Check if index template file is present
template:
src: files/index.html
dest: /var/www/html/

- name: start the httpd service
service:
name: httpd
state: started
enabled: yes

Wat doet het playbook?
#

Het playbook installeert eerst HTTPD, een Apache-webserverpakket dat wordt gebruikt in op RHEL gebaseerde besturingssystemen (CentOS, RHEL, Oracle Linux, enz.). Na de installatie van het pakket kopieert het een bestand van de Ansible-controller naar de doelhost. Vervolgens wordt geprobeerd de service te starten en in te schakelen (enable). Even ter herinnering: door de service te starten, zorg je ervoor dat de daemon op de doelhost draait. Door de service ook in te schakelen, wordt deze automatisch gestart wanneer het systeem opstart. Als je de service alleen zou starten zonder deze in te schakelen, zou de service niet automatisch starten bij het opstarten of herstarten van het systeem.

De play
#

Een ‘play’ is het grootste onderdeel van je playbook. In dit voorbeeld probeert de play die we hebben gemaakt een webserver te installeren. Zoals je kunt zien, kan een play uit meerdere taken (tasks) bestaan.

64.png

Zoals je ook kunt zien, begint het playbook met drie streepjes (—). Dit geeft aan dat het om een ​​YAML-bestand gaat en markeert het begin van het bestand. Dit geldt niet alleen voor Ansible-bestanden; het is een eigenschap die inherent is aan YAML zelf.

Vervolgens begint de play met een -name-instructie: dit is het hoofdgedeelte van het playbook en bevat informatie die van toepassing is op alle plays en taken in het playbook.

De volgende elementen zijn aanwezig:

- name: <NAME>            # Dit geeft een label aan voor het volledige playbook,
# voorbeelden zijn 'update OS' of 'install a webserver'. 

hosts: <targets>        # Hiermee wordt het doel (target) van het playbook ingesteld. 
# Als het trefwoord 'all' wordt opgegeven, is dit van toepassing op ALLE hosts
# in een gekozen inventory-bestand

become: yes             # Geeft aan dat alle taken als root worden uitgevoerd

### Taken

De taken zijn configuratiestappen die je zou uitvoeren bij het handmatig installeren van een pakket. De eerste taak probeert het HTTPD-pakket te installeren. Dit komt overeen met het commando `sudo yum install httpd`. De volgende taak kopieert een bestand naar /var/www/html/ en de laatste taak start de service en schakelt deze in. Deze laatste taak komt overeen met de commando's `sudo systemctl start httpd` en `sudo systemctl enable httpd`.

[![65.png](https://boeken.barttho.be/bookstack/public/uploads/images/gallery/2025-09/scaled-1680-/65-png.png)](https://boeken.barttho.be/bookstack/public/uploads/images/gallery/2025-09/scaled-1680-/65-png.png)

### Modules

Een module is een zelfstandig script dat Ansible namens jou uitvoert. Dit komt overeen met een commando. De module "yum" komt bijvoorbeeld overeen met het Linux-commando "yum", enzovoort. Modules interageren met verschillende aspecten van een systeem, zoals bestanden, services, pakketbeheerders of netwerkbronnen, waardoor Ansible ze op een idempotente manier kan beheren (d.w.z. herhaalde bewerkingen resulteren in dezelfde status in plaats van een cumulatief effect).

[![66.png](https://boeken.barttho.be/bookstack/public/uploads/images/gallery/2025-09/scaled-1680-/66-png.png)](https://boeken.barttho.be/bookstack/public/uploads/images/gallery/2025-09/scaled-1680-/66-png.png)

### De uitvoer van een playbook interpreteren

Playbooks maken gebruik van kleurcodering om aan te geven of er problemen zijn opgetreden of dat er wijzigingen hebben plaatsgevonden. <table border="1" id="bkmrk-color-behavior-green" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>**Kleur**
</td><td>**Gedrag**
</td></tr><tr><td><span style="color: rgb(22, 145, 121);">**Groen**</span>
</td><td>Er is niets gewijzigd</td></tr><tr><td>**<span style="color: rgb(241, 196, 15);">Geel/Oranje</span>**
</td><td>Ansible heeft met succes een parameter gewijzigd of een commando uitgevoerd</td></tr><tr><td>**<span style="color: rgb(224, 62, 45);">Rood</span>**
</td><td>Er is een fout opgetreden; Ansible kon een parameter niet wijzigen of een commando niet uitvoeren</td></tr></tbody></table>

Een voorbeeld hiervan is de onderstaande afbeelding:

[![67.png](https://boeken.barttho.be/bookstack/public/uploads/images/gallery/2025-09/scaled-1680-/67-png.png)](https://boeken.barttho.be/bookstack/public/uploads/images/gallery/2025-09/scaled-1680-/67-png.png)

# Loops en andere statements

<main class="v-main" data-booted="true" id="bkmrk-loops-in-ansible-pla"># Loops in Ansible Playbooks

Loops zijn een krachtige functie in Ansible waarmee je een taak of een reeks taken meerdere keren kunt herhalen met verschillende invoerwaarden. In Ansible kun je loops gebruiken met het `loop`-trefwoord om over een lijst te itereren, of met de `with_`-syntaxis om over de resultaten van een lookup te itereren. Hier is een eenvoudig voorbeeld dat een lus gebruikt om meerdere gebruikers op een externe machine aan te maken:
  • name: Gebruikers aanmaken user: name: “{{ item }}” state: present loop:
  • alice
  • bob
  • charlie

In dit voorbeeld wordt de `user`-module gebruikt om een ​​nieuwe gebruiker aan te maken met de naam die is opgegeven via de `item`-variabele; deze variabele neemt achtereenvolgens elke waarde uit de lijst `['alice', 'bob', 'charlie']` aan. De parameter `state` is ingesteld op `present` om ervoor te zorgen dat de gebruiker wordt aangemaakt als deze nog niet bestaat.

Je kunt ook lussen (loops) gebruiken om door een lijst met dictionaries te itereren. Het volgende playbook gebruikt bijvoorbeeld een lus om meerdere virtual hosts aan te maken op een Apache-webserver:
  • name: Configure virtual hosts apache2_vhost: servername: “{{ item.servername }}” documentroot: “{{ item.documentroot }}” loop:
  • { servername: “example.com”, documentroot: “/var/www/example” }
  • { servername: “example.net”, documentroot: “/var/www/example_net” }

In dit voorbeeld wordt de `apache2_vhost`-module gebruikt om een ​​nieuwe virtual host aan te maken met de `servername` en `documentroot` die zijn opgegeven via de `item`-variabele; deze variabele doorloopt elke dictionary in de lijst. Het trefwoord `loop` wordt gebruikt om door de lijst met dictionaries te itereren.

# If/Else-statements in Ansible-playbooks

Met if/else-statements kun je taken voorwaardelijk uitvoeren, afhankelijk van de status van het systeem. In Ansible kun je if/else-logica toepassen met het trefwoord `when`, waarbij een voorwaarde wordt opgegeven waaraan moet worden voldaan om de taak uit te voeren.

Hier is een eenvoudig voorbeeld waarin een if-statement wordt gebruikt om een ​​taak alleen uit te voeren als een bestand bestaat:
  • name: Copy file if it exists copy: src: /path/to/local/file dest: /path/to/remote/file when: ansible_facts[‘file_exists’]

In dit voorbeeld wordt de `copy`-module gebruikt om een ​​bestand van de lokale machine naar de externe machine te kopiëren, maar alleen als de variabele `file_exists` de waarde `true` heeft. De variabele `file_exists` wordt ingesteld via de variabele `ansible_facts`, die informatie over het externe systeem bevat. Je kunt ook 'else'-statements gebruiken om een ​​andere taak uit te voeren als de voorwaarde onwaar is. Het volgende playbook kopieert bijvoorbeeld een bestand als dit bestaat, en maakt een leeg bestand aan als dat niet het geval is:
  • name: Copy or create file copy: src: /path/to/local/file dest: /path/to/remote/file when: ansible_facts[‘file_exists’] become: yes become_user: root delegate_to: localhost tags:

  • file vars: file_contents: “This file was created because it didn’t exist”

  • name: Create empty file copy: content: "" dest: /path/to/remote/file when: not ansible_facts[‘file_exists’] become: yes become_user: root delegate_to: localhost tags:


# Met 'with_items'

Je kunt ook een dictionary opnemen om je Ansible-playbook geoptimaliseerd te houden. In plaats van meerdere taken te maken die sterk op elkaar lijken, kun je de `with_items`-operator gebruiken om een ​​aangepaste dictionary te doorlopen en de acties binnen dezelfde playbook-taak uit te voeren. Het volgende voorbeeld toont een dictionary waarmee meerdere VLAN's op een switch worden geconfigureerd:

```json
---
- name: Configure Cisco IOS Switch
hosts: switch
connection: network_cli
gather_facts: no
become: yes
vars:
data_vlan_id: 10
voice_vlan_id: 20
wifi_vlan_id: 30
backup_vlan_id: 40
guests_vlan_id: 50
interconnect_vlan_id: 60
access_ports: "range gi2/0/1-12"
uplink_ports: "range gi2/0/23-24"
port_channel: 1
tasks:
- name: Set access port descriptions
ios_interfaces:
config:
- name: "{{ access_ports }}"
description: Access Port configured by Ansible
enabled: true
- name: Create VLANs
ios_vlans:
config:
- vlan_id: "{{ item.id }}"
name: "{{ item.name }}"
state: active
with_items:
- { id: "{{ data_vlan_id }}", name: "data" }
- { id: "{{ voice_vlan_id }}", name: "voice" }
- { id: "{{ wifi_vlan_id }}", name: "wifi" }
- { id: "{{ backup_vlan_id }}", name: "backup" }
- { id: "{{ guests_vlan_id }}", name: "guests" }
- { id: "{{ interconnect_vlan_id }}", name: "interconnect" }

In dit specifieke playbook worden 6 VLAN’s aangemaakt, elk met een unieke ID en naam. De VLAN-ID’s en -namen worden gedefinieerd aan de hand van variabelen (data_vlan_id, voice_vlan_id, enz.), die hun waarden krijgen vanuit de Ansible-inventory of het playbook.

  1. De eerste taak heet “Set access port descriptions”. Deze maakt gebruik van de module ios_interfaces om de beschrijving en de status (ingeschakeld/uitgeschakeld) voor specifieke toegangspoorten (access ports) te configureren. De toegangspoorten worden gedefinieerd door de variabele access_ports. Deze taak gebruikt YAML-lijstsyntaxis om de configuratiewaarden op te geven. De sleutel config wordt gebruikt om een ​​lijst met toe te passen configuraties te specificeren. In dit geval wordt één enkele configuratie opgegeven, waarbij de sleutel name wordt gebruikt om de toegangspoort te identificeren en de sleutel description om de beschrijving in te stellen. De sleutel enabled wordt op true gezet om de interface in te schakelen.
  2. De tweede taak heet “Create VLANs”. Deze maakt gebruik van de module ios_vlans om VLAN’s te configureren op het doelnetwerkapparaat. Deze taak gebruikt een lus (with_items) om meerdere VLAN-configuraties aan te maken. De sleutel config wordt gebruikt om een ​​lijst met toe te passen VLAN-configuraties te specificeren. Elke VLAN-configuratie wordt opgegeven met behulp van YAML-dictionary-syntaxis. De sleutel vlan_id stelt het VLAN-ID in en de sleutel name stelt de VLAN-naam in. De sleutel state wordt op active gezet om ervoor te zorgen dat het VLAN wordt aangemaakt en ingeschakeld.