{"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\/da\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","title":{"rendered":"Grundl\u00e6ggende om Ansible, uden hvilke dine playbooks blot er en klump sammenklistrede spaghetti","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Jeg laver mange anmeldelser af andres kode i Ansible og skriver ogs\u00e5 meget selv. Gennem fejlanalyse (b\u00e5de af andres og mine egne) og en del interviews har jeg indset den grundl\u00e6ggende fejl, som Ansible-brugere laver \u2014 de dykker ned i det komplekse uden at have forst\u00e5et det grundl\u00e6ggende.<\/p>\n<p><\/p>\n<p>For at rette op p\u00e5 denne universelle uretf\u00e6rdighed har jeg besluttet at skrive en introduktion til Ansible for dem, der allerede kender det. Jeg advarer, dette er ikke en opsummering af manualerne, men en lang artikel med mange ord og ingen billeder.<\/p>\n<p><\/p>\n<p>Det forventede l\u00e6seniveau er, at du allerede har skrevet flere tusinde linjer YAML og har noget i produktion, men \"det er bare ikke helt rigtigt\".<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>Titler<\/h1>\n<p><\/p>\n<p>Den st\u00f8rste fejl, en Ansible-bruger laver, er ikke at vide, hvad ting hedder. Hvis du ikke kender navne, kan du ikke forst\u00e5, hvad der st\u00e5r i dokumentationen. Et levende eksempel: til et interview kunne en person, der angiveligt havde skrevet meget med Ansible, ikke svare p\u00e5 sp\u00f8rgsm\u00e5let \"af hvilke elementer best\u00e5r et playbook?\". Og n\u00e5r jeg foreslog, at \"man kunne forvente svaret var, at et playbook best\u00e5r af plays\", kom kommentaren \"vi bruger ikke det\". Folk skriver p\u00e5 Ansible for penge og bruger ikke plays. <em>De bruger det faktisk, men ved ikke, hvad det er.<\/em><\/p>\n<p><\/p>\n<p>S\u00e5 lad os starte med det enkle: hvad hedder hvad. M\u00e5ske ved du det, eller m\u00e5ske ikke, fordi du ikke har lagt m\u00e6rke til det, n\u00e5r du l\u00e6ste dokumentationen.<\/p>\n<p><\/p>\n<p>ansible-playbook udf\u00f8rer playbook. En playbook er en fil med udvidelsen yml\/yaml, inden i hvilken der er noget som dette:<\/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>Vi har allerede forst\u00e5et, at hele denne fil \u2014 er en playbook. Vi kan vise, hvor roljerne (roles) er, og hvor opgaverne (tasks) er. Men hvor er play her? Og hvad adskiller play fra role eller playbook?<\/p>\n<p><\/p>\n<p>Alt dette findes i dokumentationen. Og det bliver overset. Nybegyndere \u2014 fordi der er for meget, og man kan ikke huske det hele p\u00e5 \u00e9n gang. Erfarne \u2014 fordi det er \"trivielle ting\". Hvis du er erfaren \u2014 s\u00e5 l\u00e6s disse sider mindst \u00e9n gang hver sjette m\u00e5ned, og din kode vil blive meget bedre.<\/p>\n<p><\/p>\n<p>S\u00e5 husk: En playbook \u2014 er en liste, der best\u00e5r af play og <code>import_playbook<\/code>.<br \/>\nDette er en play:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group1\n  roles:\n    - role1<\/code><\/pre>\n<p><\/p>\n<p>Og dette er ogs\u00e5 endnu en play:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group2,group3\n  tasks:\n    - debug:<\/code><\/pre>\n<p><\/p>\n<p>Hvad er en play? Hvad er form\u00e5let med den?<\/p>\n<p><\/p>\n<p>En play er den vigtigste del af en playbook, fordi play og kun play forbinder listen af roller og\/eller opgaver med listen af v\u00e6rter, hvor de skal udf\u00f8res. I de dybe afkroge af dokumentationen kan man finde en omtale af <code>delegate_to<\/code>, lokale lookup-plugins, netv\u00e6rk-cli-specifikke indstillinger, jump-hosts osv. De giver mulighed for let at \u00e6ndre leddet for opgaveudf\u00f8relse. Men glem det. Hver af disse snedige muligheder har meget specifikke anvendelser, og de er bestemt ikke universelle. Vi taler om de grundl\u00e6ggende ting, som alle b\u00f8r vide og bruge.<\/p>\n<p><\/p>\n<p>Hvis du \u00f8nsker at udf\u00f8re \"noget\" \"et sted\" \u2014 s\u00e5 skriver du et play. Ikke en rolle. Ikke en rolle med moduler og delegationer. Du tager og skriver et play. Heri angiver du i feltet hosts, hvor det skal udf\u00f8res, og i roles\/tasks \u2014 hvad der skal udf\u00f8res.<\/p>\n<p><\/p>\n<p>Det er simpelt, ikke? Og hvordan kan det v\u00e6re anderledes?<\/p>\n<p><\/p>\n<p>Et karakteristisk \u00f8jeblik, n\u00e5r folk f\u00e5r lyst til at g\u00f8re det uden om play, er \"en rolle, der konfigurerer alt\". Man \u00f8nsker at have en rolle, der konfigurerer og <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/da\/server\/dts-los-angeles\/\"   title=\"server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3633\">server<\/a> af f\u00f8rste type og servere af anden type.<\/p>\n<p><\/p>\n<p>Et arketypisk eksempel er overv\u00e5gning. Man \u00f8nsker at have en rolle monitoring, der ops\u00e6tter overv\u00e5gning. Rollen monitoring tildeles til overv\u00e5gningshoste (i den relevante play). Men det viser sig, at vi skal installere pakker p\u00e5 de hoste, vi overv\u00e5ger. Hvorfor ikke bruge delegate? Og desuden skal iptables konfigureres. Delegate? Og vi skal ogs\u00e5 skrive\/revidere konfigurationen for DBMS, s\u00e5 overv\u00e5gningen kan starte. Delegate! Og hvis kreativiteten str\u00f8mmer, kan man lave delegation <code>include_role<\/code> i en indlejret l\u00f8kke med et snedigt filter p\u00e5 gruppelisten, og indeni <code>include_role<\/code> kan man ogs\u00e5 g\u00f8re <code>delegate_to<\/code> igennem. Og s\u00e5 k\u00f8rer det...<\/p>\n<p><\/p>\n<p>Et velment \u00f8nske er at have \u00e9n enkelt overv\u00e5gningsrolle, der \"g\u00f8r det hele\" \u2014 men det f\u00f8rer os til et kaos, hvor den eneste udvej ofte er: at skrive alt om fra bunden.<\/p>\n<p><\/p>\n<p>Hvor skete fejlen her? I det \u00f8jeblik, du opdagede, at for at udf\u00f8re opgaven \"x\" p\u00e5 host X, skal du g\u00e5 til host Y og g\u00f8re \"y\" der, skulle du have udf\u00f8rt en enkel \u00f8velse: g\u00e5 og skrive et play, der p\u00e5 host Y udf\u00f8rer y. Ikke tilf\u00f8je noget til \"x\", men skrive det fra bunden. Selv med hardkodede variable.<\/p>\n<p><\/p>\n<p>Tilsyneladende er alt sagt korrekt i de foreg\u00e5ende afsnit. Men det er ikke dit tilf\u00e6lde! Fordi du \u00f8nsker at skrive genanvendelig kode, der er DRY og ligner et bibliotek, og det er n\u00f8dvendigt at finde en metode til at g\u00f8re dette.<\/p>\n<p><\/p>\n<p>Her ligger der endnu en grov fejl. En fejl, der har forvandlet mange projekter fra t\u00e5leligt skrevne (det kunne v\u00e6re bedre, men det fungerer og er nemt at skrive videre p\u00e5) til en fuldst\u00e6ndig r\u00e6dsel, som selv forfatteren ikke kan forst\u00e5. Det fungerer, men lad v\u00e6re med at \u00e6ndre noget.<\/p>\n<p><\/p>\n<p>Denne fejl lyder s\u00e5ledes: en rolle er en biblioteksfunktion. Denne analogi har \u00f8delagt s\u00e5 mange gode initiativer, at det n\u00e6sten er trist at se. En rolle er ikke en biblioteksfunktion. Den kan ikke udf\u00f8re beregninger, og den kan ikke tr\u00e6ffe beslutninger p\u00e5 play-niveau. Mind mig om, hvilke beslutninger play tr\u00e6ffer?<\/p>\n<p><\/p>\n<p>Tak, du har ret. Play tr\u00e6ffer beslutningen (eller rettere, indeholder informationen) om, hvilke opgaver og roller der skal udf\u00f8res p\u00e5 hvilke v\u00e6rter.<\/p>\n<p><\/p>\n<p>Hvis du delegerer denne beslutning til en rolle, og endda med beregninger, d\u00f8mer du dig selv (og den, der skal fors\u00f8ge at forst\u00e5 din kode) til en elendig tilv\u00e6relse. Rollen beslutter ikke, hvor den skal udf\u00f8res. Det er play, der tr\u00e6ffer denne beslutning. Rollen g\u00f8r, hvad den bliver bedt om, d\u00e9r hvor den bliver bedt om det.<\/p>\n<p><\/p>\n<p>Hvorfor det er farligt at programmere i Ansible og hvorfor COBOL er bedre end Ansible, vil vi tale om i kapitlet om variable og jinja. Indtil videre kan vi sige \u00e9n ting \u2014 hver af dine beregninger efterlader et uudsletteligt spor af \u00e6ndringer i globale variable, og du kan ikke g\u00f8re noget ved det. S\u00e5 snart to \"spor\" krydser hinanden \u2014 er alt tabt.<\/p>\n<p><\/p>\n<p>Bem\u00e6rkning til de nysgerrige: en rolle kan bestemt p\u00e5virke kontrolstr\u00f8mmen. Der er <code>delegate_to<\/code> og den har fornuftige anvendelser. Der er <code>meta: end host\/play<\/code>. Men! Husk, vi l\u00e6rer grundl\u00e6ggende ting? Glemt om <code>delegate_to<\/code>. Vi taler om den enkleste og smukkeste kode i Ansible. Som er let at l\u00e6se, let at skrive, let at fejlrette, let at teste og let at tilf\u00f8je til. S\u00e5 endnu en gang:<\/p>\n<p><\/p>\n<p><strong>play og kun play beslutter, hvilke v\u00e6rter hvad udf\u00f8res p\u00e5.<\/strong><\/p>\n<p><\/p>\n<p>I denne sektion har vi unders\u00f8gt modstridene mellem play og rolle. Nu vil vi tale om forholdet mellem tasks vs rolle.<\/p>\n<p><\/p>\n<h1>Opgaver og Roller<\/h1>\n<p><\/p>\n<p>Lad os se p\u00e5 play:<\/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>Lad os antage, at du skal lave foo. Og det ser s\u00e5ledes ud <code>foo: name=foobar state=present<\/code>. Hvor skal dette skrives? i pre? post? Oprette en rolle?<\/p>\n<p><\/p>\n<p>\u2026 Og hvor er opgaverne blevet af?<\/p>\n<p><\/p>\n<p>Vi begynder endnu engang fra bunden - play-enheden. Hvis du er usikker p\u00e5 dette emne, kan du ikke bruge play som fundament for alt andet, og dit resultat bliver \"ustabilt\".<\/p>\n<p><\/p>\n<p>Play-enhed: hosts-direktiv, indstillinger for selve play og sektionerne pre_tasks, tasks, roles, post_tasks. Andre parametre for play er ikke relevante for os lige nu.<\/p>\n<p><\/p>\n<p>R\u00e6kkef\u00f8lgen af deres sektioner med tasks og roller: <code>pre_tasks<\/code>, <code>roles<\/code>, <code>tasks<\/code>, <code>post_tasks<\/code>. Da den semantiske r\u00e6kkef\u00f8lge for udf\u00f8relsen mellem <code>tasks<\/code> og <code>roles<\/code> ikke er klar, siger best practices, at vi kun tilf\u00f8jer sektionen <code>tasks<\/code>, hvis der ikke er <code>roles<\/code>. Hvis der er <code>roles<\/code>, s\u00e5 placeres alle tilknyttede tasks i sektionerne <code>pre_tasks<\/code>\/<code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Der er kun tilbage, hvad der semantisk er klart: f\u00f8rst <code>pre_tasks<\/code>, derefter <code>roles<\/code>, derefter <code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Men vi har stadig ikke svaret p\u00e5 sp\u00f8rgsm\u00e5let: hvor skal modulopkaldet <code>foo<\/code> skrives? Skal vi skrive en hel rolle for hver modul? Eller er det bedre at have en stor rolle til det hele? Og hvis ikke en rolle, hvor skal vi s\u00e5 skrive det \u2014 i pre eller i post?<\/p>\n<p><\/p>\n<p>Hvis der ikke er et velbegrundet svar p\u00e5 disse sp\u00f8rgsm\u00e5l, er det et tegn p\u00e5 mangel p\u00e5 intuition, alts\u00e5 de samme \"ustabile fundamenter\". Lad os finde ud af det. F\u00f8rst et kontrolsp\u00f8rgsm\u00e5l: Hvis play har <code>pre_tasks<\/code> og <code>post_tasks<\/code> (og ingen tasks eller roller), kan det s\u00e5 g\u00e5 galt, hvis jeg flytter den f\u00f8rste task fra <code>post_tasks<\/code> til slutningen af <code>pre_tasks<\/code>?<\/p>\n<p><\/p>\n<p>Selvf\u00f8lgelig antyder formuleringen af sp\u00f8rgsm\u00e5let, at det vil g\u00e5 galt. Men hvad pr\u00e6cist?<\/p>\n<p><\/p>\n<p>\u2026 H\u00e5ndtag. At l\u00e6se det grundl\u00e6ggende afsl\u00f8rer en vigtig fakta: alle h\u00e5ndtag flushes automatisk efter hver sektion. Dvs. alle opgaver udf\u00f8res fra <code>pre_tasks<\/code>udf\u00f8res, s\u00e5 alle handlere, der blev notify. Derefter udf\u00f8res alle roller og alle handlere, der blev notify i rollerne. S\u00e5 <code>post_tasks<\/code> og deres handlere.<\/p>\n<p><\/p>\n<p>Derfor, hvis du flytter en task fra <code>post_tasks<\/code> i <code>pre_tasks<\/code>, s\u00e5 kan du potentielt udf\u00f8re den f\u00f8r handleren. For eksempel, hvis i <code>pre_tasks<\/code> installeres og konfigureres <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/da\/server\/\"   title=\"webserveren\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1155\">webserveren<\/a>, og der sendes noget til den, vil flytning af denne task til sektionen <code>post_tasks<\/code> medf\u00f8re, at serveren ikke er startet p\u00e5 tidspunktet for \"afsendelsen\", og alt vil g\u00e5 galt. <code>pre_tasks<\/code> vil f\u00f8re til, at p\u00e5 tidspunktet for \"afsendelsen\" er serveren stadig ikke startet, og alt g\u00e5r i stykker.<\/p>\n<p><\/p>\n<p>giver os mulighed for at arbejde med resultaterne af rolleans udf\u00f8relse (inklusive handlere). <code>pre_tasks<\/code> og <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> En nysgerrig Ansible-ekspert vil sige til os, at der findes<\/p>\n<p><\/p>\n<p>meta: flush_handlers <code>, men hvorfor har vi brug for flush_handlers, hvis vi kan stole p\u00e5 r\u00e6kkef\u00f8lgen for udf\u00f8relsen af sektionerne i play? Desuden kan brugen af meta: flush_handlers give os uventede problemer med gentagne handlere, hvilket kan f\u00f8re til m\u00e6rkelige advarsler ved brug af<\/code>when <code>block<\/code> af <code>osv. Jo bedre du kender Ansible, desto flere nuancer kan du n\u00e6vne for \"smart\" l\u00f8sning. Og den enkle l\u00f8sning \u2014 brugen af naturlig adskillelse mellem pre\/roles\/post \u2014 medf\u00f8rer ikke nuancer.<\/code> osv. Jo mere du kender Ansible, jo flere nuancer vil du kunne n\u00e6vne for \"det smarte\" l\u00f8sning. Og en simpel l\u00f8sning - brugen af naturlig opdeling mellem pre\/roles\/post - skaber ikke nogen nuancer.<\/p>\n<p><\/p>\n<p>Og, lad os vende tilbage til vores 'foo'. Hvor skal vi placere det? I pre, post eller i roles? Det afh\u00e6nger tydeligvis af, om vi har brug for resultaterne fra handlerens arbejde for foo. Hvis ikke, er det ikke n\u00f8dvendigt at placere foo hverken i pre eller post - disse sektioner har en specifik betydning - at udf\u00f8re opgaver f\u00f8r og efter det prim\u00e6re kodearrangement.<\/p>\n<p><\/p>\n<p>Nu er svaret p\u00e5 sp\u00f8rgsm\u00e5let \"rolle eller opgave\" baseret p\u00e5, hvad der allerede findes i play - hvis der er tasks, s\u00e5 skal du tilf\u00f8je dem til tasks. Hvis der er roles, skal du lave en rolle (selv om det kun er en opgave). Jeg minder om, at tasks og roles ikke bruges samtidig.<\/p>\n<p><\/p>\n<p>Forst\u00e5elsen af Ansible's grundl\u00e6ggende aspekter giver velbegrundede svar p\u00e5 tilsyneladende smagsspecifikke sp\u00f8rgsm\u00e5l.<\/p>\n<p><\/p>\n<h1>Opgaver og roller (del to)<\/h1>\n<p><\/p>\n<p>Lad os nu diskutere situationen, hvor du lige er begyndt at skrive et playbook. Du skal lave foo, bar og baz. Er det tre opgaver, \u00e9n rolle eller tre roller? For at generalisere sp\u00f8rgsm\u00e5let: hvorn\u00e5r skal man begynde at skrive roller? Hvad er meningen med at skrive roller, n\u00e5r man kan skrive opgaver?\u2026 Hvad er en rolle?<\/p>\n<p><\/p>\n<p>En af de st\u00f8rste fejl (jeg har talt om det tidligere) er at antage, at en rolle er som en funktion i et bibliotek til et program. Hvordan ser en generel beskrivelse af en funktion ud? Den tager argumenter som input, interagerer med side\u00e5rsager, skaber sideeffekter og returnerer en v\u00e6rdi.<\/p>\n<p><\/p>\n<p>Nu, v\u00e6r opm\u00e6rksom. Hvad kan g\u00f8res i en rolle? At p\u00e5kalde sideeffekter - altid gerne, det er hele essensen af Ansible - at skabe sideeffekter. At have side\u00e5rsager? Simpelt. Men med \"at overf\u00f8re en v\u00e6rdi og returnere den\" - her er der ikke muligt. For det f\u00f8rste kan du ikke overf\u00f8re en v\u00e6rdi til en rolle. Du kan oprette en global variabel med en levetid svarende til play i vars sektionen for rollen. Du kan oprette en global variabel med en levetid i play inden for rollen. Eller endda med en levetid p\u00e5 playbooks (<code>set_fact<\/code>\/<code>register<\/code>). Men du kan ikke have \"lokale variabler\". Du kan ikke \"modtage en v\u00e6rdi\" og \"returnere den\".<\/p>\n<p><\/p>\n<p>Derfor f\u00f8lger det vigtigste: Du kan ikke skrive noget i Ansible og undg\u00e5 at skabe sideeffekter. \u00c6ndring af globale variabler er altid en sideeffekt for funktionen. I Rust, for eksempel, er \u00e6ndring af en global variabel \u2014 <code>unsafe<\/code>. I Ansible er den eneste metode at p\u00e5virke v\u00e6rdier for en rolle. Bem\u00e6rk de anvendte ord: ikke \"overf\u00f8re v\u00e6rdi til rolle\", men \"\u00e6ndre v\u00e6rdierne, som rollen bruger\". Der er ingen isolation mellem roller. Der er ingen isolation mellem opgaver og roller.<\/p>\n<p><\/p>\n<p>I alt: <strong>en rolle er ikke en funktion<\/strong>.<\/p>\n<p><\/p>\n<p>Hvad er der godt ved roller? For det f\u00f8rste har roller standardv\u00e6rdier (<code>\/default\/main.yaml<\/code>), for det andet har roller ekstra kataloger til opbevaring af filer.<\/p>\n<p><\/p>\n<p>Hvad er s\u00e5 godt ved standardv\u00e6rdier? Det er, at i Maslows ret forvr\u00e6ngede tabel over variabelprioriteter i Ansible er rolle-standarder de mindst prioriterede (minus kommandolinjeparametre fra Ansible). Det betyder, at hvis du \u00f8nsker at give standardv\u00e6rdier og ikke bekymre dig om, at de overskriver v\u00e6rdier fra inventar eller gruppevariabler, s\u00e5 er rolle-standarder det eneste rigtige sted for dig. (Jeg lyver lidt \u2013 der er ogs\u00e5 <code>|d(your_default_here)<\/code>, men hvis vi taler om station\u00e6re steder \u2013 s\u00e5 kun rolle-standarder).<\/p>\n<p><\/p>\n<p>Hvad er der ellers godt ved roller? Det er, at de har deres egne kataloger. Disse kataloger er til variabler, b\u00e5de permanente (dvs. beregnede for rollen) og dynamiske (der er en slags m\u00f8nster eller anti-m\u00f8nster \u2013 <code>include_vars<\/code> sammen med <code>{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml<\/code>.). Dette er kataloger til <code>files\/<\/code>, <code>templates\/<\/code>. Derudover g\u00f8r det det muligt at have sine egne moduler og plugins i roller (<code>library\/<\/code>). Men i forhold til opgaverne i playbooken (som ogs\u00e5 kan have alt dette), er fordelen her kun, at filerne ikke er i \u00e9n bunke, men i flere separate bunker.<\/p>\n<p><\/p>\n<p>Endnu en detalje: man kan pr\u00f8ve at lave roller, der vil v\u00e6re tilg\u00e6ngelige for genbrug (gennem galaxy). Efter introduktionen af samlinger kan distributionen af roller betragtes som n\u00e6sten glemt.<\/p>\n<p><\/p>\n<p>Dermed har roller to vigtige egenskaber: de har standarder (en unik egenskab), og de tillader at strukturere koden.<\/p>\n<p><\/p>\n<p>Tilbage til det oprindelige sp\u00f8rgsm\u00e5l: hvorn\u00e5r skal man lave opgaver og hvorn\u00e5r roller? Opgaver i playbooken bruges oftest enten som \"lim\" f\u00f8r\/efter roller, eller som en selvst\u00e6ndig byggeklods (s\u00e5 b\u00f8r der ikke v\u00e6re roller i koden). En bunke normale opgaver blandet med roller er klart klodset. Man b\u00f8r holde sig til en bestemt stil \u2013 enten opgaver eller roller. Roller giver opdeling af entiteter og standardv\u00e6rdier, mens opgaver tillader hurtigere l\u00e6sning af koden. Normalt placeres mere \"station\u00e6r\" (vigtig og kompleks) kode i roller, mens stilopgaver skrives som hj\u00e6lpe scripts.<\/p>\n<p><\/p>\n<p>Der er mulighed for at lave import_role som en opgave, men hvis du skriver det, s\u00e5 v\u00e6r forberedt p\u00e5 at skulle forklare, hvorfor du \u00f8nsker at g\u00f8re det.<\/p>\n<p><\/p>\n<p>Den nysgerrige l\u00e6ser kan sige, at roller kan importere roller, at roller kan have afh\u00e6ngigheder via galaxy.yml, og der er ogs\u00e5 den skr\u00e6mmende og forf\u00e6rdelige <code>include_role<\/code> \u2014 jeg minder om, at vi forbedrer vores f\u00e6rdigheder i grundl\u00e6ggende Ansible, ikke i rytmisk gymnastik.<\/p>\n<p><\/p>\n<h1>Handlere og opgaver<\/h1>\n<p><\/p>\n<p>Lad os diskutere en anden indlysende ting: handlere. At kunne bruge dem korrekt er n\u00e6sten en kunst. Hvad er forskellen mellem en handler og en opgave?<\/p>\n<p><\/p>\n<p>Da vi minder om grundprincipperne, s\u00e5 her er et eksempel:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group1\n  tasks:\n    - foo:\n      notify: handler1\n  handlers:\n     - name: handler1\n       bar:<\/code><\/pre>\n<p><\/p>\n<p>I rollen ligger handlerne i rolename\/handlers\/main.yaml. Handlerne deles mellem alle deltagere i spillet: pre\/post_tasks kan kalde handlerne fra rollen, og rollen kan kalde handlerne fra play. Men \"krydsrolle\" kald af handlere medf\u00f8rer meget st\u00f8rre forvirring end at gentage en triviel handler. (Endnu et element for bedste praksis \u2013 pr\u00f8v at undg\u00e5 gentagelser af navnene p\u00e5 handlerne).<\/p>\n<p><\/p>\n<p>Den grundl\u00e6ggende forskel er, at en opgave altid udf\u00f8res (idempotent) (plus\/minus tags og <code>block<\/code>), mens en handler \u2014 ved \u00e6ndring af tilstand (notify aktiveres kun, hvis der er sket \u00e6ndringer). Hvad kan det f\u00f8re til? For eksempel, at ved genstart, hvis der ikke var sket \u00e6ndringer, s\u00e5 bliver handleren ikke aktiveret. Og hvorfor kan det v\u00e6re, at vi har brug for at udf\u00f8re en handler, n\u00e5r der ikke var sket \u00e6ndringer i den genererende opgave? For eksempel, fordi noget gik i stykker, og der var sket \u00e6ndringer, men handleren blev ikke n\u00e5et. Fordi netv\u00e6rket var midlertidigt nede. Konfigurationen blev \u00e6ndret, tjenesten blev ikke genstartet. Ved n\u00e6ste k\u00f8rsel \u00e6ndres konfigurationen ikke, og tjenesten forbliver med den gamle version af konfigurationen.<\/p>\n<p><\/p>\n<p>Situationen med konfigurationen er ikke l\u00f8selig (mere pr\u00e6cist, man kan selv finde p\u00e5 en speciel genstartprotokol med filflag osv., men det er ikke l\u00e6ngere 'basic ansible' i nogen form). Derimod er der en anden hyppig historie: vi installerede en applikation, vi skrev dens <code>.service<\/code>-fil, og nu vil vi gerne have den <code>daemon_reload<\/code> og <code>state=started<\/code>. Og det naturlige sted for dette ser ud til at v\u00e6re handleren. Men hvis du g\u00f8r det til en opgave i slutningen af opgavelisten eller rollen, vil det blive idempotent udf\u00f8rt hver gang. Selv hvis playbooken fejler midtvejs. Dette l\u00f8ser bestemt ikke problemerne med restarted (det er ikke muligt at have en opgave med attributten restarted, da idempotens g\u00e5r tabt), men det er helt sikkert v\u00e6rd at angive state=started, den samlede stabilitet af playbooks \u00f8ges, da antallet af forbindelser og dynamisk tilstand reduceres.<\/p>\n<p><\/p>\n<p>Endnu en positiv egenskab ved handleren er, at den ikke sviner output. Der var ingen \u00e6ndringer \u2013 ingen un\u00f8dvendige skipped eller ok i output \u2013 lettere at l\u00e6se. Det er ogs\u00e5 en negativ egenskab \u2013 hvis du finder en trykfejl i en line\u00e6rt udf\u00f8rt task ved f\u00f8rste fors\u00f8g, vil handlerne kun blive udf\u00f8rt ved \u00e6ndring, dvs. under visse betingelser - meget sj\u00e6ldent. For eksempel, f\u00f8rste gang i dit liv fem \u00e5r senere. Og selvf\u00f8lgelig vil der v\u00e6re en trykfejl i navnet og alt vil g\u00e5 i stykker. Og anden gang kan de ikke startes \u2013 der er jo ingen \u00e6ndring.<\/p>\n<p><\/p>\n<p>Der skal tales s\u00e6rskilt om tilg\u00e6ngeligheden af variabler. For eksempel, hvis du notifierer for en opgave med en l\u00f8kke, hvad vil der s\u00e5 v\u00e6re i variablerne? Man kan g\u00e6tte det analytisk, men det er ikke altid trivielt, is\u00e6r hvis variablerne kommer fra forskellige steder.<\/p>\n<p><\/p>\n<p>S\u00e5 handlerne er langt mindre nyttige og langt mere problematiske, end det ser ud til. Hvis man kan skrive noget p\u00e6nt (uden krumspring) uden handlerne, er det bedst at g\u00f8re det uden dem. Hvis det ikke kan g\u00f8res p\u00e6nt \u2014 s\u00e5 er det bedre at bruge dem.<\/p>\n<p><\/p>\n<p>Den nysgerrige l\u00e6ser bem\u00e6rker med rette, at vi ikke har diskuteret <code>lytt<\/code>, at en handler kan kalde notify for en anden handler, at en handler kan inkludere import_tasks (som kan g\u00f8re include_role med with_items), at systemet med handlers i Ansible er Turing-komplet, at handlers fra include_role p\u00e5 en fascinerende m\u00e5de krydser med handlers fra play osv. \u2014 alt dette er \u00e5benlyst ikke \"grundl\u00e6ggende\").<\/p>\n<p><\/p>\n<p>Selvom der er en bestemt WTF, som faktisk er en funktion, og som man skal huske. Hvis du har en opgave, der udf\u00f8res med <code>delegate_to<\/code> og den har en notifikation, s\u00e5 udf\u00f8res den tilsvarende handler uden <code>delegate_to<\/code>, dvs. p\u00e5 den v\u00e6rt, hvortil play er tildelt. (Selvom handleren selvf\u00f8lgelig ogs\u00e5 kan have <code>delegate_to<\/code> det samme).<\/p>\n<p><\/p>\n<p>Separat vil jeg gerne sige et par ord om genanvendelige roller. Inden samlingerne kom, var ideen, at man kunne lave universelle roller, som man kunne <code>ansible-galaxy install<\/code> Og s\u00e5 k\u00f8rte det. Det fungerer p\u00e5 alle OS i alle varianter under alle forhold. S\u00e5dan er min mening: det virker ikke. Enhver rolle med massiv <code>include_vars<\/code>, med st\u00f8tte for 100500 tilf\u00e6lde er d\u00f8mt til at blive fyldt med corner case fejl. De kan d\u00e6kkes med massiv testning, men som med al testning, har du enten et cartesiansk produkt af inputv\u00e6rdier og en total funktion, eller du har \"d\u00e6kkede enkelte scenarier\". Min mening \u2014 det er langt bedre, hvis rollen er line\u00e6r (cyklomatisk kompleksitet 1).<\/p>\n<p><\/p>\n<p>Jo f\u00e6rre if'er (expr\u00e6sse eller deklarative \u2014 i form af <code>block<\/code> eller formen <code>include_vars<\/code> ud fra et s\u00e6t variabler), jo bedre er rollen. Nogle gange er det n\u00f8dvendigt at lave forgreninger, men jeg gentager, jo f\u00e6rre de er, jo bedre. S\u00e5 en tilsyneladende god rolle med galaxy (for det virker!), med en masse <code>block<\/code> kan v\u00e6re mindre foretrukket end en \"egen\" rolle best\u00e5ende af fem opgaver. \u00d8jeblikket, hvor en rolle med galaxy er bedre \u2014 er n\u00e5r du begynder at skrive noget. \u00d8jeblikket, hvor den bliver d\u00e5rligere \u2014 er n\u00e5r noget g\u00e5r i stykker, og du har mistanke om, at det er p\u00e5 grund af \"rollen med galaxy\". Du \u00e5bner den, og s\u00e5 er der fem inkluderede, otte task-lister og en bunke <code>block<\/code>\u2019er\u2026 Og det skal man finde ud af. I stedet for 5 opgaver som en line\u00e6r liste, hvor der ikke engang er noget at g\u00e5 i stykker.<\/p>\n<p><\/p>\n<h1>I de kommende dele<\/h1>\n<p><\/p>\n<ul>\n<li>Lidt om inventar, gruppevariabler, host_group_vars plugin, hostvars. Hvordan man fra spagetti binder den gordiske knude. Scope og precedence for variabler, Ansible's hukommelsesmodel. \"Hvor skal man s\u00e5 egentlig opbevare brugernavnet til databasen?\".<\/li>\n<li><code>jinja: {{ jinja }}<\/code> \u2014 nosql notype nosense bl\u00f8d plastelin. Det er overalt, selv der hvor du ikke forventer det. Lidt om <code>!!unsafe<\/code> og l\u00e6kker yaml.<\/li>\n<\/ul>\n<p>Kilde: <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\/da\/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=\"da_DK\" \/>\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\/da\/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\udd47Grundl\u00e6ggende Ansible, uden hvilke dine playbooks er en klump sammenklistret makaroni | ProHoster","description":"Jeg laver mange anmeldelser af andres kode i Ansible og skriver selv meget.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/87084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=87084"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/87084\/revisions"}],"predecessor-version":[{"id":162161,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/87084\/revisions\/162161"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=87084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=87084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=87084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}