Сценарии автоматизации#

Набор сценариев (playbook) в Ansible – это основной инструмент автоматизации, представляющий собой файл в формате YAML, в котором содержится описание конфигурации целевых узлов в декларативной форме. В отличие от отдельных (ad-hoc) команд, сценарии позволяют задавать последовательность операций, определять условия их выполнения, использовать переменные, роли и другие элементы логики, характерные для полноценного программного описания инфраструктуры.

Структура набора сценариев#

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

Для запуска сценария используется утилита командной строки ansible-playbook, обеспечивающая детальный контроль над параметрами выполнения и возможностями отладки.

ansible-playbook setup.yml -i inventory.yml

где:

  • setup.yml – путь к файлу набора сценариев;

  • -i inventory.yml – путь к файлу с инвентарным списком.

Подробнее об утилите см. Утилиты.

Иерархия исполняемых компонентов в наборе сценариев представлена на схеме:

../../_images/playbook-hierarchy-light.svg ../../_images/playbook-hierarchy-dark.svg
Пример структуры набора сценариев#
---
- name: Настройка веб-серверов
  hosts: webservers
  become: yes
  tasks:
    - name: Установка Apache
      ansible.builtin.apt:
        name: apache2
        state: present

- name: Управление пользователями
  hosts: all
  become: yes
  tasks:
    - name: Добавление нового пользователя
      ansible.builtin.user:
        name: deployer
        state: present

- name: Настройка брандмауэра
  hosts: firewalls
  become: yes
  tasks:
    - name: Открытие порта HTTP
      ansible.posix.firewalld:
        port: 80/tcp
        permanent: true
        state: enabled

Здесь:

  • Названия сценариев:

    • Настройка веб-серверов.

    • Управление пользователями.

    • Настройка брандмауэра.

  • Названия групп узлов:

    • webservers;

    • all;

    • firewalls.

  • Названия задач:

    • Установка Apache.

    • Добавление нового пользователя.

    • Открытие порта HTTP.

  • Названия модулей:

    • ansible.builtin.apt;

    • ansible.builtin.user;

    • ansible.posix.firewalld.

  • Названия переменных:

    • name;

    • state;

    • port;

    • permanent.

Инвентарный список для связывания с набором сценариев может быть задан несколькими способами. Далее приведен список вариантов в порядке убывания приоритета:

  • аргумент -i (--inventory, --inventory-file) утилиты ansible-playbook;

  • переменная окружения ANSIBLE_INVENTORY;

  • переменная inventory в конфигурационном файле ansible.cfg.

Структура сценария#

Сценарий (play) – элемент первого уровня в структуре набора сценариев. Он описывает, какие действия необходимо выполнить и на каких целевых узлах.

В сценарий входят следующие компоненты:

Компонент

Описание

Задача (task)

Использует один из модулей Ansible для выполнения отдельной операции по управлению узлами.

Модуль (module)

Реализует требуемую функциональность. Например, существуют модули для копирования файлов, управления пакетами и службами и так далее. Код модулей выполняется на целевых узлах, которые в большинстве случаев и являются управляемыми.

Расширение (plugin)

Расширяет функциональность Ansible. В отличие от модулей, код расширений всегда выполняется на управляющем узле.

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

Сценарий может включать следующие основные параметры:

  • name – название;

  • hosts – узлы, на которых выполняются задачи;

  • tasks – задачи для выполнения;

  • vars – значения переменных;

  • vars_files – список путей к файлам с переменными;

  • become – требование повысить привилегии при выполнении задач.

Пример простого сценария:

- name: Настройка веб-серверов
  hosts: webservers
  become: yes
  vars:
    apache_package: apache2
  tasks:
    - name: Установка Apache
      ansible.builtin.apt:
        name: "{{ apache_package }}"
        state: present

Помимо основных параметров, в сценариях часто используются дополнительные настройки:

  • gather_facts – включение или отключение сбора фактов перед выполнением задач.

    Значение по умолчанию: true.

  • remote_user – название учетной записи пользователя, под которой будет производиться подключение к узлам.

  • serial – ограничение количества узлов, обрабатываемых одновременно.

  • strategy – стратегия выполнения задач (например, linear, free, debug).

  • handlers – определения действий, вызываемых только при изменении состояния (например, перезапуск службы после обновления конфигурации).

  • pre_tasks и post_tasks – задачи, которые выполняются до и после основного блока tasks.

  • roles – подключение ролей, содержащих повторно используемую логику и структуру.

Структура задачи#

Задача (task) в Ansible описывает одно конкретное действие, которое должно быть выполнено на целевом узле. Это наименьшая единица логики внутри сценария, и она исполняется модулем Ansible с переданными ему параметрами.

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

В задаче, как правило, указываются следующие элементы:

  • name – название задачи, кратко описывающее ее назначение;

  • модуль Ansible – название используемого модуля, например, ansible.builtin.copy или ansible.builtin.apt;

  • параметры модуля;

  • дополнительные директивы (опционально), такие как when, loop, become, register и другие.

Пример сценария с одной задачей#
---
- name: Установка Apache на веб-серверах
  hosts: webservers
  become: yes
  tasks:
    - name: Установка пакета apache2 через APT
      ansible.builtin.apt:
        name: apache2
        state: present

В этом примере:

  • Название сценария – Установка Apache на веб-серверах.

  • Название группы узлов – webservers.

  • Флаг повышения привилегий – become: yes.

  • Название задачи – Установка пакета apache2 через APT.

  • Название используемого модуля – ansible.builtin.apt.

  • Название устанавливаемого пакета – apache2.

  • Желаемое состояние пакета – present (означает, что пакет должен быть установлен).

Большинство модулей Ansible следуют принципу идемпотентности: они не выполняют действия, если это не требуется. Например, модуль ansible.builtin.file не будет создавать файл, если он уже существует и обладает нужными атрибутами.

Примечание

В то же время идемпотентность модулей является рекомендацией а не требованием. Кроме этого, некоторые модули, например, ansible.builtin.command, в принципе не могут быть идемпотентными.

Базовые переменные#

Ansible предоставляет ряд предопределенных переменных, которые можно использовать в сценариях:

  • become – выполнение задачи с привилегиями суперпользователя.

    Пример использования become

    Установка и настройка NGINX. Задачи выполняются с привилегиями суперпользователя.

    ---
    - name: Установка и запуск NGINX
      hosts: webservers
      become: yes  # Выполнение задач с повышенными привилегиями
      tasks:
        - name: Установить NGINX
          ansible.builtin.apt:
            name: nginx
            state: present
    
        - name: Запустить NGINX
          ansible.builtin.service:
            name: nginx
            state: started
            enabled: yes
    
  • ansible_factsфакты об узле.

    Пример использования ansible_facts

    Настройка NGINX, при которой число worker_processes в конфигурационном файле задается на основе количества доступных ядер процессоров:

    ---
    - name: Настройка NGINX в зависимости от числа ядер CPU
      hosts: webservers
      become: yes
      tasks:
        - name: Создать конфигурационный файл
          ansible.builtin.template:
            src: nginx.conf.j2
            dest: /etc/nginx/nginx.conf
          vars:
            cpu_cores: "{{ ansible_facts['processor_cores'] }}"
    
        - name: Перезапустить NGINX
          ansible.builtin.service:
            name: nginx
            state: restarted
    
  • inventory_hostname – название узла в инвентарном списке.

    Пример использования inventory_hostname

    Создание лог-файла с названием, соответствующим конкретному серверу:

    ---
    - name: Создание лог-файлов
      hosts: all
      tasks:
        - name: Создать лог-файл для каждого узла
          ansible.builtin.file:
            path: "/var/logs/{{ inventory_hostname }}.log"
            state: touch
    
  • playbook_dir – каталог с текущим набором сценариев.

    Пример использования playbook_dir

    Копирование конфигурационного файла app.conf:

    ---
    - name: Развертывание конфигурации
      hosts: all
      become: yes
      tasks:
        - name: Копировать конфиг
          ansible.builtin.copy:
            src: "{{ playbook_dir }}/files/app.conf"
            dest: /etc/app/app.conf
            mode: '0644'
    

Кроме того, можно определять пользовательские переменные для использования в сценариях.

Сбор данных#

Ansible может собирать информацию об управляемых узлах, называемую фактами (facts). Факты используются для динамического изменения значений переменных, адаптации сценариев к конфигурации ОС и оборудования. Они могут быть полезны для определения ОС и выбора соответствующих пакетов, получения информации о сетевых интерфейсах, проверки параметров аппаратного обеспечения перед установкой ПО и так далее.

Сбором фактов управляет переменная gather_facts. По умолчанию ее значение равно true.

Пример набора сценариев с использованием фактов#
---
- name: Сбор информации о системе
  hosts: all
  tasks:
    - name: Вывод названия семейства ОС
      ansible.builtin.debug:
        msg: "ОС: {{ ansible_facts['os_family'] }}"

Если сценарий не использует факты, их сбор можно отключить для ускорения выполнения, установив переменной gather_facts значение false.

Пример набора сценариев без использования фактов#
---
- name: Развертывание конфигурации
  hosts: all
  gather_facts: false
  tasks:
    - name: Копирование конфигурационного файла
      ansible.builtin.copy:
      src: myconfig.cfg
      dest: /etc/myconfig.cfg

Управление пакетами и службами#

Ansible позволяет устанавливать и удалять пакеты, а также управлять службами. Для этого используются разные модули:

  • В ОС Astra Linux для управления пакетами используйте модуль ansible.builtin.apt.

  • Для управления службами используйте модули ansible.builtin.service или ansible.builtin.systemd.

Пример сценария для установки пакета и настройки связанных служб#
---
- name: Установка и управление Apache
  hosts: webservers
  tasks:
    - name: Установка Apache
      ansible.builtin.apt:
        name: apache2
        state: present

    - name: Запуск службы Apache с помощью модуля ansible.builtin.service
      ansible.builtin.service:
        name: apache2
        state: started

    - name: Перезапуск службы Apache с помощью модуля ansible.builtin.systemd
      ansible.builtin.systemd:
        name: apache2
        state: restarted

    - name: Остановка и отключение автозапуска Apache с помощью модуля ansible.builtin.systemd
      ansible.builtin.systemd:
        name: apache2
        state: stopped
        enabled: false

    - name: Удаление пакетов Apache
      ansible.builtin.apt:
        name: apache2
        state: absent

Управление файлами#

Ansible предоставляет ряд модулей для работы с файлами и каталогами, каждый из которых выполняет определенные задачи:

  • ansible.builtin.blockinfile – работа с блоками текста: добавление, изменение или удаление.

  • ansible.builtin.copy – копирование файлов с управляющего узла на управляемые, при необходимости изменяя права доступа и владельца.

  • ansible.builtin.fetch – копирование файлов с управляемых узлов на управляющий.

  • ansible.builtin.file – управление файлами и каталогами: создание, удаление, изменение прав доступа и владельцев, а также установка временных меток.

  • ansible.builtin.get_url – загрузка файлов из сети и сохранение их на целевых узлах.

  • ansible.builtin.lineinfile – управление отдельными строками в файле: добавление, изменение или удаление.

  • ansible.builtin.replace – замена текста в файлах с использованием регулярных выражений.

  • ansible.builtin.stat – проверка наличия файла или каталога, а также получение сведений о его свойствах.

  • ansible.builtin.template – обработка текстовых файлов с помощью шаблонизатора Jinja и их копирование в указанное расположение на управляемых узлах.

Пример файла шаблона templates/nginx.conf.j2#
server {
    listen 80;
    server_name {{ server_name }};
    root {{ document_root }};
}
Пример набора сценариев с использованием шаблона#
---
- name: Развертывание конфигурационного файла из шаблона
  hosts: all
  vars:
    server_name: example.com
    document_root: /var/www/html
  tasks:
    - name: Создать конфигурационный файл из шаблона
      ansible.builtin.template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'

Переменные#

Переменные позволяют задавать динамические значения в сценариях. Они могут хранить строки, числа, списки и сложные структуры данных.

Значения переменным могут быть присвоены следующими способами:

  • В сценарии внутри секции vars.

  • В отдельных файлах формата YAML. Затем эти файлы подключаются к задачам в блоке vars_files.

  • В файлах формата YAML из каталогов group_vars/ и host_vars/, размещенных в одном каталоге с набором сценариев.

  • Через аргумент командной строки -e.

  • Используя значения фактов (ansible_facts).

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

Список источников значений переменных в порядке возрастания приоритета:

  1. Значения, переданные через командную строку (например, -u my_user). Эти параметры не являются переменными и имеют самый низкий приоритет.

  2. Значения по умолчанию, заданные в определении роли (в каталоге роли).

  3. Групповые переменные из файла со статическим описанием инвентаря или заданные с помощью сценария динамического определения инвентаря.

  4. Групповые переменные инвентаря, заданные в файле group_vars/all[.yml]. Каталог group_vars/ находится в одном каталоге с файлом инвентаря.

  5. Групповые переменные набора сценариев, заданные в файле group_vars/all[.yml].

  6. Групповые переменные инвентаря, заданные для групп индивидуально в файлах group_vars/<group_name>[.yml].

  7. Групповые переменные набора сценариев, заданные для групп индивидуально в файлах group_vars/<group_name>[.yml].

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

  9. Переменные узла, заданные для описания инвентаря в файле host_vars/<host_name>[.yml].

  10. Переменные узла, заданные для сценариев в файле host_vars/<host_name>[.yml].

  11. Факты узла, включая ansible_facts и кешированные переменные, установленные через set_facts.

  12. Переменные, объявленные в сценарии в секции vars.

  13. Переменные, запрашиваемые у пользователя во время выполнения сценария через vars_prompt.

  14. Переменные, загружаемые из файлов, указанных в секции vars_files.

  15. Переменные роли, заданные в файлах из ее каталога vars/.

  16. Переменные, объявленные внутри блока и применимые только к задачам в этом блоке (block vars).

  17. Переменные, объявленные внутри задачи и доступные только в рамках ее выполнения (task vars).

  18. Переменные, загруженные во время выполнения сценария с помощью include_vars.

  19. Переменные, установленные во время выполнения сценария через set_facts или сохраненные как зарегистрированные переменные.

  20. Параметры, переданные в роли и include_role при их вызове.

  21. Параметры, переданные при использовании include_* для подключения сценариев или файлов.

  22. Дополнительные переменные (extra vars), переданные в аргументе командной строки -e.

Пример сценария с использованием переменной и несколькими уровнями приоритетов
vars_file.yml#
package_name: apache2  # Переменная в файле переменных
install_package.yml#
---
- name: Установка пакета с разными источниками переменных
  hosts: localhost
  vars_files:
    - vars_file.yml  # Подключение файла переменных
  vars:
    package_name: nginx  # Переменная на уровне сценария

  tasks:
    - name: Установить {{ package_name }}
      ansible.builtin.apt:
        name: "{{ package_name }}"
        state: present

В этом примере переменная package_name будет иметь значение apache2, потому что переменные, загруженные из файлов, имеют более высокий приоритет, чем переменные, заданные в сценарии.

Условные выражения#

Условные выражения позволяют выполнять задачи только при соблюдении определенного условия.

В Ansible для этого используется параметр when, который проверяет условие перед выполнением задачи. Если условие выполняется, выполняется и задача. В противном случае она пропускается.

Пример набора сценариев с использованием условного выражения#
---
- name: Установка Apache только для Astra Linux
  hosts: webservers
  tasks:
    - name: Установить apache2, если ОС - Astra Linux
      ansible.builtin.apt:
        name: apache2
        state: present
      when: ansible_facts['ansible_distribution'] == "Astra Linux"

В данном примере задача по установке пакета apache2 будет выполняться только на тех узлах, на которых название дистрибутива равно строке Astra Linux. Это условие проверяется с помощью факта ansible_distribution. Он содержит название дистрибутива ОС, под управлением которого работает управляемый узел.

Циклы#

Ansible поддерживает циклы для выполнения одной задачи несколько раз с разными значениями параметров.

Для задания цикла используется директива loop, в которой указывается список значений. Каждое значение по умолчанию передается в задачу в виде переменной item.

Циклы можно сочетать с дополнительными директивами управления, например:

  • loop_control – настройка цикла. Например, изменение названия переменной цикла (loop_var), управление тем, как элементы отображаются в выводе (label) и так далее.

  • until – условие прерывания цикла.

  • retries – количество попыток повторного выполнения при использовании until.

  • delay – интервал между попытками (в секундах).

  • pause – пауза между итерациями.

Пример создания нескольких пользователей с использованием цикла
---
- name: Создание нескольких пользователей
  hosts: all
  become: yes
  tasks:
    - name: Добавление пользователей
      ansible.builtin.user:
        name: "{{ item }}"
        state: present
      loop:
        - user1
        - user2
        - user3

В этом примере кода модуль ansible.builtin.user используется для создания учетных записей пользователей user1, user2 и user3. Список названий учетных записей хранится в блоке loop. Для получения действующего значения названия учетной записи используется переменная item, которая последовательно принимает указанные значения.

Пример цикла с контролем выполнения и проверкой условия

Первая задача этого сценария проверяет статус службы по указанным URI. На проверку дается 5 попыток с интервалом 10 секунд.

---
- name: Проверка запуска службы
  hosts: app_servers
  become: yes
  tasks:
    - name: Проверка доступности веб-приложения
      ansible.builtin.uri:
        url: "{{ endpoint }}"
        status_code: 200
      register: result
      until: result.status == 200
      retries: 5
      delay: 10
      loop:
        - "http://localhost:8080/health"
        - "http://localhost:9090/status"
      loop_control:
        loop_var: endpoint
        label: "{{ endpoint }}"
      vars:
        ansible.builtin.uri.url: "{{ endpoint }}"

Здесь:

  • loop – перебор списка URL-адресов, которые нужно проверить;

  • loop_control.loop_var – использование названия переменной endpoint вместо item;

  • loop_control.label – управление отображением в выводе (например, название проверяемого URL);

  • register – сохранение результата выполнения задачи в переменную result;

  • until – указание условия: задача должна вернуть HTTP-статус 200;

  • retries – количество попыток получения HTTP-статуса 200;

  • delay – интервал между попытками в секундах.