目前我正在从木偶转为 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
执行以上操作时:
现在这一切似乎都是合乎逻辑的但是Ansible再次试图聪明(没有!*)堆栈通知,因此重新加载和重启apache将导致在配置结束时单次重启apache运行。这意味着所有通知都将失败!!!
现在对某些人来说这也很好。他们会说他们只是重新运行配置并且通知将启动,因此apache将最终重新加载并且站点将再次启动。 情况并非如此。
在更正安装php的代码后,在脚本的第二次运行中,由于设计,通知将无法运行。为什么呢?
这就是为什么: Ansible将具有成功执行的任务,标记为“完成/绿色”,因此不会为这些任务注册任何通知。配置将成功,为了触发通知,因此apache重新启动,您可以执行以下操作之一:
这非常令人沮丧,因为需要彻底清理盒子,或者我对Ansible没有正确理解?
还有另一种'回收'/重播/强制执行通知的方法吗?
答案 0 :(得分:3)
是的,与Puppet相比,这是Ansible的缺点之一。 Puppet是声明性的,并且不会像Ansible(或Chef)那样出错。它有正面和负面的,例如Puppet在开始运行之前需要一点时间,因为它需要编译它的目录。
因此,如果您的Ansible脚本出错,那么您就是对的,那么您的通知更新就不会发生。我们解决它的唯一方法是使用条件语句。在你的剧本中你可以做这样的事情:
- name: My cool playbook
hosts: all
vars:
force_tasks: 0
tasks:
- name: Apache install
action: apt pkg=$item state=latest
with_items:
- apache2
- apache2-mpm-prefork
- name: Restart apache
action: service name=apache2 state=restart
when: force_tasks
然后,当您运行Playbook时,您可以将force_tasks作为环境变量传递:
ansible-playbook -i my_inventory -e "force_tasks=True" my_ansible_playbook.yml
您可以使用与标签类似的方式完成此操作。
答案 1 :(得分:0)
使用--force-handlers标志运行ansible-playbook。这告诉Ansible即使任务失败并且进一步处理停止也会运行任何排队的处理程序。 Ansible开发人员计划将此作为选项添加到ansible.cfg文件中,以便可以全局设置并将其遗忘。我不知道那个时间框架是什么。