Ansible 如何使用 handler 实现服务配置变更后的自动重启?

文章导读
在 Ansible 中,要实现配置变更后自动重启服务,最稳妥的方式是在 tasks 中通过 notify 通知 handlers,并在 handlers 区块定义重启任务,这样只有当配置实际发生变化时才会触发重启。
📋 目录
  1. 环境准备
  2. 完整配置示例
  3. 执行命令与结果验证
  4. 常见坑
  5. 参考文档
A A

在 Ansible 中,要实现配置变更后自动重启服务,最稳妥的方式是在 tasks 中通过 notify 通知 handlers,并在 handlers 区块定义重启任务,这样只有当配置实际发生变化时才会触发重启。

先说结论:通过 notify 触发 handlers 是实现幂等性重启的标准做法,避免每次执行 playbook 都无条件重启服务。

  • 适合:生产环境配置管理、服务批量部署
  • 先看:任务执行结果是否标记为 changed
  • 建议:handler 名称与 notify 字符串必须完全一致

环境准备

确保已安装 Ansible 并配置好 SSH 免密登录。创建以下基础文件结构:

project/
├── inventory      # 主机清单
├── site.yml       # Playbook 文件
└── templates/
    └── nginx.conf.j2 # 配置模板

inventory 文件示例:

[webservers]
192.168.1.10
192.168.1.11

完整配置示例

site.yml playbook 内容:

---
- hosts: webservers
  become: yes
  tasks:
    - name: Deploy config
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

templates/nginx.conf.j2 模板内容示例(简化版):

worker_processes {{ ansible_processor_vcpus }};
events {
    worker_connections 1024;
}
http {
    include /etc/nginx/conf.d/*.conf;
}

执行命令与结果验证

使用以下命令执行 playbook:

ansible-playbook -i inventory site.yml

场景一:配置发生变更(首次执行或修改模板后)

Ansible 如何使用 handler 实现服务配置变更后的自动重启?

任务状态显示 changed,PLAY RECAP 中 handlers 会被触发:

TASK [Deploy config] ***********************************
changed: [192.168.1.10]

RUNNING HANDLER [restart nginx] *********************
changed: [192.168.1.10]

PLAY RECAP ********************************************
192.168.1.10 : ok=2    changed=1    unreachable=0    failed=0

场景二:配置无变更(再次执行)

任务状态显示 ok,handler 不会执行:

TASK [Deploy config] ***********************************
ok: [192.168.1.10]

PLAY RECAP ********************************************
192.168.1.10 : ok=1    changed=0    unreachable=0    failed=0

常见坑

1. 名称拼写错误:notify 与 handler name 不一致导致无法触发,注意大小写和空格。

2. 文件未实际变更:源模板渲染后内容与目标文件完全一致,Ansible 不标记 changed,自然不 notify。

3. 模块选择不当:不要用 command 直接跑 systemctl restart,Ansible 无法感知服务状态,也失去幂等性。

4. 执行时机误解:handler 在整个 play 结束前的 handler flush 阶段统一执行,除非使用 meta: flush_handlers 强制立即执行。

参考文档