При выполнении задач в плейбуках периодически возникает необходимость перезапускать какой-либо сервис. Например, при обновлении конфигурационного файла. Простое решение - написать две обычные задачи. Одна из них будет обновлять конфиг, а вторая делать рестарт. И это будет работать, но есть одна проблема: рестарт произойдет в любом случае, даже если конфиг не изменится. В некоторых случаях такое поведение нежелательно, и в принципе это не очень красиво.
Чтобы этого избежать, в Ansible существует механизм, который называется handlers. Воспользуемся им:
На верхнем уровне, где определены хосты и список задач, добавляем еще один ключ с именем handlers и внутри него описываем набор задач. Причем в данном случае обязательно, чтобы задачи содержали имя.
Связываем таски, которые могут порождать изменения, с задачами из секции handlers. Для этого с помощью ключа notify обращаемся к хендлерам по их именам:
- hosts: webservers
tasks:
- name: install nginx
ansible.builtin.apt:
name: nginx
state: latest
become: yes
- name: update nginx config
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
notify:
- restart nginx
become: yes
handlers:
- name: restart nginx
ansible.builtin.service:
name: nginx
state: reloaded
become: yes
Теперь если задача по обновлению конфига произведет изменения, то будет вызван связанный с ней handler, который перезапустит nginx. Важно помнить, что он будет отработан не сразу, а только когда завершится весь сценарий. Это имеет значение. Ведь плейбук может содержать много задач, которые потребуют рестарта nginx. И делать это каждый раз не нужно. Достаточно будет одного перезапуска в самом конце.
Запустим наш плейбук и посмотрим, как это работает:
ansible-playbook playbook.yml -i inventory.ini
Как видим после изменения конфига был вызван handler:
RUNNING HANDLER [restart nginx] *****************************
changed: [ec2-18-216-178-214.us-east-2.compute.amazonaws.com]
Если же запустить сценарий повторно, то конфиг не поменяется и nginx не будет перезапущен.