{"id":87084,"date":"2020-07-03T13:42:34","date_gmt":"2020-07-03T11:42:34","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron"},"modified":"2020-07-03T13:42:34","modified_gmt":"2020-07-03T11:42:34","slug":"osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","status":"publish","type":"post","link":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","title":{"rendered":"De basisprincipes van Ansible, zonder welke uw playbooks een klomp kleverige macaroni zijn","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ik maak veel beoordelingen van andermans code in Ansible en schrijf ook veel zelf. Tijdens het analyseren van fouten (zowel de mijne als die van anderen) en een aantal sollicitatiegesprekken besefte ik de grote fout die Ansible-gebruikers maken: ze duiken in complexe zaken zonder de basis te beheersen.<\/p>\n<p><\/p>\n<p>Om deze universele onrechtvaardigheid te verhelpen, besloot ik een introductie tot Ansible te schrijven voor degenen die het al kennen. Let op, dit is geen samenvatting van de handboeken, dit is een longread met veel tekst en zonder afbeeldingen.<\/p>\n<p><\/p>\n<p>Het verwachte leesniveau is al een paar duizend regels YAML geschreven, er is al iets in productie, maar \"het lijkt allemaal niet goed te werken\".<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>Benamingen<\/h1>\n<p><\/p>\n<p>De grootste fout van de Ansible-gebruiker is niet te weten hoe dingen heten. Als je de termen niet kent, kun je niet begrijpen wat er in de documentatie staat. Een levendig voorbeeld: tijdens een sollicitatiegesprek kon een persoon, die beweerde veel met Ansible te hebben gewerkt, de vraag \"waaruit bestaat een playbook?\" niet beantwoorden. En toen ik suggereerde dat \"het verwachte antwoord was dat een playbook uit plays bestaat\", volgde er een dodelijke opmerking \"dat gebruiken we niet\". Mensen schrijven met Ansible voor geld en gebruiken geen plays. <em>In werkelijkheid gebruiken ze het wel, maar weten ze niet wat het is.<\/em><\/p>\n<p><\/p>\n<p>Laten we dus beginnen met het eenvoudige: hoe dingen heten. Misschien weet je dit al, of misschien ook niet, omdat je er niet op lette toen je de documentatie las.<\/p>\n<p><\/p>\n<p>ansible-playbook voert het playbook uit. Een playbook is een bestand met de extensie yml\/yaml, waarin iets als dit staat:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">---\n- hosts: group1\n  roles:\n    - role1\n\n- hosts: group2,group3\n  tasks:\n    - debug:<\/code><\/pre>\n<p><\/p>\n<p>We hebben al begrepen dat dit hele bestand een playbook is. We kunnen laten zien waar de rollen (roles) en taken (tasks) zijn. Maar waar is de play? En wat is het verschil tussen een play, roll of playbook?<\/p>\n<p><\/p>\n<p>Dit staat allemaal in de documentatie. En dat wordt vaak overgeslagen. Beginners - omdat er te veel is en je kunt niet alles in \u00e9\u00e9n keer onthouden. Ervaren gebruikers - omdat het \"triviale dingen\" zijn. Als je ervaren bent, lees deze pagina's dan minstens eens in de zes maanden door, en je code zal veel beter worden.<\/p>\n<p><\/p>\n<p>Dus onthoud dit: Een playbook is een lijst bestaande uit plays en <code>import_playbook<\/code>.<br \/>\nDit is \u00e9\u00e9n play:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group1\n  roles:\n    - role1<\/code><\/pre>\n<p><\/p>\n<p>En dit is ook weer een play:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group2,group3\n  tasks:\n    - debug:<\/code><\/pre>\n<p><\/p>\n<p>Wat is een play? Wat is het nut ervan?<\/p>\n<p><\/p>\n<p>Play is a key element for the playbook, because play alone connects the list of roles and\/or tasks with the list of hosts on which they need to be executed. Deep in the documentation, mention can be found about <code>delegate_to<\/code>, local lookup plugins, network-cli-specific settings, jump hosts, etc. They allow for a slight change in the execution location of tasks. But forget about that. Each of these clever options has very specific applications, and they are definitely not universal. Here, we are talking about the basics that everyone should know and use.<\/p>\n<p><\/p>\n<p>Als je \"iets\" ergens wilt uitvoeren, schrijf je een play. Geen rol. Geen rol met modules en delegates. Je neemt en schrijft een play. In het hosts-veld vermeld je waar je het moet uitvoeren, en in roles\/tasks wat je moet uitvoeren.<\/p>\n<p><\/p>\n<p>Simple, right? How could it be otherwise?<\/p>\n<p><\/p>\n<p>Een van de kenmerkende momenten waarop mensen de wens krijgen dit niet via een play te doen, is \"een rol die alles configureert\". Men wil een rol die configureert en <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/nl\/server\/dts-los-angeles\/\"   title=\"de server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3633\">de server<\/a> first type servers as well as second type servers.<\/p>\n<p><\/p>\n<p>An archetypal example is monitoring. There\u2019s a desire to have a monitoring role that sets up monitoring. The monitoring role is assigned to the monitoring hosts (in the corresponding play). But it turns out that we need to install packages on the hosts we are monitoring. Why not use delegate? Also, we need to configure iptables. Delegate? And we need to write\/fix the DB config so that monitoring can work. Delegate! And if creativity kicks in, we can delegate <code>include_role<\/code> in a nested cycle with a clever filter on the group list, and inside <code>include_role<\/code> you can also do <code>delegate_to<\/code> weer. En daar gaan we weer\u2026<\/p>\n<p><\/p>\n<p>Een welgemeende wens - \u00e9\u00e9n enkele monitoringrol die \"alles doet\" - leidt ons naar de hel, waarvan de enige uitweg meestal is: alles opnieuw schrijven.<\/p>\n<p><\/p>\n<p>Waar ging het mis? Op het moment dat je ontdekte dat je voor taak \"x\" op host X naar host Y moest gaan en daar \"y\" moest doen, had je een eenvoudige oefening moeten uitvoeren: ga en schrijf een play die op host Y \"y\" doet. Niet iets aanvullen in \"x\", maar vanaf nul schrijven. Zelfs met hardcoded variabelen.<\/p>\n<p><\/p>\n<p>It seems that everything said in the paragraphs above is correct. But that\u2019s not your case! Because you want to write reusable code that is DRY and resembles a library, and you need to find a way to do that.<\/p>\n<p><\/p>\n<p>Hier ligt nog een grove fout verscholen. Een fout die talloze projecten heeft veranderd van redelijk goed geschreven (het kan beter, maar alles werkt en is gemakkelijk uit te breiden) in een volslagen chaos waarin zelfs de auteur niet meer kan volgen. Het werkt, maar je kunt beter niets veranderen.<\/p>\n<p><\/p>\n<p>Deze fout klinkt zo: een rol is een bibliotheekfunctie. Deze analogie heeft zoveel goede initiatieven de das omgedaan dat het gewoon tragisch is om te zien. Een rol is geen bibliotheekfunctie. Het kan geen berekeningen maken en het kan geen beslissingen op het niveau van play nemen. Herinner mij, welke beslissingen neemt play?<\/p>\n<p><\/p>\n<p>Dank je, je hebt gelijk. Play neemt een beslissing (meer precies, bevat informatie) over welke taken en rollen op welke hosts moeten worden uitgevoerd.<\/p>\n<p><\/p>\n<p>Als je deze beslissing aan een rol delegeert, en bovendien met berekeningen, dan geef je jezelf (en degene die je code probeert te begrijpen) een miserable bestaan. Een rol beslist niet waar hij uitgevoerd wordt. Die beslissing neemt play. Een rol doet wat hem is opgedragen, daar waar dat is aangegeven.<\/p>\n<p><\/p>\n<p>Waarom programmeren met Ansible gevaarlijk is en waarom COBOL beter is dan Ansible, bespreken we in het hoofdstuk over variabelen en Jinja. Vooralsnog zeggen we dit - elke berekening die je maakt, laat een ongebluste afdruk achter van wijzigingen in globale variabelen, en daar kun je niets aan doen. Zodra twee \"afdrukken\" elkaar kruisen - is alles verloren.<\/p>\n<p><\/p>\n<p>Opmerking voor de oplettenden: een rol kan inderdaad invloed hebben op de control flow. Er zijn <code>delegate_to<\/code> en hij heeft redelijkerwijs toepassingen. Er zijn <code>meta: eindhost\/play<\/code>. Maar! Vergeet niet, we leren de basis? Vergeet niet over <code>delegate_to<\/code>. We hebben het over de eenvoudigste en mooiste code in Ansible. Die gemakkelijk te lezen, gemakkelijk te schrijven, gemakkelijk te debuggen, gemakkelijk te testen en gemakkelijk uit te breiden is. Dus nogmaals:<\/p>\n<p><\/p>\n<p><strong>play en alleen play beslist op welke hosts wat uitgevoerd wordt.<\/strong><\/p>\n<p><\/p>\n<p>In dit onderdeel hebben we het conflict tussen play en role behandeld. Laten we nu het onderwerp taken versus rol bespreken.<\/p>\n<p><\/p>\n<h1>Taken en Rollen<\/h1>\n<p><\/p>\n<p>Laten we play bekijken:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: somegroup\n  pre_tasks:\n    - some_tasks1:\n  roles:\n     - role1\n     - role2\n  post_tasks:\n     - some_task2:\n     - some_task3:<\/code><\/pre>\n<p><\/p>\n<p>Stel, je moet foo maken. En het ziet eruit als <code>foo: name=foobar state=present<\/code>. Waar schrijf je dit? In pre? post? Een rol maken?<\/p>\n<p><\/p>\n<p>\u2026 En waar zijn de taken gebleven?<\/p>\n<p><\/p>\n<p>We beginnen weer bij de basis \u2014 play. Als je hierin niet goed bent, kun je play niet gebruiken als fundament voor de rest, en het resultaat wordt \"wankel\".<\/p>\n<p><\/p>\n<p>Het play-onderdeel: de hosts-directive, de instellingen van het play zelf en de secties pre_tasks, tasks, roles, post_tasks. Andere parameters voor het play zijn nu niet belangrijk voor ons.<\/p>\n<p><\/p>\n<p>De volgorde van hun secties met taken en rollen: <code>pre_tasks<\/code>, <code>roles<\/code>, <code>tasks<\/code>, <code>post_tasks<\/code>. Aangezien de semantische volgorde van uitvoering tussen <code>tasks<\/code> en <code>roles<\/code> onduidelijk is, zegt best practices dat we de sectie <code>tasks<\/code>toevoegen, alleen als er geen <code>roles<\/code>. Als er een <code>roles<\/code>, dan worden alle bijbehorende taken geplaatst in de sectie <code>pre_tasks<\/code>\/<code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Er blijft alleen over dat semantisch alles duidelijk is: eerst <code>pre_tasks<\/code>, daarna <code>roles<\/code>, daarna <code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Maar we hebben nog niet geantwoord op de vraag: waar moeten we de module-aanroep <code>foo<\/code> plaatsen? Moeten we voor elke module een hele rol schrijven? Of is het beter om \u00e9\u00e9n uitgebreide rol voor alles te hebben? En als het geen rol is, waar moet het dan geschreven worden \u2014 in pre of in post?<\/p>\n<p><\/p>\n<p>Als er geen goed onderbouwd antwoord op deze vragen is, dan is dat een teken van een gebrek aan intu\u00eftie, oftewel die \"wankele fundamenten\". Laten we dit uitzoeken. Eerst een controlevraag: Als play heeft <code>pre_tasks<\/code> en <code>post_tasks<\/code> (en er zijn geen taken of rollen), kan er dan iets kapotgaan als ik de eerste taak van <code>post_tasks<\/code> naar het einde verplaats? <code>pre_tasks<\/code>?<\/p>\n<p><\/p>\n<p>Natuurlijk suggereert de formulering van de vraag dat er iets kapotgaat. Maar wat precies?<\/p>\n<p><\/p>\n<p>\u2026 Handlers. Het lezen van de basisprincipes onthult een belangrijk feit: alle handlers worden automatisch flush'ged na elke sectie. Dat wil zeggen, alle taken in <code>pre_tasks<\/code>, dan worden alle handlers uitgevoerd die zijn genotificeerd. Vervolgens worden alle rollen uitgevoerd en alle handlers die zijn genotificeerd in die rollen. Daarna <code>post_tasks<\/code> en hun handlers.<\/p>\n<p><\/p>\n<p>Daarom, als je een taak verplaatst van <code>post_tasks<\/code> in <code>pre_tasks<\/code>, dan is de kans groot dat je het uitvoert voordat de handler is uitgevoerd. Bijvoorbeeld, als in <code>pre_tasks<\/code> wordt ge\u00efnstalleerd en geconfigureerd <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/nl\/server\/\"   title=\"webserver\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1155\">webserver<\/a>, en in <code>post_tasks<\/code> en er iets naartoe wordt gestuurd, dan leidt het verplaatsen van deze taak naar de sectie <code>pre_tasks<\/code> dit leidt ertoe dat op het moment van \"verzenden\" de server nog niet draait en alles kapot gaat.<\/p>\n<p><\/p>\n<p>Laten we nu nog eens nadenken, waarom hebben we <code>pre_tasks<\/code> en <code>post_tasks<\/code>? \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432\u0441\u0451 \u043d\u0443\u0436\u043d\u043e\u0435 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0445\u044d\u043d\u0434\u043b\u0435\u0440\u044b) \u0434\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0440\u043e\u043b\u0438. \u0410 <code>post_tasks<\/code> nodig dat ons in staat stelt om met de resultaten van het uitvoeren van rollen (inclusief handlers) te werken.<\/p>\n<p><\/p>\n<p>Een oplettende expert in Ansible zal ons vertellen dat er <code>meta: flush_handlers<\/code>is, maar waarom hebben we flush_handlers nodig, als we kunnen rekenen op de volgorde van uitvoering van de secties in het play? Bovendien kan het gebruik van meta: flush_handlers ons in de problemen brengen met herhaalde handlers, en vreemde waarschuwingen veroorzaken bij het gebruik van <code>when<\/code> \u2018 <code>block<\/code> enzovoorts. Hoe beter je Ansible kent, hoe meer nuances je kunt opnoemen voor een \"slim\" ontwerp. Een eenvoudige oplossing is het gebruik van natuurlijke scheiding tussen pre\/roles\/post \u2014 dit roept geen nuances op.<\/p>\n<p><\/p>\n<p>En, terugkomend op onze 'foo'. Waar moeten we het plaatsen? In pre, post of in roles? Dit hangt duidelijk af van of we de resultaten van de handler nodig hebben voor foo. Als dat niet het geval is, hoeft foo niet in pre of in post te worden geplaatst \u2014 deze secties hebben een speciale betekenis \u2014 het uitvoeren van taken v\u00f3\u00f3r en n\u00e1 de belangrijkste code.<\/p>\n<p><\/p>\n<p>Nu wordt het antwoord op de vraag \"rol of taak\" afhankelijk van wat er al in play is \u2014 als er taken zijn, dan moet je die in taken aanvullen. Als er rollen zijn, moet je een rol maken (ook al is het maar uit \u00e9\u00e9n taak). Ik herinner je eraan dat taken en rollen niet tegelijkertijd worden gebruikt.<\/p>\n<p><\/p>\n<p>Het begrijpen van de basisprincipes van Ansible geeft onderbouwde antwoorden op vragen die schijnbaar om persoonlijke voorkeur draaien.<\/p>\n<p><\/p>\n<h1>Taken en rollen (deel twee)<\/h1>\n<p><\/p>\n<p>Laten we nu de situatie bespreken waarin je net begint met het schrijven van een playbook. Je moet foo, bar en baz maken. Zijn dit drie taken, \u00e9\u00e9n rol of drie rollen? Om de vraag te generaliseren: wanneer moet je beginnen met het schrijven van rollen? Wat is de betekenis van het schrijven van rollen als je ook taken kunt schrijven?\u2026 En wat is een rol?<\/p>\n<p><\/p>\n<p>Een van de grootste fouten (daar heb ik het al over gehad) is denken dat een rol als een functie in de bibliotheek van een programma is. Hoe ziet een algemene beschrijving van een functie eruit? Het neemt argumenten als invoer, interacteert met side causes, heeft side effects en geeft een waarde terug.<\/p>\n<p><\/p>\n<p>Nu, let op. Wat hiervan kan in een rol worden gedaan? Bijwerkingen oproepen \u2014 altijd welkom, dat is de essentie van Ansible \u2014 bijwerkingen maken. Hebben side causes? Eenvoudig. Maar met \"een waarde doorgeven en deze retourneren\" \u2014 daar gaat het mis. Ten eerste kun je geen waarde naar een rol doorgeven. Je kunt een globale variabele instellen met een levensduur die de play beslaat in de sectie vars voor de rol. Je kunt een globale variabele instellen met een levensduur in de play binnen de rol. Of zelfs met een levensduur van playbooks (<code>set_fact<\/code>\/<code>register<\/code>). Maar je kunt geen \"lokale variabelen\" hebben. Je kunt geen \"waarde ontvangen\" en deze \"teruggeven\".<\/p>\n<p><\/p>\n<p>Hieruit volgt het belangrijkste: je kunt in Ansible niets schrijven zonder side effects op te roepen. Het wijzigen van globale variabelen is altijd een side effect voor een functie. In Rust, bijvoorbeeld, is het wijzigen van een globale variabele <code>unsafe<\/code>. In Ansible is er maar \u00e9\u00e9n manier om waarden voor een rol te be\u00efnvloeden. Let op de gebruikte woorden: niet &quot;waarde doorgeven aan de rol&quot;, maar &quot;waarden wijzigen die de rol gebruikt&quot;. Er is geen isolatie tussen rollen. Er is geen isolatie tussen taken en rollen.<\/p>\n<p><\/p>\n<p>Kortom: <strong>een rol is geen functie<\/strong>.<\/p>\n<p><\/p>\n<p>Wat is er goed aan rollen? Ten eerste hebben rollen standaardwaarden (<code>\/default\/main.yaml<\/code>), ten tweede hebben rollen extra mappen om bestanden op te slaan.<\/p>\n<p><\/p>\n<p>Wat is er zo goed aan standaardwaarden? In de behoorlijk verdraaide prioriteitstabel van Maslow voor variabelen in Ansible zijn de rolstandaardwaarden de minst prioritaire (behalve de commandoregelparameters van Ansible). Dit betekent dat als je standaardwaarden moet geven zonder je zorgen te maken dat ze de waarden uit de inventory of groepsvariabelen overschrijven, de standaardwaarden van de rol de enige juiste plek voor je zijn. (Ik lieg een beetje - er is ook nog <code>|d(your_default_here)<\/code>, maar als we het hebben over vaste plekken - dan zijn het alleen de standaardwaarden van de rollen).<\/p>\n<p><\/p>\n<p>Wat is er nog meer goed aan rollen? Ze hebben hun eigen mappen. Dit zijn mappen voor variabelen, zowel statische (d.w.z. berekend voor de rol) als dynamische (er is een of andere patroon, of anti-patroon - <code>include_vars<\/code> samen met <code>{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml<\/code>.). Dit zijn mappen voor <code>files\/<\/code>, <code>templates\/<\/code>. Bovendien stelt het je in staat om je eigen modules en plugins te hebben (<code>library\/<\/code>). Maar in vergelijking met taken in een playbook (waar ook alles kan zijn), is het voordeel hier alleen dat de bestanden niet in \u00e9\u00e9n grote hoop zijn gestapeld, maar in verschillende kleine stapels.<\/p>\n<p><\/p>\n<p>Een ander detail: je kunt proberen rollen te maken die beschikbaar zijn voor hergebruik (via galaxy). Na de introductie van collecties kan de verspreiding van rollen als bijna vergeten worden beschouwd.<\/p>\n<p><\/p>\n<p>Dus hebben rollen twee belangrijke kenmerken: ze hebben standaardwaarden (een unieke eigenschap) en ze stellen je in staat om de code te structureren.<\/p>\n<p><\/p>\n<p>Terugkomend op de oorspronkelijke vraag: wanneer gebruik je taken en wanneer rollen? Taken in een playbook worden meestal gebruikt ofwel als &quot;lijm&quot; voor\/na rollen, of als onafhankelijke bouwstenen (dan mogen rollen niet in de code staan). Een stapel normale taken door elkaar met rollen is duidelijk slordig. Je moet je aan een specifieke stijl houden \u2014 of taken of rollen. Rollen bieden scheiding van entiteiten en standaarden, taken maken het gemakkelijker om de code te lezen. Gewoonlijk worden meer &quot;stationaire&quot; (belangrijke en complexe) code in de rol geplaatst, terwijl bij de stijl van taken ondersteunende scripts worden geschreven.<\/p>\n<p><\/p>\n<p>Er is de mogelijkheid om import_role als taak te maken, maar als je dat schrijft, wees dan bereid om jezelf uit te leggen waarom je dat zou willen doen.<\/p>\n<p><\/p>\n<p>Een kritische lezer kan zeggen dat rollen rollen kunnen importeren, dat rollen afhankelijkheden kunnen hebben via galaxy.yml, en er is ook het gruwelijke en vreselijke <code>include_role<\/code> \u2014 ik herinner je eraan dat we onze vaardigheden in basis Ansible verbeteren, en niet in ritmische gymnastiek.<\/p>\n<p><\/p>\n<h1>Handlers en taken<\/h1>\n<p><\/p>\n<p>Laten we nog iets voor de hand liggends bespreken: handlers. De vaardigheid om ze correct te gebruiken is bijna een kunst. Wat is het verschil tussen een handler en een taak?<\/p>\n<p><\/p>\n<p>Omdat we de basisherinneringen opfrissen, hier is een voorbeeld:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group1\n  taken:\n    - foo:\n      notify: handler1\n  handlers:\n     - naam: handler1\n       bar:<\/code><\/pre>\n<p><\/p>\n<p>De handlers van de rol bevinden zich in rolename\/handlers\/main.yaml. Handlers worden gedeeld tussen alle deelnemers aan de play: pre\/post_tasks kunnen de handlers van de rol aanroepen, en de rol kan handlers uit de play aanroepen. Echter, &quot;kruisrol&quot; aanroepen van handlers zorgt voor veel grotere verwarring dan het herhalen van een triviale handler. (Een ander element van de best practices is om te proberen herhalingen van de namen van handlers te vermijden).<\/p>\n<p><\/p>\n<p>Het belangrijkste verschil is dat een taak altijd (bijna altijd met uitzondering van tags en <code>when<\/code>), idempotent wordt uitgevoerd, terwijl de handler wordt uitgevoerd op basis van statuswijzigingen (notify wordt alleen geactiveerd als er iets is veranderd). Wat houdt dat in? Bijvoorbeeld, dat bij een herhaalde uitvoering, als er geen wijzigingen zijn geweest, er ook geen handler zal zijn. Maar waarom kan het zo zijn dat we een handler moeten uitvoeren, terwijl er geen wijzigingen waren bij de veroorzakende taak? Bijvoorbeeld omdat er iets kapot was en er wel wijzigingen waren, maar de uitvoering kwam niet bij de handler. Bijvoorbeeld omdat het netwerk tijdelijk uit viel. De configuratie is veranderd, de service is niet herstart. Bij de volgende uitvoering verandert de configuratie al niet meer, en blijft de service met de oude versie van de configuratie.<\/p>\n<p><\/p>\n<p>De situatie met de configuratie is niet oplosbaar (eigenlijk, je kunt voor jezelf een speciaal herstartprotocol uitvinden met bestandsvlaggen, enzovoort, maar dat is al niet meer &lsquo;basis ansible&rsquo; in welke vorm dan ook). Maar er is een andere veelvoorkomende situatie: we hebben een applicatie ge\u00efnstalleerd, hebben deze genoteerd. <code>.service<\/code>-bestand, en nu willen we deze <code>daemon_reload<\/code> en <code>state=started<\/code>. En een natuurlijke plek hiervoor lijkt de handler. Maar als je het geen handler maar een taak aan het einde van de takenlijst of rol maakt, zal het idempotent worden uitgevoerd elke keer. Zelfs als de playbook halverwege faalt. Dit lost het probleem van restarted absoluut niet op (je kunt geen taak met de eigenschap restarted doen, omdat de idempotentie verloren gaat), maar het is zeker beter om state=started te doen, omdat de algehele stabiliteit van playbooks toeneemt, omdat het aantal afhankelijkheden en dynamische toestand vermindert.<\/p>\n<p><\/p>\n<p>Een ander positief kenmerk van de handler is dat deze de output niet vervuilt. Er waren geen wijzigingen \u2014 geen overbodige skipped of ok in de output \u2014 het is gemakkelijker te lezen. Dit is ook een negatief kenmerk \u2014 als je een spelfout in een lineair uitgevoerde taak bij de eerste poging vindt, worden handlers alleen uitgevoerd bij veranderingen, dat wil zeggen onder bepaalde voorwaarden \u2014 zeer zeldzaam. Bijvoorbeeld, de eerste keer in je leven na vijf jaar. En natuurlijk zal er een spelfout in de naam zijn en alles zal mislukken. De tweede keer kun je ze niet uitvoeren \u2014 er zijn geen wijzigingen.<\/p>\n<p><\/p>\n<p>Er moet apart gesproken worden over de beschikbaarheid van variabelen. Bijvoorbeeld, als je notify voor een taak met een loop, wat zal er dan in de variabelen staan? Je kunt dat analytisch afleiden, maar het is niet altijd triviaal, vooral als de variabelen uit verschillende bronnen komen.<\/p>\n<p><\/p>\n<p>Handlers zijn dus veel minder nuttig en veel problematischer dan ze lijken. Als het mogelijk is om iets mooi (zonder franje) te schrijven zonder handlers, doe het dan zonder. Als het niet mooi lukt, gebruik ze dan beter.<\/p>\n<p><\/p>\n<p>De oplettende lezer merkt terecht op dat we niet hebben besproken <code>listen<\/code>, dat handlers notify kunnen aanroepen voor andere handlers, dat een handler import_tasks kan bevatten (die include_role met with_items kan doen), dat het systeem van handlers in Ansible Turing-compleet is, dat handlers uit include_role op een intrigerende manier overlappen met handlers uit plays, etc. - dit is allemaal duidelijk geen \"basis\".<\/p>\n<p><\/p>\n<p>Maar er is \u00e9\u00e9n bepaalde WTF die eigenlijk een feature is, en waar je aan moet denken. Als je een taak uitvoert met <code>delegate_to<\/code> en het heeft notify, dan wordt de bijbehorende handler uitgevoerd zonder <code>delegate_to<\/code>, dat wil zeggen, op de host waarop de play is toegewezen. (Hoewel een handler uiteraard ook kan hebben <code>delegate_to<\/code> ook).<\/p>\n<p><\/p>\n<p>Ik wil apart een paar woorden zeggen over herbruikbare rollen. Tot de komst van collecties was er het idee dat je universele rollen kon maken die je kon <code>ansible-galaxy install<\/code> en verder gegaan. Werkt op alle besturingssystemen in alle varianten in alle situaties. Dus, mijn mening: dit werkt niet. Elke rol met een massale <code>include_vars<\/code>, het ondersteunen van 100500 gevallen is gedoemd tot diepten van corner case bugs. Ze kunnen worden afgedekt door middel van uitgebreide tests, maar zoals bij elke test, ofwel heb je een cartesiaans product van invoerwaarden en een totale functie, ofwel heb je \"specifieke scenario's gedekt\". Mijn mening - het is veel beter als de rol lineair is (cyclomatische complexiteit 1).<\/p>\n<p><\/p>\n<p>Hoe minder if-statements (expliciet of declaratief - in de vorm van <code>when<\/code> of vorm <code>include_vars<\/code> per set variabelen), hoe beter de rol. Soms moet je takken maken, maar nogmaals, hoe minder, hoe beter. Dus het lijkt alsof een goede rol met galaxy (werkt immers!) met een hoop <code>when<\/code> kan minder gewenst zijn dan \"eigen\" rol van vijf taken. Het moment waarop de rol met Galaxy beter is - wanneer je iets begint te schrijven. Het moment waarop het slechter wordt - wanneer er iets fout gaat, en je vermoedt dat dit te maken heeft met de \"rol uit Galaxy\". Je opent het, en daar zijn vijf inclusies, acht taaklijsten en een stapel <code>when<\/code>\u2018en... En daar moet je doorheen. In plaats van 5 taken in een lineaire lijst, waarin er eigenlijk niets stuk kan gaan.<\/p>\n<p><\/p>\n<h1>In de volgende delen<\/h1>\n<p><\/p>\n<ul>\n<li>Een beetje over inventory, groepsvariabelen, host_group_vars plugin, hostvars. Hoe je spaghetti omzet in een Gordiaanse knoop. Scope en precedentie van variabelen, Ansible geheugenmodel. \"Dus waar moet je de gebruikersnaam voor de database opslaan?\".<\/li>\n<li><code>jinja: {{ jinja }}<\/code> \u2014 nosql notype nosense zachte klei. Het is overal, zelfs daar waar je het niet verwacht. Een beetje over <code>!!unsafe<\/code> en smakelijke yaml.<\/li>\n<\/ul>\n<p>Bron: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/508762\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042f \u0434\u0435\u043b\u0430\u044e \u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0432\u044c\u044e \u0434\u043b\u044f \u0447\u0443\u0436\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430 \u0410\u043d\u0441\u0438\u0431\u043b \u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u0438\u0448\u0443 \u0441\u0430\u043c. \u0412 \u0445\u043e\u0434\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u043e\u0448\u0438\u0431\u043e\u043a (\u043a\u0430\u043a \u0447\u0443\u0436\u0438\u0445, \u0442\u0430\u043a \u0438 \u0441\u0432\u043e\u0438\u0445), \u0430 \u0442\u0430\u043a \u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439, \u044f \u043f\u043e\u043d\u044f\u043b \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0410\u043d\u0441\u0438\u0431\u043b\u0430 \u2014 \u043e\u043d\u0438 \u043b\u0435\u0437\u0443\u0442 \u0432 \u0441\u043b\u043e\u0436\u043d\u043e\u0435, \u043d\u0435 \u043e\u0441\u0432\u043e\u0438\u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e. \u0414\u043b\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0432\u0441\u0435\u043b\u0435\u043d\u0441\u043a\u043e\u0439 \u043d\u0435\u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 \u0410\u043d\u0441\u0438\u0431\u043b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-87084","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042f \u0434\u0435\u043b\u0430\u044e \u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0432\u044c\u044e \u0434\u043b\u044f \u0447\u0443\u0436\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430 \u0410\u043d\u0441\u0438\u0431\u043b \u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u0438\u0448\u0443 \u0441\u0430\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u0441\u043d\u043e\u0432\u044b Ansible, \u0431\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u0430\u0448\u0438 \u043f\u043b\u0435\u0439\u0431\u0443\u043a\u0438 \u2014 \u043a\u043e\u043c\u043e\u043a \u0441\u043b\u0438\u043f\u0448\u0438\u0445\u0441\u044f \u043c\u0430\u043a\u0430\u0440\u043e\u043d | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042f \u0434\u0435\u043b\u0430\u044e \u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0432\u044c\u044e \u0434\u043b\u044f \u0447\u0443\u0436\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430 \u0410\u043d\u0441\u0438\u0431\u043b \u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u0438\u0448\u0443 \u0441\u0430\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-03T11:42:34+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-03T11:42:34+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Basisprincipes van Ansible, zonder welke je playbooks een klomp samengeplakte pasta zijn | ProHoster","description":"Ik doe veel reviews voor andermans code in Ansible en schrijf zelf veel.","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u0441\u043d\u043e\u0432\u044b Ansible, \u0431\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u0430\u0448\u0438 \u043f\u043b\u0435\u0439\u0431\u0443\u043a\u0438 \u2014 \u043a\u043e\u043c\u043e\u043a \u0441\u043b\u0438\u043f\u0448\u0438\u0445\u0441\u044f \u043c\u0430\u043a\u0430\u0440\u043e\u043d | ProHoster","og:description":"\u042f \u0434\u0435\u043b\u0430\u044e \u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0432\u044c\u044e \u0434\u043b\u044f \u0447\u0443\u0436\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430 \u0410\u043d\u0441\u0438\u0431\u043b \u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u0438\u0448\u0443 \u0441\u0430\u043c.","og:url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-03T11:42:34+00:00","article:modified_time":"2020-07-03T11:42:34+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"87084","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:58:53","updated":"2026-02-22 15:29:30","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/87084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=87084"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/87084\/revisions"}],"predecessor-version":[{"id":162161,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/87084\/revisions\/162161"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=87084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=87084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=87084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}