在 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: webserversbecome: yestasks:- name: Deploy configtemplate:src: templates/nginx.conf.j2dest: /etc/nginx/nginx.confnotify: restart nginxhandlers:- name: restart nginxservice:name: nginxstate: 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
场景一:配置发生变更(首次执行或修改模板后)
任务状态显示 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 强制立即执行。
参考文档
- Ansible Official Docs: Handlers
原文链接:https://www.zjcp.cc/ask/11075.html
