Поиск по сайту:

Как использовать обработчики в Ansible Playbooks

Учебное пособие по обработчикам Ansible | Ansible Notify и обработчик

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

Есть две директивы, участвующие в запуске задач-обработчиков.

  • Директива Notify, которая отправит триггерный сигнал запускаемым задачам.
  • Директива-обработчик, по которой группируются задачи.

Давайте поговорим о практическом примере использования. Допустим, вы хотите написать книгу по усилению защиты SSH, в которой вы будете вносить некоторые изменения в файл конфигурации ssh.

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

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

Ключевые моменты обработчиков Ansible

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

  • Задачи-обработчики будут выполняться только тогда, когда родительская задача вносит изменения (changed=true).
  • Задачи-обработчики будут запускаться только в конце каждого воспроизведения, но есть возможность запускать их где угодно.
  • Независимо от того, сколько раз вы вызываете одну и ту же задачу-обработчик в игре на одном хосте, задача-обработчик будет запущена только один раз.
  • Имена задач должны быть уникальными. Если две задачи имеют одинаковое имя, будет запущена только первая задача.
  • Задачи будут выполняться в том порядке, в котором они определены в директиве обработчика, а не в порядке, вызванном директивой notify.

Синтаксис

Чтобы определить задачу обработчика, следует использовать директивы notify и handler. Директива Notify отправит сигнал задаче-обработчику для выполнения.

Ниже приведен пример книги действий. У меня есть две задачи, определенные в директиве обработчика. Для запуска этих задач используется директива notify, а в качестве значения передается имя задачи.

- name: Handlers testing
  hosts: ubuntu.anslab.com
  gather_facts: false

  tasks:
    - name: Get the hostname
      shell: hostname -s
      register: hostname
      notify: print hostname
  handlers:
    - name: print hostname
     debug:
       var: hostname.stdout

    - name: print IP
     debug:
       var: IP.stdout

Ниже приведены результаты плейбука. Несмотря на то, что у меня есть две задачи в обработчике, запускается только одна задача, которая вызывается через директиву notify.

Обработчик — вывод

Вызов нескольких задач

В рамках одной директивы уведомления вы можете вызвать несколько задач-обработчиков. Укажите имя задачи-обработчика в формате списка YAML.

    - name: Get the hostname
      shell: hostname -s
      register: hostname
      notify:
        - print hostname
        - print IP

Нотация списка Python также может использоваться для вызова нескольких задач-обработчиков.

    - name: Get the hostname
      shell: hostname -s
      register: hostname
      notify: ["print hostname", "print IP"]

Порядок исполнения

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

- name: Handlers testing
  hosts: ubuntu.anslab.com
  gather_facts: false

  tasks:
    
    - name: Get the hostname
      shell: hostname -s
      register: hostname
      notify: print hostname

    - name: Get IP address of the hostname
      shell: hostname -I
      register: IP
      notify: print IP

  handlers:
    - name: print hostname
      debug:
        var: hostname.stdout

    - name: print IP
      debug:
        var: IP.stdout

Взгляните на приведенную выше пьесу. Первая задача (получить имя хоста) вызывает задачу-обработчик (напечатать имя хоста). Вторая задача — вызов второй задачи обработчика (печать IP).

Когда я запускаю playbook, обе задачи выполняются первыми и отправляют сигнал обработчику, а задача обработчика запускается после завершения всех задач.

Порядок исполнения

Внимание: независимо от того, как вызывается задача обработчика, она будет выполняться в том порядке, в котором она определена в директиве обработчика.

Запускать только один раз

Вы можете вызвать одну и ту же задачу-обработчик несколько раз, но задача-обработчик будет запущена только один раз.

Я использую ту же книгу, которую использовал в предыдущем разделе, но изменил директиву notify для вызова той же задачи-обработчика (print hostname).

- name: Handlers testing
  hosts: ubuntu.anslab.com
  gather_facts: false

  tasks:
    - name: Get the hostname
      shell: hostname -s
      register: hostname
      notify: print hostname

    - name: Get IP address of the hostname
      shell: hostname -I
      register: IP
      notify: print hostname

  handlers:
    - name: print hostname
      debug:
        var: hostname.stdout

    - name: print IP
      debug:
        var: IP.stdout

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

Запускать только один раз

Дублирующиеся задачи

Как я уже говорил во введении, задачам следует давать описательные и уникальные имена. Если две или более задачи определены с одинаковым именем, будет выполняться только первая задача, прочитанная ansible, игнорируя все остальные задачи с тем же именем.

Если вы посмотрите на задачи ниже, имена обеих задач одинаковы. Теперь, когда я запускаю playbook, ansible запустит первую задачу обработчика и распечатает IP-адрес.

  handlers:
    - name: print hostname
      debug:
        var: IP.stdout
    - name: print hostname
      debug:
       var: hostname.stdout

Дублирующиеся задачи

Обработка сбоев задач

В ansible, если задача завершается неудачно, последующие задачи не будут выполняться. Обработчики обрабатывают сбои следующим образом: если на конкретном хосте происходит сбой какой-либо задачи, то задача обработчика не запускается для этого хоста, даже если невыполненная задача не является родительской задачей (директива notify).

Если вы посмотрите на приведенный ниже сборник сценариев, вы увидите две задачи, использующие модуль оболочки. Первая задача использует /bin/true и всегда будет работать нормально. Эта задача вызывает задачу-обработчик (run_now), которая просто выводит сообщение на стандартный вывод. Вторая задача завершается неудачно с помощью /bin/false.

- name: Testing handler
  hosts: ubuntu.anslab.com
  gather_facts: false

  tasks:
    - name: set a task to success
      shell: /bin/true
      notify: run_now

    - name: set a task to fail
      shell: /bin/false
 
  handlers:
    - name: run_now
      debug: msg="I am called from [ task 1 ]"

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

Сбой задачи — вывод

Давайте посмотрим, как обрабатывать сбои задач с помощью различных вариантов.

1. Обработчики силы

Вы можете установить свойство force_handlers: true в книге воспроизведения, которая будет запускать задачу обработчика, даже если у вас есть сбои задач.

Принудительные обработчики

Вы также можете установить этот параметр в разных областях.

  • Пособие ⇒ force_handlers: true
  • файл ansible.cfg ⇒ force_handlers=true
  • Аргумент командной строки ⇒ --force-handlers

2. Игнорировать ошибки

Вы также можете установить свойство ignore_errors: true, которое будет игнорировать невыполненную задачу и выполнять задачи-обработчики.

Игнорирование ошибок

Промывочный обработчик

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

ansible-doc meta

Мета — документ Ansible

Flush_handlers запустит все задачи, которые уже отправили сигнал директиве notify.

- name: Testing handler
  hosts: ubuntu.anslab.com
  gather_facts: false

  tasks:
    - name: set a task to success
      shell: /bin/true
      notify: run_now

    - name: Run handler now
      meta: flush_handlers

    - name: set a task to fail
      shell: /bin/false
 
  handlers:
    - name: run_now
      debug: msg="I am called from [ task 1 ]"

Промывочный обработчик

Как видно из приведенного выше вывода, задача обработчика выполняется как вторая задача в игре.

Запустите задачу обработчика, используя «Прослушивание»

До сих пор мы запускали все задачи-обработчики, используя имя задачи. Используя «listen», вы можете группировать несколько задач и запускать все задачи с помощью оператора уведомления. Это хорошая альтернатива тегам при использовании обработчиков.

Если вы видите приведенную ниже схему, я установил для параметра listen значение all Task и вызываю его с помощью директивы notify.

- name: Testing handler
  hosts: ubuntu.anslab.com
  gather_facts: false

  tasks:

    - name: set a task to success
      shell: /bin/true
      notify: "all task"

  handlers:

    - name: handler task 1
      debug: 
        msg: This is handler task 1
      listen: "all task"

    - name: handler task 2
      debug: 
        msg: This is handler task 2
      listen: "all task"

    - name: handler task 3
      debug: 
        msg: This is handler task 3
      listen: "all task"

Слушайте темы

Заключение

В этой статье мы увидели, что такое обработчики и как использовать директивы notify и handler в ansible playbook для достижения различных целей.

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

Ресурс:

  • Обработчики: выполнение операций при изменении

Статьи по данной тематике