Ansible basics without which your playbooks are a clump of pasta

I do a lot of reviews for someone else's code in Ansible and write a lot myself. In the course of analyzing the mistakes (both strangers and my own), as well as a number of interviews, I realized the main mistake that Ansible users make - they climb into the difficult without mastering the basic one.



To correct this universal injustice, I decided to write an introduction to Ansible for those who already know it. I warn you, this is not a retelling of mans, this is a longread with a lot of letters and no pictures.



The expected level of the reader - several thousand lines of yamla have already been written, something is already in production, but "somehow everything is crooked."



Names



The main mistake of the Ansible user is not to know what is called. If you don't know the names, you cannot understand what is written in the documentation. A living example: at an interview, a person who allegedly claimed that he wrote a lot in Ansible could not answer the question "what elements of a playbook consists of?". And when I suggested that "the answer was that the playbook consists of play", then the murderous comment "we do not use this" followed. People write in Ansible for money and do not use play. Actually use, but do not know what it is.



So let's start with a simple: what’s called. Maybe you know this, or maybe not, because you didn’t pay attention when you read the documentation.



ansible-playbook executes the playbook. A playbook is a file with the yml / yaml extension, inside of which something like this:



---
- hosts: group1
  roles:
    - role1

- hosts: group2,group3
  tasks:
    - debug:


We already realized that this whole file is a playbook. We can show where roles are, where tasks are. But where is play? And how is play different from role or playbook?



The documentation has it all. And they miss it. Beginners - because there are too many and you can't remember everything at once. Experienced - because "trivial things". If you are experienced, re-read these pages at least once every half a year, and your code will become a better class.



So, remember: Playbook is a list of play and import_playbook.

This is one play:



- hosts: group1
  roles:
    - role1


and this is also another play:



- hosts: group2,group3
  tasks:
    - debug:


What is play? Why is she?



Play β€” playbook, play play / , . delegate_to, lookup-, network-cli- , jump- .. . , . , . , .



"-" "-" β€” play. . . play. , hosts , roles/tasks β€” .



, ? ?



, play, ", ". , , .



. monitoring, . monitoring ( . play). , , , . delegate? iptables. delegate? / , . delegate! , include_role , include_role delegate_to . ...



β€” - monitoring, " " β€” : .



? , , "x" X Y "y", : play, Y y. - "x", . .



, . ! , DRY , .



. , ( , ) , . , - .



: β€” . , . β€” . play. , play?



, . Play (, ) , .



, , ( , ) . . play. , , , .



COBOL jinja. β€” , . "" β€” .



: , , control flow. delegate_to . meta: end host/play. ! , ? delegate_to. . , , , . , :



play play .



play role. tasks vs role.





play:



- hosts: somegroup
  pre_tasks:
    - some_tasks1:
  roles:
     - role1
     - role2
  post_tasks:
     - some_task2:
     - some_task3:


, foo. foo: name=foobar state=present. ? pre? post? role?



… tasks?



β€” play. , play , "".



play: hosts, play pre_tasks, tasks, roles, post_tasks. play .



: pre_tasks, roles, tasks, post_tasks. tasks roles , best practices , tasks, roles. roles, pre_tasks/post_tasks.



, : pre_tasks, roles, post_tasks.



: foo ? ? ? , β€” pre post?



, , " ". . : play pre_tasks post_tasks ( tasks, roles), - , post_tasks pre_tasks?



, , . ?



… . : flush' . .. pre_tasks, , notify. , notify . post_tasks .



, post_tasks pre_tasks, , , handler'. , pre_tasks -, post_tasks - , pre_tasks , "" .



, pre_tasks post_tasks? , , ( ) . post_tasks ( ).



Ansible , meta: flush_handlers, flush_handlers, play? , meta: flush_handlers , when block .. , "" . β€” pre/roles/post β€” .



, , 'foo'. ? pre, post roles? , , foo. , foo pre, post β€” β€” .



" " , play β€” tasks, tasks. roles β€” ( task). , tasks roles .



, , .



( )



, . foo, bar baz. , ? : ? , ?… ?



( ) β€” , β€” . ? , side causes, side effects, .



, . ? side effects β€” , β€” -. side causes? . " " β€” - . -, . play vars . play . (set_fact/register). " ". " " " ".



: ansible - -. β€” side effect . Rust, , β€” unsafe. β€” . : " ", " , ". . .



: β€” .



? -, default values (/default/main.yaml), - .



default values? , , role defaults β€” ( ). , - , β€” . ( β€” |d(your_default_here), β€” ).



? , . , (.. ), ( , - β€” include_vars {{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml.). files/, templates/. , (library/). , playbook' ( ), , , .



: , ( galaxy). .



, : ( ) .



: ? "" / , ( ). β€” . β€” , . , . "" ( ) , .



import_role , , , .



, , galaxy.yml, include_role β€” , , .





: . β€” . ?



, :



- hosts: group1
  tasks:
    - foo:
      notify: handler1
  handlers:
     - name: handler1
       bar:


handler' rolename/handlers/main.yaml. Handler' play: pre/post_tasks handler' , handler' . , "-" handler' wtf, handler'. ( best practices β€” handler').



, () (/ when), β€” (notify changed). ? , , , changed, handler. , handler changed ? , - changed , . , . , . , .



(, .., 'basic ansible' ). : , .service-, daemon_reload state=started. , , . , . . restarted ( restarted, .. ), state=started, , .. .



handler' , . β€” skipped ok β€” . β€” task' , handler' changed, .. β€” . , . , , . β€” changed- .



. , notify , ? , , , .



… handler' , . - ( ) . β€” .



, listen, handler notify handler', handler import_tasks ( include_role c with_items), -, include_role .. β€” "").



WTF, , . delegate_to notify, delegate_to, .. , play. ( , , delegate_to ).



reusable roles. , , ansible-galaxy install . . , : . include_vars, 100500 corner case . , , , " ". β€” , ( 1).



if' ( β€” when include_vars ), . , , , , . galaxy ( !) when , "" . , galaxy β€” - . , β€” - , , - " galaxy". , , - when'… . 5 , - .





  • group variables, host_group_vars plugin, hostvars. How to tie the Gordian knot from spaghetti. Scope and precedence variables, Ansible memory model. "So where is the username for the database stored?"
  • jinja: {{ jinja }}- nosql notype nosense soft plasticine. It is everywhere, even where you don't expect it. A little pro !!unsafeand yaml delicious.



All Articles