Ansible 2.0 b2: обзор новшеств
keeper

О системе управления конфигурациями Ansible мы уже писали два года назад. Мы активно её используем в собственной практике и внимательно следим за всеми изменениями и обновлениями.
Конечно же, мы не могли оставить без внимания следующую новость: вышла в свет вторая бета-версия Ansible v2.0. Черновой вариант Ansible v2.0 был размещён на GitHub уже давно, а теперь наконец-то появился более или менее стабильный бета-релиз.
В этой статье мы расскажем, что нового появилось во второй версии.

Что нового

Никаких радикальных изменений во второй версии нет — об этом уже давно говорил один из разработчиков Ansible Джеймс Каммарата в докладе, прочитанном в этом году на конференции AnsibleFest в Нью-Йорке.
Появилось много новых модулей, а в некоторые из старых модулей были внесены изменения. Разработчики гарантируют стопроцентную совместимость со сценариями (Playbooks) для предыдущих версий.

Однако изменения затронули внутренние API, и тем, кто пользуется «самописными» плагинами, придётся эти плагины скорректировать. Разработчики уверяют (см. доклад по ссылке выше), что переход на новую версию должен произойти без особых проблем.
Подробный список всех изменений опубликован здесь.

Сообщения об ошибках

Система оповещения об ошибках в первой версии была довольно неудобной. Вот пример ошибки в имени модуля:

- hosts: all
  gather_facts: no
  tasks:
    - debug: msg="hi"
    - not_a_syntax_error_just_invalid_module: msg="error"
    - debug: msg="bye"

При обнаружении этой ошибки первая версия выдавала весьма лаконичное сообщение:

ERROR: not_a_syntax_error_just_invalid_module is not a legal parameter in an Ansible 
task or handler 

Вторая же версия выдаёт гораздо более информативное сообщение и указывает место, где была обнаружена ошибка:

ERROR! no action detected in task

The error appears to have been in '... .yml': line 5, column 44, but may  
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  - debug: msg="hi"
  - not_a_syntax_error_just_invalid_module: msg="error"
                                           ^ here

Это делает процесс работы с Ansible более удобным, а во многих случаях ещё и экономит время.

Блоки

Ещё одной интересной новацией являются блоки. Во многих языках программирования для обработки исключений используется конструкция try/except/finally. Похожая конструкция появилась и в Ansible:

- hosts: localhost
  connection: local
  gather_facts: no
  tasks:
  - block:
      - command: /bin/false
      - debug: msg="you shouldn't see me"
    rescue:
      - debug: msg="this is the rescue"
      - command: /bin/false
      - debug: msg="you shouldn't see this either"
    always:
      - debug: msg="this is the always block, it will always be seen"

Вывод при выполнении приведённого сценария будет выглядеть примерно так:

PLAY [] ******************************************************

TASK [command] ******************************************************************  
fatal: [localhost]: FAILED! => ...

NO MORE HOSTS LEFT **************************************************************

CLEANUP TASK [debug msg=this is the rescue] *************************************  
ok: [localhost] => {  
    "msg": "this is the rescue", 
    "changed": false
}

CLEANUP TASK [command] **********************************************************  
fatal: [localhost]: FAILED! => ...

CLEANUP TASK [debug msg=this is the always block, it will always be seen] *******  
ok: [localhost] => {  
    "msg": "this is the always block, it will always be seen", 
    "changed": false
}

Если при выполнении блока случится ошибка, то будут выполнены действия, указанные в секциях rescue и always. После этого выполнение сценария будет остановлено.

Стратегии

В новой версии Ansible можно выбирать, в какой последовательности будут выполняться содержащиеся в сценарии задания. Возможные варианты выполнения называются стратегиями (strategy). Существует два вида стратегий:

  • линейная (linear)— работает так же, как и в предыдущей версии: выполнение нового задания начнётся после того, как текущее задание будет выполнено на всех хостах;
  • произвольная (free) — на каждом хосте задание выполняется как можно быстрее и без учёта того, что происходит на других хостах.

Поясним сказанное конкретным примером и рассмотрим следующий фрагмент сценария:

- hosts: all
  gather_facts: no
  strategy: free
  tasks:
    - pause: seconds={{ 10 |random}}
    - debug: msg="msg_1"
    - pause: seconds={{ 10 |random}}
    - debug: msg="msg_2"
    - pause: seconds={{ 10 |random}}
    - debug: msg="msg_3"

Если бы мы выбрали традиционную (линейную) стратегию, то при выполнении этого сценария увидели бы такой вывод (приводим в несколько сокращённом варианте):

TASK [debug msg=msg_1] **********************************************************  
ok: [host3] => { "msg": "msg_1", "changed": false}  
ok: [host4] => { "msg": "msg_1", "changed": false}  
ok: [host2] => { "msg": "msg_1", "changed": false}  
ok: [host1] => { "msg": "msg_1", "changed": false}

TASK [debug msg=msg_2] **********************************************************  
ok: [host4] => {"msg": "msg_2", "changed": false}  
ok: [host1] => {"msg": "msg_2", "changed": false}  
ok: [host2] => {"msg": "msg_2", "changed": false}  
ok: [host3] => {"msg": "msg_2", "changed": false}

TASK [debug msg=msg_3] **********************************************************  
ok: [host1] => {"msg": "msg_3", "changed": false}  
ok: [host2] => {"msg": "msg_3", "changed": false}  
ok: [host3] => {"msg": "msg_3", "changed": false}  
ok: [host4] => {"msg": "msg_3", "changed": false}

Задания выполняются в случайном порядке, но при этом выполнение заданий из группы msg_3 не будет начато до тех пор, пока не завершится выполнение заданий из группы msg_2.

Если же выбрана произвольная стратегия, вывод будет совсем другим:

PLAY [] ******************************************************  
ok: [host3] => {"msg": "msg_1", "changed": false}  
ok: [host4] => {"msg": "msg_1", "changed": false}  
ok: [host2] => {"msg": "msg_1", "changed": false}  
ok: [host4] => {"msg": "msg_2", "changed": false}  
ok: [host2] => {"msg": "msg_2", "changed": false}  
ok: [host4] => {"msg": "msg_3", "changed": false}  
ok: [host1] => {"msg": "msg_1", "changed": false}  
ok: [host2] => {"msg": "msg_3", "changed": false}  
ok: [host3] => {"msg": "msg_2", "changed": false}  
ok: [host3] => {"msg": "msg_3", "changed": false}  
ok: [host1] => {"msg": "msg_2", "changed": false}  
ok: [host1] => {"msg": "msg_3", "changed": false}

Как видим, все действия на хостах осуществляются в произвольном режиме. Благодаря этому нововведению многие сценарии будут выполняться гораздо быстрее.

В случае необходимости пользователь может определить и собственную стратегию — достаточно лишь написать соответствующий плагин. Правда, на API для плагинов пока что работает нестабильно, да и документация оставляет желать лучшего.

Include + with

Очень часто новое — это хорошо забытое старое. В более ранних версиях Ansible уже были конструкции вида:

main.yml:

- hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - include: foo.yml some_var={{ item }}
      with_items:
        - a
        - b
        - c

foo.yml:

- debug: msg={{some_var}}

В версии 1.5 и всех последующих они уже были исключены. Во второй версии они вернулись.

Наследование блоков и ролей

Значения ‘become’ и другие теперь могут быть присвоены блокам и ролям, и их будут наследовать все задания, включённые в эти блоки и роли:

- hosts: all
  gather_facts: false
  remote_user: testing
    - roles: {role: foo ,  become_user: root}
  tasks:
    block:
      - command: whoami
      - command: do/something/privileged
      - stat = path=/root/ .ssh/id_rsa
        become_user: root

Как попробовать

Новая версия уже доступна для скачивания здесь. Кроме того, её можно собрать их исходного кода, размещённого на GitHub:

$ git clone https://github.com/ansible/ansible.git
$ cd ansible
$ git checkout v2.0.0-0.4.beta2
$ git submodule update --init
$ .hacking/env-setup

При желании можно собрать deb-пакет:

$ make deb

Заключение

Нововведения, появившиеся во второй версии, показывают, что в целом Ansible развивается в правильном направлении. Мы будем с интересом следить за его дальнейшим развитием.
А вы уже пробовали новую версию Ansible? Если пробовали, приглашаем поделиться впечатлениями в комментариях.

Что еще почитать по теме

Владимир Туров 1 сентября 2020

Дело совершенно секретного iPod

Это был обычный серый день в конце 2005 года. Я сидел на рабочем месте и писал код для следующей версии iPod. Вдруг без стука ворвался директор ПО для iPod, начальник моего начальника, и закрыл дверь.
Владимир Туров 1 сентября 2020

Новое в блоге

bondar 24 сентября 2021

Piller CPM300: зачем мы устанавливаем новые динамические ИБП

Бесперебойная подача электропитания в серверные — одна из обязательств провайдера дата-центра перед клиентами. Но важна не только отказоустойчивость решения, но и его эффективность с точки потребления…
bondar 24 сентября 2021
Владимир Туров 18 сентября 2021

Разбираем редкого зверя от Nvidia — DGX A100

Крупные IT-компании располагают дорогими «игрушками», которые скрыты от взоров большинства пользователей. Сегодня мы приоткроем завесу тайны и расскажем про систему, которая оптимизирована для работы …
Владимир Туров 18 сентября 2021
Андрей Зайцев 8 сентября 2021

Продуктовый дайджест: новые серверы, Selectel Connect и обновления «Облачной платформы»

У нас обновления в конфигурациях серверов, кластерах Kubernetes и разделах базы знаний. А еще обратите внимание на сервис Selectel Connect. В конце дайджеста — анонс конференции по ML и записи митапов…
Андрей Зайцев 8 сентября 2021
Ульяна Малышева 12 августа 2021

RHVoice Lab: как серверы помогают создавать голоса для синтезаторов речи

В этом году Selectel стал поддерживать некоммерческий проект RHVoice Lab — лабораторию по созданию новых голосов для одноименного отечественного синтезатора речи. Его особенность в том, что синтезатор…
Ульяна Малышева 12 августа 2021