{"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\/fr\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","title":{"rendered":"Les bases d'Ansible, sans lesquelles vos playbooks ne sont qu'un amas de p\u00e2tes coll\u00e9es","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Je fais beaucoup de revues de code sur Ansible et j'\u00e9cris beaucoup moi-m\u00eame. Au cours de l'analyse des erreurs (celles des autres comme les miennes), ainsi que lors de plusieurs entretiens, j'ai compris la principale erreur commise par les utilisateurs d'Ansible : ils s'attaquent \u00e0 des choses complexes sans avoir ma\u00eetris\u00e9 les bases.<\/p>\n<p><\/p>\n<p>Pour rem\u00e9dier \u00e0 cette injustice universelle, j'ai d\u00e9cid\u00e9 d'\u00e9crire une introduction \u00e0 Ansible pour ceux qui le connaissent d\u00e9j\u00e0. Je pr\u00e9viens, ce n'est pas un r\u00e9sum\u00e9 de manuels, c'est un long article avec beaucoup de mots et pas d'images.<\/p>\n<p><\/p>\n<p>Le niveau de lecteur attendu est celui qui a d\u00e9j\u00e0 \u00e9crit plusieurs milliers de lignes de YAML, qui a d\u00e9j\u00e0 mis quelque chose en production, mais qui trouve que \u00ab c'est un peu tordu \u00bb.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>Noms<\/h1>\n<p><\/p>\n<p>L'erreur principale des utilisateurs d'Ansible est de ne pas savoir comment les choses s'appellent. Si vous ne connaissez pas les noms, vous ne pouvez pas comprendre ce qui est \u00e9crit dans la documentation. Un exemple vivant : lors d'un entretien, une personne, qui semblait avoir beaucoup \u00e9crit sur Ansible, n'a pas pu r\u00e9pondre \u00e0 la question \u00ab de quels \u00e9l\u00e9ments se compose un playbook ? \u00bb. Et quand j'ai sugg\u00e9r\u00e9 que \u00ab la r\u00e9ponse attendue \u00e9tait que le playbook se compose de plays \u00bb, il a suivi un commentaire d\u00e9vastateur \u00ab nous n'utilisons pas cela \u00bb. Les gens \u00e9crivent sur Ansible pour l'argent et n'utilisent pas de plays. <em>En r\u00e9alit\u00e9, ils les utilisent, mais ne savent pas ce que c'est.<\/em><\/p>\n<p><\/p>\n<p>Commen\u00e7ons donc par le simple : comment chaque chose s'appelle. Peut-\u00eatre que vous le savez, peut-\u00eatre que non, parce que vous n'avez pas fait attention en lisant la documentation.<\/p>\n<p><\/p>\n<p>ansible-playbook ex\u00e9cute le playbook. Un playbook est un fichier avec l'extension .yml\/.yaml, \u00e0 l'int\u00e9rieur duquel il y a quelque chose comme :<\/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>Nous avons d\u00e9j\u00e0 compris que tout ce fichier est un playbook. Nous pouvons montrer o\u00f9 se trouvent les r\u00f4les (roles), o\u00f9 se trouvent les t\u00e2ches (tasks). Mais o\u00f9 est le play ici ? Et quelle est la diff\u00e9rence entre un play, un role ou un playbook ?<\/p>\n<p><\/p>\n<p>Tout cela est pr\u00e9sent dans la documentation. Et cela est souvent n\u00e9glig\u00e9. Les d\u00e9butants \u2014 parce qu'il y a trop d'informations et qu'on ne peut pas tout retenir imm\u00e9diatement. Les exp\u00e9riment\u00e9s \u2014 parce que \u00ab ce sont des choses triviales \u00bb. Si vous \u00eates exp\u00e9riment\u00e9, relisez ces pages au moins une fois tous les six mois, et votre code sera de classe sup\u00e9rieure.<\/p>\n<p><\/p>\n<p>Alors, retenez bien : un playbook est une liste compos\u00e9e de plays et <code>import_playbook<\/code>.<br \/>\nVoici un play :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group1\n  roles:\n    - role1<\/code><\/pre>\n<p><\/p>\n<p>Et voici un autre play :<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">- hosts: group2,group3\n  tasks:\n    - debug:<\/code><\/pre>\n<p><\/p>\n<p>Qu'est-ce qu'un play ? \u00c0 quoi sert-il ?<\/p>\n<p><\/p>\n<p>Un play est un \u00e9l\u00e9ment cl\u00e9 du playbook, car le play et uniquement le play lie la liste des r\u00f4les et\/ou des t\u00e2ches \u00e0 la liste des h\u00f4tes sur lesquels ils doivent \u00eatre ex\u00e9cut\u00e9s. Dans les profondeurs de la documentation, on peut trouver une mention de <code>delegate_to<\/code>, les plugins de lookup locaux, les param\u00e8tres sp\u00e9cifiques au network-cli, les jump hosts, etc. Ils permettent de modifier l\u00e9g\u00e8rement l'emplacement d'ex\u00e9cution des t\u00e2ches. Mais, oubliez cela. Chacune de ces options complexes a des applications tr\u00e8s sp\u00e9cifiques, et elles ne sont certainement pas universelles. Ici, nous parlons des bases que tout le monde devrait conna\u00eetre et utiliser.<\/p>\n<p><\/p>\n<p>Si vous voulez ex\u00e9cuter \u00ab quelque chose \u00bb \u00ab quelque part \u00bb \u2014 vous \u00e9crivez un play. Pas un r\u00f4le. Pas un r\u00f4le avec des modules et des d\u00e9l\u00e9gu\u00e9s. Vous prenez et \u00e9crivez un play. Dans lequel, dans le champ hosts, vous \u00e9num\u00e9rez o\u00f9 ex\u00e9cuter, et dans roles\/tasks \u2014 ce qu'il faut ex\u00e9cuter.<\/p>\n<p><\/p>\n<p>C'est simple, non ? Et comment pourrait-il en \u00eatre autrement ?<\/p>\n<p><\/p>\n<p>L'un des moments caract\u00e9ristiques o\u00f9 les gens ressentent le besoin de ne pas faire cela via un play, c'est \u00ab un r\u00f4le qui configure tout \u00bb. On a envie d'avoir un r\u00f4le qui configure et <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/fr\/server\/dts-los-angeles\/\"   title=\"de serveurs\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"3633\">de serveurs<\/a> un type de premier niveau, et des serveurs de deuxi\u00e8me niveau.<\/p>\n<p><\/p>\n<p>Un exemple arch\u00e9typal est la surveillance. On veut avoir un r\u00f4le monitoring qui configure la surveillance. Le r\u00f4le monitoring est attribu\u00e9 aux h\u00f4tes de surveillance (dans le play correspondant). Mais, il s'av\u00e8re que pour surveiller, nous devons installer des paquets sur les h\u00f4tes que nous surveillons. Pourquoi ne pas utiliser un delegate ? Et puis il faut configurer iptables. delegate ? Et puis il faut \u00e9crire\/corriger la configuration pour la base de donn\u00e9es, pour que la surveillance fonctionne. delegate ! Et si la cr\u00e9ativit\u00e9 arrive, on peut faire une d\u00e9l\u00e9gation <code>include_role<\/code> dans une boucle imbriqu\u00e9e avec un filtre astucieux sur la liste des groupes, et \u00e0 l'int\u00e9rieur <code>include_role<\/code> on peut aussi faire <code>delegate_to<\/code> encore. Et \u00e7a part\u2026<\/p>\n<p><\/p>\n<p>Un souhait louable \u2014 d'avoir un seul r\u00f4le de monitoring qui \u00ab fait tout \u00bb \u2014 nous conduit \u00e0 un enfer d'o\u00f9 la seule sortie est souvent : tout r\u00e9\u00e9crire depuis le d\u00e9but.<\/p>\n<p><\/p>\n<p>O\u00f9 est survenue l'erreur ? Au moment o\u00f9 vous avez d\u00e9couvert que pour accomplir la t\u00e2che \u00ab x \u00bb sur l'h\u00f4te X, vous deviez aller sur l'h\u00f4te Y et faire \u00ab y \u00bb, vous auriez d\u00fb r\u00e9aliser un exercice simple : aller et \u00e9crire un play, qui sur l'h\u00f4te Y effectue y. Ne pas rajouter quelque chose dans \u00ab x \u00bb, mais \u00e9crire depuis z\u00e9ro. M\u00eame avec des variables hardcod\u00e9es.<\/p>\n<p><\/p>\n<p>En fait, dans les paragraphes ci-dessus, tout est dit correctement. Mais ce n'est pas votre cas ! Parce que vous voulez \u00e9crire un code r\u00e9utilisable, qui est DRY et ressemble \u00e0 une biblioth\u00e8que, et vous devez trouver comment le faire.<\/p>\n<p><\/p>\n<p>Voici une autre grave erreur cach\u00e9e ici. Une erreur qui a transform\u00e9 de nombreux projets, initialement admissibles (cela pourrait \u00eatre mieux, mais tout fonctionne et peut \u00eatre facilement compl\u00e9t\u00e9), en un v\u00e9ritable d\u00e9sastre, o\u00f9 m\u00eame l'auteur ne peut s'y retrouver. Cela fonctionne, mais Dieu nous pr\u00e9serve de vouloir changer quoi que ce soit.<\/p>\n<p><\/p>\n<p>Cette erreur se r\u00e9sume ainsi : un r\u00f4le est une fonction de biblioth\u00e8que. Cette analogie a tu\u00e9 tant de bonnes initiatives qu\u2019il est triste de regarder. Un r\u00f4le n'est pas une fonction de biblioth\u00e8que. Il ne peut pas effectuer de calculs et ne peut pas prendre de d\u00e9cisions au niveau de play. Rappelez-moi quelles d\u00e9cisions prend play ?<\/p>\n<p><\/p>\n<p>Merci, vous avez raison. Play prend une d\u00e9cision (plus pr\u00e9cis\u00e9ment, contient l'information) concernant les t\u00e2ches et les r\u00f4les \u00e0 ex\u00e9cuter sur quels h\u00f4tes.<\/p>\n<p><\/p>\n<p>Si vous d\u00e9l\u00e9guez cette d\u00e9cision \u00e0 un r\u00f4le, en plus des calculs, vous condamnez votre existence (et celle de la personne qui tentera de comprendre votre code) \u00e0 \u00eatre mis\u00e9rable. Un r\u00f4le ne d\u00e9cide pas o\u00f9 il s'ex\u00e9cute. Cette d\u00e9cision est prise par play. Un r\u00f4le fait ce qu'on lui dit, l\u00e0 o\u00f9 on lui dit.<\/p>\n<p><\/p>\n<p>Pourquoi coder avec Ansible est dangereux et en quoi COBOL est meilleur qu'Ansible, nous en parlerons dans le chapitre sur les variables et Jinja. Pour l'instant, disons juste que chaque calcul que vous effectuez laisse une empreinte ind\u00e9l\u00e9bile de changements dans les variables globales, et vous ne pouvez rien y faire. D\u00e8s que deux \u00ab empreintes \u00bb se croisent \u2014 tout est perdu.<\/p>\n<p><\/p>\n<p>Remarque pour les curieux : un r\u00f4le peut en effet influencer le contr\u00f4le de flux. Il existe <code>delegate_to<\/code> et il a des applications raisonnables. Il y a <code>meta : end host\/play<\/code>. Mais ! Rappelez-vous, nous apprenons les bases ? Avez-vous oubli\u00e9 <code>delegate_to<\/code>. Nous parlons du code le plus simple et le plus beau sur Ansible. Qui est facile \u00e0 lire, facile \u00e0 \u00e9crire, facile \u00e0 d\u00e9boguer, facile \u00e0 tester et facile \u00e0 compl\u00e9ter. Donc, une fois de plus :<\/p>\n<p><\/p>\n<p><strong>play et uniquement play d\u00e9cide sur quels h\u00f4tes quoi ex\u00e9cuter.<\/strong><\/p>\n<p><\/p>\n<p>Dans cette section, nous avons examin\u00e9 l'opposition entre play et r\u00f4le. Parlerons maintenant des relations tasks vs r\u00f4le.<\/p>\n<p><\/p>\n<h1>T\u00e2ches et R\u00f4les<\/h1>\n<p><\/p>\n<p>Consid\u00e9rons 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>Supposons que vous deviez faire foo. Et cela ressemble \u00e0 <code>foo: name=foobar state=present<\/code>. O\u00f9 cela doit-il \u00eatre \u00e9crit ? dans pre ? post ? Faut-il cr\u00e9er un r\u00f4le ?<\/p>\n<p><\/p>\n<p>\u2026 Et o\u00f9 sont pass\u00e9es les tasks ?<\/p>\n<p><\/p>\n<p>Nous commen\u00e7ons encore par les bases - le play. Si vous ne ma\u00eetrisez pas ce sujet, vous ne pouvez pas utiliser le play comme base pour tout le reste, et votre r\u00e9sultat devient \"pr\u00e9caire\".<\/p>\n<p><\/p>\n<p>L'appareil play : directive hosts, param\u00e8tres de play lui-m\u00eame et sections pre_tasks, tasks, roles, post_tasks. Les autres param\u00e8tres pour play ne nous importent pas pour le moment.<\/p>\n<p><\/p>\n<p>L'ordre de leurs sections avec les t\u00e2ches et les r\u00f4les : <code>pre_tasks<\/code>, <code>roles<\/code>, <code>tasks<\/code>, <code>post_tasks<\/code>. \u00c9tant donn\u00e9 que l'ordre d'ex\u00e9cution s\u00e9mantiquement entre <code>tasks<\/code> et <code>roles<\/code> n'est pas clair, les meilleures pratiques indiquent que nous ajoutons la section <code>tasks<\/code>, seulement s'il n'y a pas de <code>roles<\/code>. S'il y a <code>roles<\/code>, alors toutes les t\u00e2ches associ\u00e9es sont plac\u00e9es dans les sections <code>pre_tasks<\/code>\/<code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Il ne reste que ce qui est s\u00e9mantiquement clair : d'abord <code>pre_tasks<\/code>, puis <code>roles<\/code>, puis <code>post_tasks<\/code>.<\/p>\n<p><\/p>\n<p>Mais nous n'avons toujours pas r\u00e9pondu \u00e0 la question : o\u00f9 \u00e9crire l'appel du module <code>foo<\/code> ? Faut-il \u00e9crire un r\u00f4le entier pour chaque module ? Ou mieux vaut-il avoir un r\u00f4le global ? Et si ce n'est pas un r\u00f4le, o\u00f9 \u00e9crire - dans pre ou dans post ?<\/p>\n<p><\/p>\n<p>S'il n'y a pas de r\u00e9ponse argument\u00e9e \u00e0 ces questions, cela indique un manque d'intuition, c'est-\u00e0-dire ces fameuses \"bases pr\u00e9caires\". D\u00e9composons cela. D'abord, une question de contr\u00f4le : Si le play a <code>pre_tasks<\/code> et <code>post_tasks<\/code> (et pas de tasks ni de roles), quelque chose peut-il se casser si je d\u00e9place la premi\u00e8re t\u00e2che de <code>post_tasks<\/code> \u00e0 la fin <code>pre_tasks<\/code>?<\/p>\n<p><\/p>\n<p>Bien s\u00fbr, la formulation de la question sous-entend que cela va casser. Mais quoi pr\u00e9cis\u00e9ment ?<\/p>\n<p><\/p>\n<p>\u2026 Les handlers. Lire les fondamentaux r\u00e9v\u00e8le un fait important : tous les handlers sont automatiquement flush\u00e9s apr\u00e8s chaque section. Autrement dit, toutes les t\u00e2ches de <code>pre_tasks<\/code>, puis tous les handlers qui ont \u00e9t\u00e9 notifi\u00e9s sont ex\u00e9cut\u00e9s. Ensuite, toutes les r\u00f4les et tous les handlers qui ont \u00e9t\u00e9 notifi\u00e9s dans les r\u00f4les sont ex\u00e9cut\u00e9s. Puis <code>post_tasks<\/code> et leurs handlers.<\/p>\n<p><\/p>\n<p>Ainsi, si vous d\u00e9placez une t\u00e2che de <code>post_tasks<\/code> dans <code>pre_tasks<\/code>, donc, potentiellement, vous l'ex\u00e9cuterez avant d'ex\u00e9cuter le handler. Par exemple, si dans <code>pre_tasks<\/code> , quelque chose est install\u00e9 et configur\u00e9 <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/fr\/server\/\"   title=\"serveur web\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1155\">serveur web<\/a>, et dans <code>post_tasks<\/code> vers lequel quelque chose est envoy\u00e9, alors d\u00e9placer cette t\u00e2che dans la section <code>pre_tasks<\/code> cela entra\u00eenera le fait qu'au moment de \"l'envoi\", le serveur ne sera pas encore lanc\u00e9 et tout \u00e9chouera.<\/p>\n<p><\/p>\n<p>Et maintenant, r\u00e9fl\u00e9chissons encore, pourquoi avons-nous besoin de <code>pre_tasks<\/code> et <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> nous permettra de travailler avec les r\u00e9sultats d'ex\u00e9cution des r\u00f4les (y compris les handlers).<\/p>\n<p><\/p>\n<p>Un expert pointilleux d'Ansible nous dira qu'il y a <code>meta: flush_handlers<\/code>, mais pourquoi aurions-nous besoin de flush_handlers, si nous pouvons compter sur l'ordre d'ex\u00e9cution des sections dans play ? De plus, l'utilisation de meta: flush_handlers peut nous causer des surprises avec des handlers r\u00e9p\u00e9t\u00e9s, g\u00e9n\u00e9rer des avertissements \u00e9tranges en cas d'utilisation de <code>when<\/code> au <code>block<\/code> et cetera. Plus vous connaissez Ansible, plus vous pourrez nommer de nuances pour une solution \"rus\u00e9e\". Et la solution simple - utiliser une s\u00e9paration naturelle entre pre\/roles\/post - ne soul\u00e8ve pas de nuances.<\/p>\n<p><\/p>\n<p>Et, revenons \u00e0 notre 'foo'. O\u00f9 le placer ? Dans pre, post ou roles ? \u00c9videmment, cela d\u00e9pend de savoir si nous avons besoin des r\u00e9sultats du handler pour foo. Si ce n'est pas le cas, alors foo n'a pas besoin d'\u00eatre mis dans ni pre ni post - ces sections ont un sens particulier - ex\u00e9cuter les t\u00e2ches avant et apr\u00e8s le bloc de code principal.<\/p>\n<p><\/p>\n<p>Maintenant, la r\u00e9ponse \u00e0 la question \"r\u00f4le ou t\u00e2che\" se r\u00e9sume \u00e0 ce qui est d\u00e9j\u00e0 dans le play - s'il y a des tasks, alors il faut ajouter dans tasks. S'il y a des roles - il faut cr\u00e9er un r\u00f4le (m\u00eame s'il n'y a qu'une t\u00e2che). Je rappelle que les tasks et roles ne sont pas utilis\u00e9es simultan\u00e9ment.<\/p>\n<p><\/p>\n<p>Comprendre les bases d'Ansible donne des r\u00e9ponses justifi\u00e9es \u00e0 ce qui semble \u00eatre des questions de go\u00fbt.<\/p>\n<p><\/p>\n<h1>T\u00e2ches et r\u00f4les (partie deux)<\/h1>\n<p><\/p>\n<p>Discutons maintenant de la situation o\u00f9 vous commencez \u00e0 \u00e9crire un playbook. Vous devez faire foo, bar et baz. S'agit-il de trois t\u00e2ches, d'un r\u00f4le ou de trois r\u00f4les ? En r\u00e9sum\u00e9 : \u00e0 quel moment doit-on commencer \u00e0 \u00e9crire des r\u00f4les ? Quel est l'int\u00e9r\u00eat d'\u00e9crire des r\u00f4les quand on peut \u00e9crire des t\u00e2ches ?\u2026 Qu'est-ce qu'un r\u00f4le ?<\/p>\n<p><\/p>\n<p>Une des erreurs les plus graves (j'en ai d\u00e9j\u00e0 parl\u00e9) est de consid\u00e9rer qu'un r\u00f4le est comme une fonction dans la biblioth\u00e8que d'un programme. \u00c0 quoi ressemble une description g\u00e9n\u00e9ralis\u00e9e d'une fonction ? Elle prend des arguments en entr\u00e9e, interagit avec des effets secondaires, produit des effets collat\u00e9raux et retourne une valeur.<\/p>\n<p><\/p>\n<p>Maintenant, attention. Que peut-on faire dans un r\u00f4le ? Appeler des effets secondaires - pas de probl\u00e8me, c'est l'essence m\u00eame d'Ansible - cr\u00e9er des effets secondaires. Avoir des causes secondaires ? \u00c9videmment. Mais pour \"passer une valeur et la retourner\" - ici, c'est non. Tout d'abord, vous ne pouvez pas passer de valeur \u00e0 un r\u00f4le. Vous pouvez d\u00e9finir une variable globale dont la dur\u00e9e de vie est \u00e9quivalente au play dans la section vars pour le r\u00f4le. Vous pouvez d\u00e9finir une variable globale dont la dur\u00e9e de vie est dans le play \u00e0 l'int\u00e9rieur du r\u00f4le. Ou m\u00eame dont la dur\u00e9e de vie est celle des playbooks (<code>set_fact<\/code>\/<code>register<\/code>). Mais vous ne pouvez pas avoir de \"variables locales\". Vous ne pouvez pas \"recevoir une valeur\" et \"la retourner\".<\/p>\n<p><\/p>\n<p>Ce qui en d\u00e9coule est essentiel : il est impossible d'\u00e9crire quelque chose sur Ansible sans provoquer d'effets secondaires. La modification de variables globales est toujours un effet secondaire pour une fonction. Dans Rust, par exemple, la modification d'une variable globale \u2014 c'est <code>unsafe<\/code>. Dans Ansible, la seule m\u00e9thode d'influencer les valeurs d'un r\u00f4le. Faites attention aux mots utilis\u00e9s : ne pas dire \"passer une valeur au r\u00f4le\", mais \"modifier les valeurs que le r\u00f4le utilise\". Il n'y a pas d'isolement entre les r\u00f4les. Il n'y a pas d'isolement entre les t\u00e2ches et les r\u00f4les.<\/p>\n<p><\/p>\n<p>Total : <strong>un r\u00f4le n'est pas une fonction<\/strong>.<\/p>\n<p><\/p>\n<p>Quels sont les avantages des r\u00f4les ? Tout d'abord, les r\u00f4les ont des valeurs par d\u00e9faut (<code>\/default\/main.yaml<\/code>), deuxi\u00e8mement, les r\u00f4les ont des r\u00e9pertoires suppl\u00e9mentaires pour stocker des fichiers.<\/p>\n<p><\/p>\n<p>Pourquoi les valeurs par d\u00e9faut sont-elles bonnes ? Parce que dans la pyramide de Maslow, qui pr\u00e9sente une hi\u00e9rarchie assez complexe des variables dans Ansible, les valeurs par d\u00e9faut des r\u00f4les sont les moins prioritaires (\u00e0 l'exception des param\u00e8tres de ligne de commande d'Ansible). Cela signifie que si vous devez fournir des valeurs par d\u00e9faut sans vous inqui\u00e9ter qu'elles ne remplacent des valeurs provenant d'inventaires ou de variables de groupe, alors les valeurs par d\u00e9faut des r\u00f4les sont le seul endroit appropri\u00e9 pour vous. (Je mens un peu - il y a aussi <code>|d(your_default_here)<\/code>, mais si nous parlons d'emplacements fixes, alors ce ne sont que les valeurs par d\u00e9faut des r\u00f4les).<\/p>\n<p><\/p>\n<p>Qu'est-ce qui est encore bon dans les r\u00f4les ? Ils ont leurs propres r\u00e9pertoires. Ce sont des r\u00e9pertoires pour les variables, tant permanentes (c\u2019est-\u00e0-dire calcul\u00e9es pour le r\u00f4le) que dynamiques (il existe un motif ou un anti-motif appel\u00e9 <code>include_vars<\/code> avec <code>{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml<\/code>.). Ce sont des r\u00e9pertoires pour <code>files\/<\/code>, <code>templates\/<\/code>. De plus, cela permet d'avoir des modules et des plugins propres aux r\u00f4les (<code>library\/<\/code>). Mais, par rapport aux t\u00e2ches dans le playbook (qui peut aussi avoir tout \u00e7a), l'avantage ici est simplement que les fichiers ne sont pas tous m\u00e9lang\u00e9s en un seul tas, mais en plusieurs tas distincts.<\/p>\n<p><\/p>\n<p>Un autre d\u00e9tail : il est possible d'essayer de cr\u00e9er des r\u00f4les qui seront disponibles pour la r\u00e9utilisation (via galaxy). Apr\u00e8s l'apparition des collections, la distribution des r\u00f4les peut \u00eatre consid\u00e9r\u00e9e comme presque oubli\u00e9e.<\/p>\n<p><\/p>\n<p>Ainsi, les r\u00f4les poss\u00e8dent deux caract\u00e9ristiques importantes : ils ont des valeurs par d\u00e9faut (une caract\u00e9ristique unique) et ils permettent de structurer le code.<\/p>\n<p><\/p>\n<p>Pour revenir \u00e0 la question initiale : quand utiliser des t\u00e2ches et quand des r\u00f4les ? Les t\u00e2ches dans le playbook sont le plus souvent utilis\u00e9es soit comme \"colles\" avant\/apr\u00e8s les r\u00f4les, soit comme \u00e9l\u00e9ments distincts (dans ce cas, il ne devrait pas y avoir de r\u00f4les dans le code). Un m\u00e9lange de t\u00e2ches normales avec des r\u00f4les est d\u00e9finitivement d\u00e9sordonn\u00e9. Il faut s'en tenir \u00e0 un style pr\u00e9cis \u2014 soit des t\u00e2ches, soit des r\u00f4les. Les r\u00f4les offrent une s\u00e9paration des entit\u00e9s et des valeurs par d\u00e9faut, tandis que les t\u00e2ches permettent de lire le code plus rapidement. En g\u00e9n\u00e9ral, on place dans les r\u00f4les un code plus \"stationnaire\" (important et complexe), et dans le style des t\u00e2ches, on \u00e9crit des scripts auxiliaires.<\/p>\n<p><\/p>\n<p>Il est possible de faire un import_role comme t\u00e2che, mais si vous \u00e9crivez cela, pr\u00e9parez-vous \u00e0 expliquer pourquoi vous voulez le faire pour votre propre sens esth\u00e9tique.<\/p>\n<p><\/p>\n<p>Un lecteur pointilleux peut dire que les r\u00f4les peuvent importer des r\u00f4les, que les r\u00f4les peuvent avoir des d\u00e9pendances via galaxy.yml, et il y a aussi le terrible et horrible. <code>include_role<\/code> \u2014 je rappelle que nous am\u00e9liorons nos comp\u00e9tences en Ansible de base, et non en gymnastique rythmique.<\/p>\n<p><\/p>\n<h1>Gestionnaires et t\u00e2ches<\/h1>\n<p><\/p>\n<p>Discutons d'une autre chose \u00e9vidente : les gestionnaires. Savoir les utiliser correctement est presque un art. Quelle est la diff\u00e9rence entre un gestionnaire et une t\u00e2che ?<\/p>\n<p><\/p>\n<p>Puisque nous nous rappelons les bases, voici un exemple :<\/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>Les handlers des r\u00f4les se trouvent dans rolename\/handlers\/main.yaml. Les handlers sont partag\u00e9s entre tous les participants du play : les pre\/post_tasks peuvent appeler les handlers du r\u00f4le, et le r\u00f4le peut appeler les handlers du play. Cependant, les appels de handlers \"cross-r\u00f4les\" provoquent beaucoup plus de confusion que la r\u00e9p\u00e9tition d'un handler triviale. (Un autre \u00e9l\u00e9ment des bonnes pratiques \u2014 essayer de ne pas r\u00e9p\u00e9ter les noms des handlers).<\/p>\n<p><\/p>\n<p>La principale diff\u00e9rence est que la t\u00e2che s'ex\u00e9cute (idempotemment) toujours (plus ou moins les balises et <code>when<\/code>), tandis que le gestionnaire s'ex\u00e9cute en fonction du changement d'\u00e9tat (notify ne se d\u00e9clenche que s'il y a eu un changement). Qu'est-ce que cela implique ? Par exemple, lors de l'ex\u00e9cution r\u00e9p\u00e9t\u00e9e, si aucune modification n'a eu lieu, il n'y aura pas de gestionnaire. Et pourquoi pourrait-il \u00eatre n\u00e9cessaire d'ex\u00e9cuter un gestionnaire alors qu'il n'y a pas eu de changement dans la t\u00e2che g\u00e9n\u00e9ratrice ? Par exemple, parce que quelque chose s'est cass\u00e9 et qu'il y a eu un changement, mais l'ex\u00e9cution n'est pas parvenue jusqu'au gestionnaire. Par exemple, parce que le r\u00e9seau \u00e9tait temporairement hors service. La configuration a chang\u00e9, le service n'a pas \u00e9t\u00e9 red\u00e9marr\u00e9. Lors de la prochaine ex\u00e9cution, la configuration ne change plus, et le service reste avec l'ancienne version de la configuration.<\/p>\n<p><\/p>\n<p>La situation avec le config est insoluble (en fait, il est possible d'inventer soi-m\u00eame un protocole de red\u00e9marrage sp\u00e9cial avec des drapeaux de fichiers, etc., mais cela ne rel\u00e8ve plus du 'basic ansible' sous aucune forme). En revanche, il existe une autre histoire fr\u00e9quente : nous avons install\u00e9 l'application, l'avons enregistr\u00e9e. <code>.service<\/code>- fichier, et maintenant nous voulons faire son <code>daemon_reload<\/code> et <code>state=started<\/code>. Et un endroit naturel pour cela semble \u00eatre un gestionnaire. Mais si nous en faisons une t\u00e2che au bas de la liste des t\u00e2ches ou un r\u00f4le, elle sera ex\u00e9cut\u00e9e de mani\u00e8re idempotente \u00e0 chaque fois. M\u00eame si le playbook \u00e9choue en cours de route. Cela ne r\u00e9sout absolument pas le probl\u00e8me du red\u00e9marrage (il n'est pas possible de faire une t\u00e2che avec l'attribut restarted, car cela perd l'idempotence), mais il est certainement utile de faire state=started, la stabilit\u00e9 g\u00e9n\u00e9rale des playbooks augmente car le nombre de d\u00e9pendances et d'\u00e9tats dynamiques diminue.<\/p>\n<p><\/p>\n<p>Une autre caract\u00e9ristique positive du handler est qu'il ne surcharge pas la sortie. Pas de modifications \u2014 pas de skipped ou ok suppl\u00e9mentaires dans la sortie \u2014 plus facile \u00e0 lire. Cela constitue aussi une caract\u00e9ristique n\u00e9gative : si vous trouvez une faute de frappe dans une t\u00e2che ex\u00e9cut\u00e9e lin\u00e9airement lors du premier passage, les handlers ne seront ex\u00e9cut\u00e9s que lors d'un changement, c'est-\u00e0-dire dans certaines conditions \u2014 tr\u00e8s rarement. Par exemple, la premi\u00e8re fois en cinq ans. Et, bien s\u00fbr, il y aura une faute de frappe dans le nom et tout va casser. La seconde fois, ils ne peuvent pas \u00eatre lanc\u00e9s \u2014 pas de changement.<\/p>\n<p><\/p>\n<p>Il faut parler s\u00e9par\u00e9ment de l'accessibilit\u00e9 des variables. Par exemple, si vous notifiez pour une t\u00e2che avec une boucle, que se passera-t-il dans les variables ? On peut le deviner par voie analytique, mais ce n'est pas toujours trivial, surtout si les variables proviennent de diff\u00e9rents endroits.<\/p>\n<p><\/p>\n<p>Ainsi, les handlers sont beaucoup moins utiles et bien plus probl\u00e9matiques qu'il n'y para\u00eet. Si quelque chose peut \u00eatre \u00e9crit de mani\u00e8re \u00e9l\u00e9gante (sans contorsions) sans handlers, il vaut mieux le faire sans eux. Si cela ne fonctionne pas de mani\u00e8re esth\u00e9tique, il est pr\u00e9f\u00e9rable d'en utiliser.<\/p>\n<p><\/p>\n<p>Un lecteur perspicace remarque \u00e0 juste titre que nous n'avons pas discut\u00e9 <code>\u00e9couter<\/code>, que le handler peut appeler notify pour un autre handler, que le handler peut inclure import_tasks (qui peut faire include_role avec with_items), que le syst\u00e8me de handlers dans Ansible est Turing-complet, que les handlers d'included_role se croisent de mani\u00e8re curieuse avec les handlers de play, etc. \u2014 tout cela ne repr\u00e9sente clairement pas les \"fondamentaux\").<\/p>\n<p><\/p>\n<p>Bien qu'il y ait un certain WTF qui est en r\u00e9alit\u00e9 une fonctionnalit\u00e9, et dont il faut se souvenir. Si vous avez une t\u00e2che qui s'ex\u00e9cute avec <code>delegate_to<\/code> et qu'elle a un notify, alors le gestionnaire correspondant s'ex\u00e9cute sans <code>delegate_to<\/code>, c'est-\u00e0-dire sur l'h\u00f4te auquel le play est assign\u00e9. (Bien que le gestionnaire puisse, bien s\u00fbr, avoir <code>delegate_to<\/code> aussi).<\/p>\n<p><\/p>\n<p>Je voudrais \u00e9galement dire quelques mots sur les r\u00f4les r\u00e9utilisables. Avant l'apparition des collections, l'id\u00e9e \u00e9tait de cr\u00e9er des r\u00f4les universels qui peuvent \u00eatre <code>ansible-galaxy install<\/code> et je suis parti. Cela fonctionne sur tous les syst\u00e8mes d'exploitation dans toutes les variantes et toutes les situations. Mon avis est le suivant : cela ne fonctionne pas. Tout r\u00f4le tr\u00e8s g\u00e9n\u00e9ral avec un support pour 100500 cas est condamn\u00e9 aux ab\u00eemes des bugs sp\u00e9cifiques. On peut les juguler par des tests massifs, mais comme pour tout test, soit vous avez le produit cart\u00e9sien des valeurs d'entr\u00e9e et une fonction totale, soit vous avez \"des sc\u00e9narios couverts\". \u00c0 mon avis, il est bien mieux d'avoir un r\u00f4le lin\u00e9aire (complexit\u00e9 cyclomatique 1). <code>include_vars<\/code>, avec le support de 100500 cas, est vou\u00e9e aux ab\u00eemes des bugs corner case. On peut les colmater par des tests massifs, mais comme pour tout test, soit vous avez le produit cart\u00e9sien des valeurs d'entr\u00e9e et une fonction totale, soit vous avez \"couverts des sc\u00e9narios particuliers\". Mon avis \u2014 il vaut mieux que le r\u00f4le soit lin\u00e9aire (complexit\u00e9 cyclomatique 1).<\/p>\n<p><\/p>\n<p>Moins il y a de if (expr\u00e8s ou d\u00e9claratifs \u2014 sous forme de <code>when<\/code> sur un ensemble de variables), mieux c'est pour le r\u00f4le. Il arrive parfois qu'il faille faire des embranchements, mais, je le r\u00e9p\u00e8te, moins il y en a, mieux c'est. Donc, il semble qu'un bon r\u00f4le avec galaxy (\u00e7a fonctionne, apr\u00e8s tout !) avec une tonne <code>include_vars<\/code> puisse \u00eatre moins pr\u00e9f\u00e9r\u00e9 qu'un r\u00f4le \"propre\" de cinq t\u00e2ches. Le moment o\u00f9 un r\u00f4le avec galaxy est meilleur \u2014 c'est quand vous commencez \u00e0 \u00e9crire quelque chose. Le moment o\u00f9 cela devient pire \u2014 c'est quand quelque chose se casse, et vous soup\u00e7onnez que cela vient du \"r\u00f4le avec galaxy\". Vous l'ouvrez, et l\u00e0, vous avez cinq inclusions, huit listes de t\u00e2ches et une pile <code>when<\/code> ), moins cela peut \u00eatre pr\u00e9f\u00e9rable qu'un r\u00f4le \"propre\" compos\u00e9 de cinq t\u00e2ches. Le moment o\u00f9 un r\u00f4le avec galaxy est meilleur \u2014 c'est quand vous commencez \u00e0 \u00e9crire quelque chose. Le moment o\u00f9 il devient pire \u2014 c'est quand quelque chose casse, et vous soup\u00e7onnez que c'est \u00e0 cause du \"r\u00f4le avec galaxy\". Vous l'ouvrez, et l\u00e0, il y a cinq inclusions, huit listes de t\u00e2ches et une pile <code>when<\/code>\u2026 Et vous devez comprendre cela. Au lieu de 5 t\u00e2ches dans une liste lin\u00e9aire, o\u00f9 il n'y a m\u00eame pas de quoi casser.<\/p>\n<p><\/p>\n<h1>Un peu sur l'inventaire, les variables de groupe, le plugin host_group_vars, les hostvars. Comment attacher une \u00e9pine de Gordius \u00e0 partir d'une spaghetti. Port\u00e9e et priorit\u00e9 des variables, mod\u00e8le de m\u00e9moire d'Ansible. \"Alors o\u00f9 stocker le nom d'utilisateur pour la base de donn\u00e9es ?\".<\/h1>\n<p><\/p>\n<ul>\n<li>Un peu sur l'inventaire, les variables de groupe, le plugin host_group_vars, les hostvars. Comment relier les spaghetti en un n\u0153ud gordien. \u00c9tendue et priorit\u00e9 des variables, mod\u00e8le de m\u00e9moire d'Ansible. \"Alors o\u00f9 stocker le nom d'utilisateur pour la base de donn\u00e9es ?\".<\/li>\n<li><code>\u2014 nosql notype nosense plastique mall\u00e9able. Il est partout, m\u00eame l\u00e0 o\u00f9 vous ne l'attendez pas. Un peu sur<\/code> !!unsafe <code>et un yaml savoureux.<\/code> Je fais beaucoup de revues de code pour d'autres sur Ansible et j'\u00e9cris beaucoup moi-m\u00eame.<\/li>\n<\/ul>\n<p>Source : <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.2 - 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\/fr\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\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\/fr\/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\udd47Les fondamentaux d'Ansible, sans lesquels vos playbooks ne sont qu'un tas de p\u00e2tes coll\u00e9es | ProHoster","description":"\ud83e\udd47Les bases d'Ansible, sans lesquelles vos playbooks sont un amas de p\u00e2tes coll\u00e9es | ProHoster","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/osnovy-ansible-bez-kotoryh-vashi-plejbuki-komok-slipshihsya-makaron","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/87084","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=87084"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/87084\/revisions"}],"predecessor-version":[{"id":162161,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/87084\/revisions\/162161"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=87084"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=87084"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=87084"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}