{"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\/pl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","title":{"rendered":"Podstawy Ansible, bez kt\u00f3rych twoje playbooki to tylko zbitek lepkich makaron\u00f3w","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Zajmuj\u0119 si\u0119 wiele recenzjami obcego kodu w Ansible i du\u017co sam pisz\u0119. Analizuj\u0105c b\u0142\u0119dy (zar\u00f3wno cudze, jak i swoje), a tak\u017ce przeprowadzaj\u0105c pewn\u0105 liczb\u0119 rozm\u00f3w kwalifikacyjnych, zrozumia\u0142em podstawowy b\u0142\u0105d, kt\u00f3ry pope\u0142niaj\u0105 u\u017cytkownicy Ansible \u2014 wchodz\u0105 w z\u0142o\u017cono\u015bci, nie opanowawszy podstaw.<\/p>\n<p><\/p>\n<p>Aby naprawi\u0107 t\u0119 kosmiczn\u0105 niesprawiedliwo\u015b\u0107, postanowi\u0142em napisa\u0107 wprowadzenie do Ansible dla tych, kt\u00f3rzy ju\u017c go znaj\u0105. Ostrzegam, to nie jest streszczenie przewodnik\u00f3w, to d\u0142ugi tekst, w kt\u00f3rym jest du\u017co liter i \u017cadnych obrazk\u00f3w.<\/p>\n<p><\/p>\n<p>Oczekiwany poziom czytelnika \u2014 ju\u017c napisano kilka tysi\u0119cy linii YAML, co\u015b ju\u017c jest w produkcji, ale \"wszystko jest jako\u015b krzywo\".<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>Nazwy<\/h1>\n<p><\/p>\n<p>G\u0142\u00f3wny b\u0142\u0105d u\u017cytkownika Ansible polega na tym, \u017ce nie wie, jak co si\u0119 nazywa. Je\u015bli nie znasz nazw, nie mo\u017cesz zrozumie\u0107 tego, co jest napisane w dokumentacji. \u017bywy przyk\u0142ad: na rozmowie kwalifikacyjnej osoba, kt\u00f3ra rzekomo du\u017co pisa\u0142a w Ansible, nie potrafi\u0142a odpowiedzie\u0107 na pytanie \"z jakich element\u00f3w sk\u0142ada si\u0119 playbook?\". A kiedy zasugerowa\u0142em, \u017ce \"oczekiwano odpowiedzi, \u017ce playbook sk\u0142ada si\u0119 z play\", pad\u0142 zab\u00f3jczy komentarz \"my tego nie u\u017cywamy\". Ludzie pisz\u0105 w Ansible za pieni\u0105dze i nie u\u017cywaj\u0105 play. <em>W rzeczywisto\u015bci u\u017cywaj\u0105, ale nie wiedz\u0105, co to jest.<\/em><\/p>\n<p><\/p>\n<p>Zaczynajmy wi\u0119c od prostego: jak co nazywa si\u0119. Mo\u017ce to ju\u017c wiesz, a mo\u017ce nie, bo nie zwr\u00f3ci\u0142e\u015b uwagi czytaj\u0105c dokumentacj\u0119.<\/p>\n<p><\/p>\n<p>ansible-playbook wykonuje playbook. Playbook to plik z rozszerzeniem yml\/yaml, wewn\u0105trz kt\u00f3rego jest co\u015b takiego:<\/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>Ju\u017c zrozumieli\u015bmy, \u017ce ca\u0142y ten plik to playbook. Mo\u017cemy pokaza\u0107, gdzie s\u0105 role (roles), gdzie s\u0105 zadania (tasks). Ale gdzie tu jest play? I czym r\u00f3\u017cni si\u0119 play od role czy playbooka?<\/p>\n<p><\/p>\n<p>W dokumentacji to wszystko jest. I to jest pomijane. Pocz\u0105tkuj\u0105cy \u2014 poniewa\u017c jest tam zbyt wiele i nie zapami\u0119tasz wszystkiego naraz. Do\u015bwiadczeni \u2014 poniewa\u017c \"trywialne rzeczy\". Je\u015bli jeste\u015b do\u015bwiadczony \u2014 przepisuj te strony przynajmniej raz na p\u00f3\u0142 roku, a tw\u00f3j kod stanie si\u0119 o klas\u0119 lepszy.<\/p>\n<p><\/p>\n<p>Zatem zapami\u0119taj: Playbook to lista, sk\u0142adaj\u0105ca si\u0119 z play i <code>import_playbook<\/code>.<br \/>\nTo jest jedna play:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group1\n  roles:\n    - role1<\/code><\/pre>\n<p><\/p>\n<p>A to jest jeszcze jedna play:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group2,group3\n  tasks:\n    - debug:<\/code><\/pre>\n<p><\/p>\n<p>Czym jest play? Po co ona jest?<\/p>\n<p><\/p>\n<p>Play to kluczowy element dla playbooka, poniewa\u017c play i tylko play \u0142\u0105czy list\u0119 r\u00f3l i\/lub zada\u0144 z list\u0105 host\u00f3w, na kt\u00f3rych maj\u0105 by\u0107 wykonywane. W g\u0142\u0119bokich zakamarkach dokumentacji mo\u017cna znale\u017a\u0107 wzmiank\u0119 o <code>delegate_to<\/code>, lokalne wtyczki lookup, specyficzne ustawienia network-cli, jump-hosty itd. Umo\u017cliwiaj\u0105 one drobn\u0105 zmian\u0119 miejsca wykonania zada\u0144. Ale zapomnij o tym. Ka\u017cda z tych sprytnych opcji ma bardzo specyficzne zastosowania i z pewno\u015bci\u0105 nie s\u0105 one uniwersalne. A my m\u00f3wimy o podstawowych rzeczach, kt\u00f3re powinni zna\u0107 i u\u017cywa\u0107 wszyscy.<\/p>\n<p><\/p>\n<p>Je\u015bli chcesz \"co\u015b\" wykona\u0107 \"gdzie\u015b\" \u2014 piszesz play. Nie rol\u0119. Nie rol\u0119 z modu\u0142ami i delegatami. Bierzesz i piszesz play. W kt\u00f3rej w polu hosts wymieniasz, gdzie to wykona\u0107, a w roles\/tasks \u2014 co wykona\u0107.<\/p>\n<p><\/p>\n<p>Proste, prawda? A jak mo\u017ce by\u0107 inaczej?<\/p>\n<p><\/p>\n<p>Jednym z charakterystycznych moment\u00f3w, kiedy ludzie chc\u0105 zrobi\u0107 to nie przez play, jest \"rola, kt\u00f3ra wszystko konfiguruje\". Chc\u0105 mie\u0107 rol\u0119, kt\u00f3ra konfiguruje i <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/pl\/server\/dts-los-angeles\/\"   title=\"serwera\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3633\">serwera<\/a> pierwszego typu, i serwery drugiego typu.<\/p>\n<p><\/p>\n<p>Archetypowym przyk\u0142adem jest monitorowanie. Chcesz mie\u0107 rol\u0119 monitoring, kt\u00f3ra skonfiguruje monitorowanie. Rola monitoring jest przypisywana do host\u00f3w monitoruj\u0105cych (w odpowiednim play). Ale okazuje si\u0119, \u017ce do monitorowania musimy zainstalowa\u0107 pakiety na hostach, kt\u00f3re monitorujemy. Czemu nie u\u017cy\u0107 delegata? A jeszcze musimy skonfigurowa\u0107 iptables. Delegate? A jeszcze musimy napisa\u0107\/poprawi\u0107 konfiguracj\u0119 dla DBMS, aby monitorowanie dzia\u0142a\u0142o. Delegate! A je\u015bli wena przyjdzie, mo\u017cna zrobi\u0107 delegacj\u0119 <code>include_role<\/code> w zagnie\u017cd\u017conej p\u0119tli wed\u0142ug sprytnego filtru na li\u015bcie grup, a wewn\u0105trz <code>include_role<\/code> mo\u017cna jeszcze zrobi\u0107 <code>delegate_to<\/code> znowu. I si\u0119 zaczyna\u2026<\/p>\n<p><\/p>\n<p>S\u0142uszne \u017cyczenie \u2014 mie\u0107 jedn\u0105, jedyn\u0105 rol\u0119 monitoring, kt\u00f3ra \"wszystko robi\" \u2014 prowadzi nas do piek\u0142a, z kt\u00f3rego najcz\u0119\u015bciej jest tylko jedno wyj\u015bcie: wszystko przepisa\u0107 od zera.<\/p>\n<p><\/p>\n<p>Gdzie zasz\u0142a pomy\u0142ka? W chwili, gdy odkry\u0142e\u015b, \u017ce do wykonania zadania \"x\" na ho\u015bcie X musisz p\u00f3j\u015b\u0107 na host Y i zrobi\u0107 tam \"y\", powiniene\u015b wykona\u0107 proste \u0107wiczenie: p\u00f3j\u015b\u0107 i napisa\u0107 play, kt\u00f3ra na ho\u015bcie Y wykonuje y. Nie dopisywa\u0107 co\u015b do \"x\", a napisa\u0107 od zera. Nawet je\u015bli z zaszytymi zmiennymi.<\/p>\n<p><\/p>\n<p>Wydaje si\u0119, \u017ce w powy\u017cszych akapitach wszystko zosta\u0142o powiedziane poprawnie. Ale to nie jest tw\u00f3j przypadek! Poniewa\u017c chcesz napisa\u0107 kod wielokrotnego u\u017cytku, kt\u00f3ry jest DRY i przypomina bibliotek\u0119, i trzeba szuka\u0107 metody, jak to zrobi\u0107.<\/p>\n<p><\/p>\n<p>Tutaj czai si\u0119 jeszcze jeden powa\u017cny b\u0142\u0105d. B\u0142\u0105d, kt\u00f3ry przemieni\u0142 wiele projekt\u00f3w z do\u015b\u0107 dobrze napisanych (mo\u017cna lepiej, ale wszystko dzia\u0142a i \u0142atwo to rozbudowa\u0107) w absolutny koszmar, w kt\u00f3rym nawet autor nie potrafi si\u0119 odnale\u017a\u0107. To dzia\u0142a, ale chro\u0144 Bo\u017ce, \u017ceby co\u015b zmieni\u0107.<\/p>\n<p><\/p>\n<p>Ten b\u0142\u0105d brzmi tak: rola to funkcja biblioteczna. Ta analogia zniszczy\u0142a tyle dobrych inicjatyw, \u017ce po prostu smutno na to patrze\u0107. Rola to nie funkcja biblioteczna. Nie mo\u017ce wykonywa\u0107 oblicze\u0144 ani podejmowa\u0107 decyzji na poziomie play. Przypomnij mi, jakie decyzje podejmuje play?<\/p>\n<p><\/p>\n<p>Dzi\u0119kuj\u0119, masz racj\u0119. Play podejmuje decyzj\u0119 (dok\u0142adniej, zawiera informacje) o tym, jakie zadania i role maj\u0105 by\u0107 wykonywane na jakich hostach.<\/p>\n<p><\/p>\n<p>Je\u015bli delegujesz t\u0119 decyzj\u0119 na rol\u0119, a jeszcze z obliczeniami, skazujesz siebie (i tego, kto b\u0119dzie pr\u00f3bowa\u0142 zrozumie\u0107 tw\u00f3j kod) na \u017ca\u0142osne istnienie. Rola nie decyduje, gdzie ma by\u0107 wykonywana. Decyzj\u0119 o tym podejmuje play. Rola robi to, co jej powiedziano, tam, gdzie jej powiedziano.<\/p>\n<p><\/p>\n<p>Dlaczego programowanie w Ansible jest niebezpieczne i czemu COBOL jest lepszy od Ansible, om\u00f3wimy w rozdziale o zmiennych i jinja. Na razie powiedzmy jedno \u2014 ka\u017cde twoje obliczenie zostawia za sob\u0105 nieusuwalny \u015blad zmian globalnych zmiennych, i nic z tym nie mo\u017cesz zrobi\u0107. Gdy tylko dwa \"\u015blady\" si\u0119 przeci\u0119\u0142y \u2014 wszystko stracone.<\/p>\n<p><\/p>\n<p>Uwaga dla dociekliwych: rola z pewno\u015bci\u0105 mo\u017ce wp\u0142ywa\u0107 na kontrol\u0119 przep\u0142ywu. Istniej\u0105 <code>delegate_to<\/code> i ma sensowne zastosowania. S\u0105 <code>meta: end host\/play<\/code>. Ale! Pami\u0119taj, uczymy si\u0119 podstaw? Zapomnieli\u015bcie o <code>delegate_to<\/code>. M\u00f3wimy o najprostszej i najpi\u0119kniejszej strukturze kodu w Ansible. Kt\u00f3ry jest \u0142atwy do przeczytania, \u0142atwy do napisania, \u0142atwy do debugowania, \u0142atwy do testowania i \u0142atwy do rozszerzenia. Tak wi\u0119c, jeszcze raz:<\/p>\n<p><\/p>\n<p><strong>play i tylko play decyduje, na jakich hostach co ma by\u0107 wykonywane.<\/strong><\/p>\n<p><\/p>\n<p>W tej sekcji wyja\u015bnili\u015bmy opozycj\u0119 mi\u0119dzy play a rol\u0105. Teraz porozmawiajmy o relacjach tasks vs role.<\/p>\n<p><\/p>\n<h1>Zadania i role<\/h1>\n<p><\/p>\n<p>Rozwa\u017cmy 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>Za\u0142\u00f3\u017cmy, \u017ce musisz zrobi\u0107 foo. I wygl\u0105da to tak: <code>foo: name=foobar state=present<\/code>. Gdzie to napisa\u0107? w pre? post? Tworzy\u0107 rol\u0119?<\/p>\n<p><\/p>\n<p>\u2026 A gdzie si\u0119 podzia\u0142y zadania?<\/p>\n<p><\/p>\n<p>Zaczynamy od podstaw \u2014 urz\u0105dzenia play. Je\u015bli nie czujesz si\u0119 w tym pewnie, nie mo\u017cesz traktowa\u0107 play jako fundamentu dla wszystkiego innego, a tw\u00f3j wynik staje si\u0119 \"w\u0105t\u0142y\".<\/p>\n<p><\/p>\n<p>Urz\u0105dzenie play: dyrektywa hosts, ustawienia samego play oraz sekcje pre_tasks, tasks, roles, post_tasks. Pozosta\u0142e parametry dla play nie s\u0105 teraz dla nas wa\u017cne.<\/p>\n<p><\/p>\n<p>Kolejno\u015b\u0107 ich sekcji z zadaniami i rolami: <code>pre_tasks<\/code>, <code>roles<\/code>, <code>tasks<\/code>, <code>post_tasks<\/code>. Poniewa\u017c semantycznie kolejno\u015b\u0107 wykonania mi\u0119dzy <code>tasks<\/code> i <code>roles<\/code> nie jest jasna, najlepsze praktyki m\u00f3wi\u0105, \u017ce dodajemy sekcj\u0119 <code>tasks<\/code>, tylko je\u015bli nie ma <code>roles<\/code>. Je\u015bli jest <code>roles<\/code>, to wszystkie przylegaj\u0105ce zadania umieszczane s\u0105 w sekcjach <code>pre_tasks<\/code>\/<code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Pozostaje tylko to, co semantycznie jest jasne: najpierw <code>pre_tasks<\/code>, potem <code>roles<\/code>, potem <code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Ale wci\u0105\u017c nie odpowiedzieli\u015bmy na pytanie: gdzie wywo\u0142a\u0107 modu\u0142 <code>foo<\/code> napisa\u0107? Czy musimy pisa\u0107 ca\u0142\u0105 rol\u0119 dla ka\u017cdego modu\u0142u? A mo\u017ce lepiej mie\u0107 jedn\u0105 du\u017c\u0105 rol\u0119 dla wszystkiego? A je\u015bli nie rola, to gdzie pisa\u0107 \u2014 w pre czy w post?<\/p>\n<p><\/p>\n<p>Je\u015bli nie ma przekonywuj\u0105cej odpowiedzi na te pytania, oznacza to brak intuicji, czyli te w\u0105t\u0142e fundamenty. Zajmijmy si\u0119 tym. Na pocz\u0105tek pytanie kontrolne: Je\u015bli play ma... <code>pre_tasks<\/code> i <code>post_tasks<\/code> (i nie ma ani tasks, ani roles), to czy co\u015b mo\u017ce si\u0119 zepsu\u0107, je\u015bli przenios\u0119 pierwsze zadanie z <code>post_tasks<\/code> na koniec <code>pre_tasks<\/code>?<\/p>\n<p><\/p>\n<p>Oczywi\u015bcie, sformu\u0142owanie pytania sugeruje, \u017ce co\u015b si\u0119 zepsuje. Ale co dok\u0142adnie?<\/p>\n<p><\/p>\n<p>... Handler\u00f3w. Zrozumienie podstaw ujawnia wa\u017cny fakt: wszystkie handlery s\u0105 automatycznie flush'owane po ka\u017cdej sekcji. Tzn. wykonywane s\u0105 wszystkie zadania z... <code>pre_tasks<\/code>, a potem wszystkie handlery, kt\u00f3re by\u0142y notify. Nast\u0119pnie wykonuj\u0105 si\u0119 wszystkie role i wszystkie handlery, kt\u00f3re by\u0142y notify w rolach. Nast\u0119pnie <code>post_tasks<\/code> i ich handlery.<\/p>\n<p><\/p>\n<p>W ten spos\u00f3b, je\u015bli przeniesiesz zadanie z <code>post_tasks<\/code> do <code>pre_tasks<\/code>, to potencjalnie wykonasz je przed wykonaniem handler'a. Na przyk\u0142ad, je\u015bli w... <code>pre_tasks<\/code> jest instalowany i konfigurowany <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/pl\/server\/\"   title=\"serwer www\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1155\">serwer www<\/a>, a w <code>post_tasks<\/code> co\u015b jest do niego przesy\u0142ane, to przeniesienie tego zadania do sekcji <code>pre_tasks<\/code> prowadzi to do sytuacji, w kt\u00f3rej w momencie \"wysy\u0142ania\" serwer nie b\u0119dzie jeszcze uruchomiony i wszystko si\u0119 zepsuje.<\/p>\n<p><\/p>\n<p>A teraz pomy\u015blmy jeszcze raz, po co nam <code>pre_tasks<\/code> i <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> pozwoli nam pracowa\u0107 z wynikami wykonania r\u00f3l (w tym handler\u00f3w).<\/p>\n<p><\/p>\n<p>Zawzi\u0119ty znawca Ansible powie nam, \u017ce jest <code>meta: flush_handlers<\/code>, ale po co nam flush_handlers, skoro mo\u017cemy polega\u0107 na kolejno\u015bci wykonania sekcji w play? Co wi\u0119cej, u\u017cycie meta: flush_handlers mo\u017ce przynie\u015b\u0107 nam niespodziewane powtarzaj\u0105ce si\u0119 handlery, a w przypadku u\u017cycia <code>when<\/code> u <code>block<\/code> itd. Im lepiej znasz ansible, tym wi\u0119cej szczeg\u00f3\u0142\u00f3w mo\u017cesz nazwa\u0107 dla \"sprytnego\" rozwi\u0105zania. A proste rozwi\u0105zanie \u2014 wykorzystanie naturalnego podzia\u0142u mi\u0119dzy pre\/roles\/post \u2014 nie budzi w\u0105tpliwo\u015bci.<\/p>\n<p><\/p>\n<p>I wracaj\u0105c do naszego 'foo'. Gdzie go umie\u015bci\u0107? W pre, post czy w roles? Oczywi\u015bcie, to zale\u017cy od tego, czy potrzebujemy wynik\u00f3w pracy handlera dla foo. Je\u015bli ich nie ma, foo nie trzeba umieszcza\u0107 ani w pre, ani w post \u2014 te sekcje maj\u0105 specjalne znaczenie \u2014 wykonywanie zada\u0144 przed i po g\u0142\u00f3wnym bloku kodu.<\/p>\n<p><\/p>\n<p>Teraz odpowied\u017a na pytanie \"rola czy zadanie\" sprowadza si\u0119 do tego, co ju\u017c istnieje w play \u2014 je\u015bli s\u0105 tam tasks, trzeba je dopisa\u0107 do tasks. Je\u015bli s\u0105 roles \u2014 trzeba stworzy\u0107 rol\u0119 (nawet z jednego tasku). Przypominam, tasks i roles nie s\u0105 u\u017cywane jednocze\u015bnie.<\/p>\n<p><\/p>\n<p>Zrozumienie podstaw Ansible\u2019a daje uzasadnione odpowiedzi na, wydawa\u0142oby si\u0119, pytania o charakterze subiektywnym.<\/p>\n<p><\/p>\n<h1>Zadania i role (cz\u0119\u015b\u0107 druga)<\/h1>\n<p><\/p>\n<p>Teraz om\u00f3wimy sytuacj\u0119, gdy dopiero zaczynasz pisa\u0107 playbook. Musisz zrobi\u0107 foo, bar i baz. To trzy zadania, jedna rola czy trzy role? Generalizuj\u0105c pytanie: w kt\u00f3rym momencie nale\u017cy zacz\u0105\u0107 pisa\u0107 role? Jaki jest sens pisania r\u00f3l, skoro mo\u017cna pisa\u0107 zadania?\u2026 Czym jest rola?<\/p>\n<p><\/p>\n<p>Jednym z najwi\u0119kszych b\u0142\u0119d\u00f3w (ju\u017c o tym wspomnia\u0142em) jest mylenie roli z funkcj\u0105 w bibliotece programu. Jak wygl\u0105da og\u00f3lne opisanie funkcji? Przyjmuje argumenty na wej\u015bciu, oddzia\u0142uje na side causes, wywo\u0142uje side effects, zwraca warto\u015b\u0107.<\/p>\n<p><\/p>\n<p>Teraz, uwaga. Co mo\u017cna zrobi\u0107 w roli? Wywo\u0142ywa\u0107 efekty uboczne \u2014 zawsze prosz\u0119, to jest istota ca\u0142ego Ansibla \u2014 generowanie efekt\u00f3w ubocznych. Mie\u0107 przyczyny uboczne? Elementarne. Ale z \"przekaza\u0107 warto\u015b\u0107 i zwr\u00f3ci\u0107 j\u0105\" \u2014 tutaj ju\u017c nie. Po pierwsze, nie mo\u017cesz przekaza\u0107 warto\u015bci do roli. Mo\u017cesz ustawi\u0107 zmienn\u0105 globaln\u0105 o czasie \u017cycia r\u00f3wnym play w sekcji vars dla roli. Mo\u017cesz ustawi\u0107 zmienn\u0105 globaln\u0105 o czasie \u017cycia w play wewn\u0105trz roli. Lub nawet o czasie \u017cycia playbooka (<code>set_fact<\/code>\/<code>register<\/code>). Ale nie mo\u017cesz mie\u0107 \"zmiennych lokalnych\". Nie mo\u017cesz \"przyjmowa\u0107 warto\u015bci\" i \"zwraca\u0107 jej\".<\/p>\n<p><\/p>\n<p>Z tego wynika najwa\u017cniejsze: nie mo\u017cna w Ansible napisa\u0107 czego\u015b i nie wywo\u0142a\u0107 side effects. Zmiana zmiennych globalnych \u2014 to zawsze side effect dla funkcji. W Rust, na przyk\u0142ad, zmiana zmiennej globalnej to <code>unsafe<\/code>. W Ansible jest to jedyny spos\u00f3b na wp\u0142ywanie na warto\u015bci dla roli. Zauwa\u017c, jak u\u017cywane s\u0105 s\u0142owa: nie &quot;przekaza\u0107 warto\u015b\u0107 do roli&quot;, ale &quot;zmieni\u0107 warto\u015bci, z kt\u00f3rych korzysta rola&quot;. Nie ma izolacji mi\u0119dzy rolami. Nie ma izolacji mi\u0119dzy zadaniami a rolami.<\/p>\n<p><\/p>\n<p>Podsumowuj\u0105c: <strong>rola \u2014 to nie funkcja<\/strong>.<\/p>\n<p><\/p>\n<p>Co dobrego jest w roli? Po pierwsze, rola ma warto\u015bci domy\u015blne (<code>\/default\/main.yaml<\/code>), po drugie, rola ma dodatkowe katalogi do przechowywania plik\u00f3w.<\/p>\n<p><\/p>\n<p>Czym wi\u0119c s\u0105 dobre warto\u015bci domy\u015blne? Tym, \u017ce w mocno zniekszta\u0142conej tabeli priorytet\u00f3w zmiennych wed\u0142ug Maslowa, domy\u015blne warto\u015bci roli \u2014 s\u0105 najbardziej nisko priorytetowe (z wyj\u0105tkiem parametr\u00f3w wiersza polece\u0144 Ansible). To oznacza, \u017ce je\u015bli musisz dostarczy\u0107 warto\u015bci domy\u015blne i nie martwi\u0107 si\u0119, \u017ce zast\u0105pi\u0105 warto\u015bci z inwentarza lub zmiennych grupowych, to domy\u015blne warto\u015bci roli to jedyne w\u0142a\u015bciwe miejsce dla Ciebie. (Troszk\u0119 k\u0142ami\u0119 \u2014 jest jeszcze <code>|d(your_default_here)<\/code>, ale je\u015bli m\u00f3wimy o sta\u0142ych miejscach \u2014 to tylko domy\u015blne warto\u015bci r\u00f3l).<\/p>\n<p><\/p>\n<p>Co jeszcze jest dobre w rolach? To, \u017ce maj\u0105 swoje katalogi. S\u0105 to katalogi dla zmiennych, zar\u00f3wno sta\u0142ych (tzn. obliczanych dla roli), jak i dynamicznych (jest taki wzorzec lub antywzorzec \u2014 <code>include_vars<\/code> wraz z <code>{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml<\/code>.). To s\u0105 katalogi dla <code>files\/<\/code>, <code>templates\/<\/code>. Dodatkowo pozwala to na posiadanie w\u0142asnych modu\u0142\u00f3w i wtyczek w rolach (<code>library\/<\/code>). Jednak w por\u00f3wnaniu z zadaniami w playbooku (kt\u00f3ry te\u017c mo\u017ce mie\u0107 to wszystko), korzy\u015b\u0107 tkwi tylko w tym, \u017ce pliki s\u0105 podzielone na kilka osobnych zbior\u00f3w, a nie wrzucone do jednego.<\/p>\n<p><\/p>\n<p>Jeszcze jeden szczeg\u00f3\u0142: mo\u017cna pr\u00f3bowa\u0107 tworzy\u0107 role, kt\u00f3re b\u0119d\u0105 dost\u0119pne do ponownego u\u017cycia (przez galaxy). Po wprowadzeniu kolekcji dystrybucja r\u00f3l mo\u017ce by\u0107 uwa\u017cana za prawie zapomnian\u0105.<\/p>\n<p><\/p>\n<p>W ten spos\u00f3b role maj\u0105 dwie wa\u017cne cechy: maj\u0105 domy\u015blne warto\u015bci (unikalna cecha) i pozwalaj\u0105 strukturyzowa\u0107 kod.<\/p>\n<p><\/p>\n<p>Wracaj\u0105c do pierwotnego pytania: kiedy stosowa\u0107 zadania, a kiedy role? Zadania w playbooku s\u0105 najcz\u0119\u015bciej u\u017cywane jako &quot;klej&quot; przed\/po rolach, lub jako samodzielny element konstrukcyjny (wtedy w kodzie nie powinno by\u0107 r\u00f3l). Mieszanie normalnych zada\u0144 z rolami to wyra\u017ana niechlujno\u015b\u0107. Nale\u017cy stosowa\u0107 konkretny styl \u2014 albo zadania, albo role. Role oferuj\u0105 podzia\u0142 dla encji i domy\u015blne warto\u015bci, zadania pozwalaj\u0105 szybciej czyta\u0107 kod. Zwykle w rolach umieszczany jest bardziej &quot;sta\u0142y&quot; (wa\u017cny i skomplikowany) kod, a w stylu zada\u0144 pisane s\u0105 pomocnicze skrypty.<\/p>\n<p><\/p>\n<p>Mo\u017cna zrobi\u0107 import_role jako zadanie, ale je\u015bli to robisz, przygotuj si\u0119 na wyja\u015bnienie dla w\u0142asnego poczucia estetyki, dlaczego chcesz to robi\u0107.<\/p>\n<p><\/p>\n<p>Dociekliwy czytelnik mo\u017ce powiedzie\u0107, \u017ce role mog\u0105 importowa\u0107 role, role mog\u0105 mie\u0107 zale\u017cno\u015bci przez galaxy.yml, a ponadto istnieje co\u015b strasznego i przera\u017caj\u0105cego. <code>include_role<\/code> Przypominam, \u017ce rozwijamy umiej\u0119tno\u015bci w podstawowym Ansible, a nie w gimnastyce artystycznej.<\/p>\n<p><\/p>\n<h1>Handlerzy i zadania<\/h1>\n<p><\/p>\n<p>Porozmawiajmy o jeszcze jednej oczywistej kwestii: handlerzy. Umiej\u0119tno\u015b\u0107 ich odpowiedniego u\u017cycia to niemal sztuka. Jaka jest r\u00f3\u017cnica mi\u0119dzy handlerem a zadaniem?<\/p>\n<p><\/p>\n<p>Poniewa\u017c przypominamy sobie podstawy, oto przyk\u0142ad:<\/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>Handler\u2019y roli znajduj\u0105 si\u0119 w rolename\/handlers\/main.yaml. Handler\u2019y s\u0105 dzielone mi\u0119dzy wszystkimi uczestnikami play: pre\/post_tasks mog\u0105 wywo\u0142ywa\u0107 handler\u2019y roli, a rola mo\u017ce wywo\u0142ywa\u0107 handler\u2019y z play. Jednak &quot;cross-rolowe&quot; wywo\u0142ania handler\u2019\u00f3w powoduj\u0105 znacznie wi\u0119ksze zaskoczenie, ni\u017c powtarzanie trywialnego handler\u2019a. (Kolejny element najlepszych praktyk \u2014 staraj si\u0119 unika\u0107 powtarzania nazw handler\u2019\u00f3w).<\/p>\n<p><\/p>\n<p>Podstawowa r\u00f3\u017cnica polega na tym, \u017ce zadanie jest zawsze wykonywane (idempotentnie) (plus\/minus tagi i <code>when<\/code>), a handler \u2014 w zale\u017cno\u015bci od zmiany stanu (notify dzia\u0142a tylko, je\u015bli by\u0142o zmienione). Co z tego wynika? Na przyk\u0142ad, \u017ce przy kolejnym uruchomieniu, je\u015bli nie by\u0142o zmiany, to nie b\u0119dzie r\u00f3wnie\u017c handlera. A dlaczego mo\u017ce by\u0107 tak, \u017ce musimy uruchomi\u0107 handler, kiedy w zadaniu macierzystym nie by\u0142o zmiany? Na przyk\u0142ad dlatego, \u017ce co\u015b si\u0119 zepsu\u0142o i zmiana by\u0142a, ale do handlera wykonanie nie dotar\u0142o. Na przyk\u0142ad, poniewa\u017c sie\u0107 chwilowo zawiod\u0142a. Konfiguracja zmieni\u0142a si\u0119, us\u0142uga nie zosta\u0142a uruchomiona ponownie. Przy nast\u0119pnym uruchomieniu konfiguracja ju\u017c si\u0119 nie zmienia, a us\u0142uga pozostaje z star\u0105 wersj\u0105 konfiguracji.<\/p>\n<p><\/p>\n<p>Sytuacja z konfiguracj\u0105 jest nierozwi\u0105zywalna (w\u0142a\u015bciwie, mo\u017cna wymy\u015bli\u0107 specjalny protok\u00f3\u0142 ponownego uruchamiania z flagami plik\u00f3w itd., ale to ju\u017c nie jest \u2018basic ansible\u2019 w \u017cadnej postaci). Za to jest inna cz\u0119sta historia: zainstalowali\u015bmy aplikacj\u0119, zapisali\u015bmy j\u0105, <code>.service<\/code>-plik, i teraz chcemy go <code>daemon_reload<\/code> i <code>stan=uruchomiony<\/code>. Naturalnym miejscem dla tego wydaje si\u0119 by\u0107 handler. Ale je\u015bli zrobisz z niego task na ko\u0144cu listy zada\u0144 lub rol\u0119, to b\u0119dzie wykonywany idempotentnie za ka\u017cdym razem. Nawet je\u015bli playbook si\u0119 zepsuje w po\u0142owie. To nie rozwi\u0105zuje problemu restarted (nie mo\u017cna zrobi\u0107 tasku z atrybutem restarted, poniewa\u017c traci si\u0119 idempotentno\u015b\u0107), ale zdecydowanie warto ustawi\u0107 state=started, og\u00f3lna stabilno\u015b\u0107 playbook\u00f3w wzrasta, poniewa\u017c zmniejsza si\u0119 liczba zale\u017cno\u015bci i dynamicznych stan\u00f3w.<\/p>\n<p><\/p>\n<p>Kolejn\u0105 pozytywn\u0105 cech\u0105 handler\u2019a jest to, \u017ce nie zatyka on wyj\u015bcia. Nie by\u0142o zmian \u2014 brak zb\u0119dnych skipped lub ok w wyj\u015bciu \u2014 \u0142atwiej to przeczyta\u0107. To r\u00f3wnie\u017c jest negatywn\u0105 cech\u0105 \u2014 je\u015bli znajdziesz liter\u00f3wk\u0119 w liniowo wykonywanej task\u2019ie przy pierwszym uruchomieniu, to handler\u2019y b\u0119d\u0105 wykonywane tylko przy changed, czyli pod pewnymi warunkami \u2014 bardzo rzadko. Na przyk\u0142ad, pierwszy raz w \u017cyciu po pi\u0119ciu latach. I, oczywi\u015bcie, tam b\u0119dzie liter\u00f3wka w nazwie i wszystko si\u0119 zepsuje. A drugi raz ich nie uruchomisz \u2014 bo changed nie ma.<\/p>\n<p><\/p>\n<p>Osobno trzeba porozmawia\u0107 o dost\u0119pno\u015bci zmiennych. Na przyk\u0142ad, je\u015bli u\u017cywasz notify dla tasku z p\u0119tl\u0105, to co b\u0119dzie w zmiennych? Mo\u017cna to dedukowa\u0107 analitycznie, ale nie zawsze jest to trywialne, zw\u0142aszcza je\u015bli zmienne pochodz\u0105 z r\u00f3\u017cnych \u017ar\u00f3de\u0142.<\/p>\n<p><\/p>\n<p>Zatem handlery s\u0105 znacznie mniej przydatne i znacznie bardziej problematyczne, ni\u017c si\u0119 wydaje. Je\u015bli mo\u017cna co\u015b napisa\u0107 \u0142adnie (bez trik\u00f3w) bez handler\u00f3w, lepiej zrobi\u0107 to bez nich. Je\u015bli nie wychodzi \u0142adnie \u2014 lepiej ju\u017c z nimi.<\/p>\n<p><\/p>\n<p>Skrupulatny czytelnik s\u0142usznie zauwa\u017ca, \u017ce nie om\u00f3wili\u015bmy <code>listen<\/code>, \u017ce handler mo\u017ce wywo\u0142a\u0107 notify dla innego handlera, \u017ce handler mo\u017ce zawiera\u0107 import_tasks (kt\u00f3ry mo\u017ce robi\u0107 include_role z with_items), \u017ce system handler\u00f3w w Ansible jest turingowo pe\u0142ny, \u017ce handlery z include_role niezwykle interesuj\u0105co krzy\u017cuj\u0105 si\u0119 z handlerami z play itd. \u2014 to wszystko zdecydowanie nie s\u0105 \"podstawy\".<\/p>\n<p><\/p>\n<p>Chocia\u017c jest jeden okre\u015blony WTF, kt\u00f3ry tak naprawd\u0119 jest funkcj\u0105, o kt\u00f3rej nale\u017cy pami\u0119ta\u0107. Je\u015bli masz task, kt\u00f3ry wykonuje si\u0119 z <code>delegate_to<\/code> i ma notify, to odpowiedni handler jest wykonywany bez <code>delegate_to<\/code>, tzn. na ho\u015bcie, na kt\u00f3rym przypisana jest play. (Chocia\u017c handler mo\u017ce mie\u0107 r\u00f3wnie\u017c <code>delegate_to<\/code> to).<\/p>\n<p><\/p>\n<p>Osobno chc\u0119 powiedzie\u0107 kilka s\u0142\u00f3w o reusable roles. Do czasu pojawienia si\u0119 kolekcji istnia\u0142a idea, \u017ce mo\u017cna stworzy\u0107 uniwersalne role, kt\u00f3re mo\u017cna <code>ansible-galaxy install<\/code> i pojecha\u0142. Dzia\u0142a na wszystkich systemach operacyjnych w ka\u017cdej sytuacji. Moje zdanie: to nie dzia\u0142a. Ka\u017cda rola z masow\u0105 <code>include_vars<\/code>, wspieraj\u0105c 100500 przypadk\u00f3w, jest skazana na otch\u0142anie bug\u00f3w corner case. Mo\u017cna je zaklepa\u0107 masywnym testowaniem, ale jak z ka\u017cdym testowaniem, albo macie iloczyn kartezja\u0144ski warto\u015bci wej\u015bciowych i funkcj\u0119 totaln\u0105, albo \"pokryte s\u0105 poszczeg\u00f3lne scenariusze\". Moim zdaniem \u2014 znacznie lepiej, gdy rola jest liniowa (z\u0142o\u017cono\u015b\u0107 cyklomatyczna 1).<\/p>\n<p><\/p>\n<p>Im mniej if\u00f3w (jawnych lub deklaratywnych \u2014 w formie <code>when<\/code> lub formie <code>include_vars<\/code> na zestaw zmiennych), tym lepiej rola. Czasami trzeba robi\u0107 rozga\u0142\u0119zienia, ale, powtarzam, im ich mniej, tym lepiej. Tak wi\u0119c wydaje si\u0119, \u017ce dobra rola z galaxy (dzia\u0142a przecie\u017c!) z mn\u00f3stwem <code>when<\/code> mo\u017ce by\u0107 mniej preferowana ni\u017c \"w\u0142asna\" rola z pi\u0119ciu zada\u0144. Moment, w kt\u00f3rym rola z galaxy jest lepsza \u2014 to gdy zaczynasz co\u015b pisa\u0107. Moment, w kt\u00f3rym staje si\u0119 gorsza \u2014 to gdy co\u015b si\u0119 psuje i masz podejrzenie, \u017ce to przez \"rol\u0119 z galaxy\". Otwierasz j\u0105, a tam pi\u0119\u0107 inklud\u00f3w, osiem list zada\u0144 i sterta <code>when<\/code>\u2019\u00f3w\u2026 I trzeba si\u0119 w tym ogarn\u0105\u0107. Zamiast 5 zada\u0144 w liniowej li\u015bcie, w kt\u00f3rej nie ma nic do zepsucia.<\/p>\n<p><\/p>\n<h1>W nast\u0119pnych cz\u0119\u015bciach<\/h1>\n<p><\/p>\n<ul>\n<li>Troch\u0119 o inwentarzu, grupowych zmiennych, pluginie host_group_vars, hostvars. Jak ze spaghetti zwi\u0105za\u0107 Gordyjski w\u0119ze\u0142. Zakres i priorytet zmiennych, model pami\u0119ci Ansible. \"Gdzie wi\u0119c przechowywa\u0107 nazw\u0119 u\u017cytkownika dla bazy danych?\".<\/li>\n<li><code>jinja: {{ jinja }}<\/code> \u2014 nosql notype nosense mi\u0119kka plastelina. Jest wsz\u0119dzie, nawet tam, gdzie si\u0119 go nie spodziewasz. Troch\u0119 o <code>!!unsafe<\/code> i smacznym yaml.<\/li>\n<\/ul>\n<p>\u0179r\u00f3d\u0142o: <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.1.1 - 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\/pl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\/pl\/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\udd47Podstawy Ansible, bez kt\u00f3rych twoje playbooki to kulka sklejonych makaron\u00f3w | ProHoster","description":"Du\u017co recenzuj\u0119 cudzego kodu w Ansible i sam wiele pisz\u0119.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/87084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=87084"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/87084\/revisions"}],"predecessor-version":[{"id":162161,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/87084\/revisions\/162161"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=87084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=87084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=87084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}