Обработчики: выполнение операций при изменении
Иногда вам нужно, чтобы задача выполнялась только при внесении изменений на машине. Например, вы можете захотеть перезапустить службу, если задача обновила конфигурацию этой службы, но не если конфигурация не изменилась. Ansible использует обработчики для решения этой задачи. Обработчики — это задачи, которые выполняются только при уведомлении. Каждый обработчик должен иметь глобально уникальное имя.
Пример обработчика
Этот плейбук, verify-apache.yml, содержит единственный плей с обработчиком:
---
- name: Verify apache installation
hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: Ensure apache is at the latest version
ansible.builtin.yum:
name: httpd
state: latest
- name: Write the apache config file
ansible.builtin.template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- Restart apache
- name: Ensure apache is running
ansible.builtin.service:
name: httpd
state: started
handlers:
- name: Restart apache
ansible.builtin.service:
name: httpd
state: restarted
В этом примере плейбука вторая задача уведомляет обработчик. Одна задача может уведомлять о выполнении более одного обработчика:
- name: Template configuration file
ansible.builtin.template:
src: template.j2
dest: /etc/foo.conf
notify:
- Restart memcached
- Restart apache
handlers:
- name: Restart memcached
ansible.builtin.service:
name: memcached
state: restarted
- name: Restart apache
ansible.builtin.service:
name: apache
state: restarted
Управление выполнением обработчиков
По умолчанию обработчики выполняются после завершения всех задач в конкретном плее. Этот подход эффективен, так как обработчик выполняется только один раз, независимо от того, сколько задач его уведомили. Например, если несколько задач обновляют файл конфигурации и уведомляют обработчик о перезапуске Apache, Ansible перезапускает Apache только один раз, чтобы избежать ненужных перезапусков.
Если вам нужно, чтобы обработчики выполнялись до завершения плей, добавьте задачу для их сброса с помощью модуля meta, который выполняет действия Ansible:
tasks:
- name: Some tasks go here
ansible.builtin.shell: ...
- name: Flush handlers
meta: flush_handlers
- name: Some other tasks
ansible.builtin.shell: ...
Задача meta: flush_handlers запускает любые обработчики, которые были уведомлены на этом этапе плей.
Использование переменных с обработчиками
Возможно, вам нужно, чтобы ваши обработчики Ansible использовали переменные. Например, если имя службы незначительно различается в зависимости от дистрибутива, вы хотите, чтобы ваш вывод отображал точное имя перезапущенной службы для каждой целевой машины. Избегайте размещения переменных в имени обработчика. Поскольку имена обработчиков шаблонизируются на ранней стадии, Ansible может не иметь доступного значения для имени обработчика такого типа:
handlers:
# This handler name may cause your play to fail!
- name: Restart "{{ web_service_name }}"
Если переменная, используемая в имени обработчика, недоступна, весь плей завершается с ошибкой. Изменение этой переменной в середине плей не приведет к созданию нового обработчика.
Вместо этого поместите переменные в параметры задачи вашего обработчика. Вы можете загрузить значения с помощью include_vars следующим образом:
tasks:
- name: Set host variables based on distribution
include_vars: "{{ ansible_facts.distribution }}.yml"
handlers:
- name: Restart web service
ansible.builtin.service:
name: "{{ web_service_name | default('httpd') }}"
state: restarted
Обработчики также могут «прослушивать» общие темы, и задачи могут уведомлять об этих темах следующим образом:
handlers:
- name: Restart memcached
ansible.builtin.service:
name: memcached
state: restarted
listen: "restart web services"
- name: Restart apache
ansible.builtin.service:
name: apache
state: restarted
listen: "restart web services"
tasks:
- name: Restart everything
ansible.builtin.command: echo "this task will restart the web services"
notify: "restart web services"
Это использование упрощает запуск нескольких обработчиков. Оно также отвязывает обработчики от их имен, упрощая совместное использование обработчиков между плейбуками и ролями (особенно при использовании ролей сторонних разработчиков из общего источника, например, Galaxy).
Примечание
- Обработчики всегда выполняются в том порядке, в котором они определены, а не в порядке, указанном в операторе notify. Это также относится к обработчикам, использующим
listen. - Имена обработчиков и
listenтемы существуют в глобальном пространстве имен. - Имена обработчиков могут быть шаблонизированы, а
listenтемы — нет. - Используйте уникальные имена обработчиков. Если вы запускаете более одного обработчика с одинаковым именем, первые обработчики перезаписываются. Будет запущен только последний определенный обработчик.
- Вы можете уведомлять обработчик, определенный внутри статического include.
- Вы не можете уведомлять обработчик, определенный внутри динамического include.
- Обработчик не может выполнить import_role или include_role.
При использовании обработчиков в ролях обратите внимание на следующее:
- обработчики, уведомленные в
pre_tasks,tasks, иpost_tasksразделах, автоматически сбрасываются в конце раздела, в котором они были уведомлены. - обработчики, уведомленные в
rolesразделе, автоматически сбрасываются в концеtasksраздела, но перед любымиtasksобработчиками. - обработчики ограничены плее и могут использоваться за пределами роли, в которой они определены.
© 2012–2018 Michael DeHaan
© 2018–2021 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.11/user_guide/playbooks_handlers.html