目前我正在从 puppet 切换到Ansible,我对一些概念或至少 ansible 的工作方式有点困惑。
有关设置的一些信息:
我正在使用Ansible Best Practices中的示例,并使用多个角色(剧本)等来构建我的项目。
我正在使用 Vagrant 进行配置,盒子是 Saucy64 VBox。
混乱来自哪里:
当我配置并运行 ansible 时,任务开始执行,然后是通知堆栈。
例子:
最后一个任务:
TASK: [mysql | delete anonymous MySQL server user for localhost] **************
<127.0.0.1> REMOTE_MODULE mysql_user user='' state=absent
changed: [default] => {"changed": true, "item": "", "user": ""}
然后是第一个通知:
NOTIFIED: [timezone | update tzdata] ******************************************
<127.0.0.1> REMOTE_MODULE command /usr/sbin/dpkg-reconfigure --frontend noninteractive tzdata
changed: [default] => {"changed": true, "cmd": ["/usr/sbin/dpkg-reconfigure", "--frontend", "noninteractive", "tzdata"], "delta": "0:00:00.224081", "end": "2014-02-03 22:34:48.508961", "item": "", "rc": 0, "start": "2014-02-03 22:34:48.284880", "stderr": "\nCurrent default time zone: 'Europe/Amsterdam'\nLocal time is now: Mon Feb 3 22:34:48 CET 2014.\nUniversal Time is now: Mon Feb 3 21:34:48 UTC 2014.", "stdout": ""}
现在这一切都很好。随着角色的增加,越来越多的通知出现了。
现在问题来了。
当通知失败时,配置将照常停止。但是通知堆栈是空的!这意味着在错误通知之后的所有通知都不会被执行!
如果是这样,那么如果您更改了 apache 的 vhosts 设置并通知 apache 服务重新加载,那么这将丢失。
举个例子(伪语言):
- name: Install Apache Modules
notify: Restart Apache
- name: Enable Vhosts
notify: Reload Apache
- name: Install PHP
command: GGGGGG # throws an error
当上面执行时:
- Apache 模块已安装
- 虚拟主机启用
- PHP 尝试安装但失败
- 脚本退出
- (通知在哪里?)
现在在这一点上一切似乎都是合乎逻辑的,但 Ansible 再次尝试聪明(不!*)堆栈通知,因此重新加载和重新启动 apache 将导致在配置结束时重新启动 apache 运行。这意味着所有通知都将失败!!!
现在到这里对于某些人来说这也很好。他们会说,嘿,只需重新运行配置,通知就会启动,因此 apache 最终将重新加载,站点将再次启动。不是这种情况。
在更正安装 php 的代码后第二次运行脚本时,由于设计原因,通知将不会运行。为什么?
这就是原因:Ansible 会将成功执行的任务标记为“完成/绿色”,因此不会为这些任务注册任何通知。配置将成功,为了触发通知并因此重新启动 apache,您可以执行以下操作之一:
- 通过 ansible 或 ssh 向服务器运行直接命令
- 编辑脚本以触发任务
- 为此添加一个单独的任务
- 销毁盒子实例并重新配置
这非常令人沮丧,因为需要彻底清理盒子,或者我对 Ansible 的理解不正确?
是否有另一种“回收”/重播/强制执行通知的方法?
- 聪明的做法是要么将任务标记为未完成,然后重新启动通知,要么将通知保留一个单独的队列作为它们自己的任务。*