Обработчики: выполнение операций при изменении
Иногда нужно, чтобы задача выполнялась только при изменении на машине. Например, вы можете захотеть перезапустить службу, если задача обновляет конфигурацию этой службы, но не если конфигурация не изменена. 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).
Примечание
- Обработчики всегда выполняются в порядке их определения, а не в порядке, указанном в операторе уведомления. Это также относится к обработчикам, использующим
listen. - Имена обработчиков и
listenтемы существуют в глобальном пространстве имён. - Имена обработчиков могут быть шаблонизированы, а
listenтемы — нет. - Используйте уникальные имена обработчиков. Если вы запускаете более одного обработчика с одинаковым именем, первые из них перезаписываются. Выполнится только последний определённый.
- Можно уведомлять обработчик, определённый внутри статического include.
- Нельзя уведомлять обработчик, определённый внутри динамического include.
При использовании обработчиков в ролях обратите внимание на следующее:
- Обработчики, уведомлённые в
pre_tasks,tasksиpost_tasksразделах, автоматически очищаются в конце раздела, где они были уведомлены. - Обработчики, уведомлённые в
rolesразделе, автоматически очищаются в концеtasksраздела, но перед любымиtasksобработчиками. - Обработчики обладают областью действия плейбука и могут использоваться вне роли, в которой они определены.
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.10/user_guide/playbooks_handlers.html