如何使用Ansible等待服务器重启?

我试图重新启动服务器,然后等待,使用这个:

- name: Restart server shell: reboot - name: Wait for server to restart wait_for: port=22 delay=1 timeout=300 

但是我得到这个错误:

 TASK: [iptables | Wait for server to restart] ********************************* fatal: [example.com] => failed to transfer file to /root/.ansible/tmp/ansible-tmp-1401138291.69-222045017562709/wait_for: sftp> put /tmp/tmpApPR8k /root/.ansible/tmp/ansible-tmp-1401138291.69-222045017562709/wait_for Connected to example.com. Connection closed 

您应该将wait_for任务更改为以local_action身份运行,并指定您正在等待的主机。 例如:

 - name: Wait for server to restart local_action: module: wait_for host=192.168.50.4 port=22 delay=1 timeout=300 

等待作为一项任务

你可以使用:

 - name: Wait for server to restart local_action: module: wait_for host={{ inventory_hostname }} port=22 delay=1 timeout=300 sudo: false 

{{ ansible_ssh_host }}但是,如果使用以下条目,则可能更愿意使用{{ ansible_ssh_host }}variables作为主机名和/或{{ ansible_ssh_port }}作为SSH主机和端口:

 hostname ansible_ssh_host=some.other.name.com ansible_ssh_port=2222 

在你的清单(Ansible hosts文件)。

等待作为处理程序

但我build议使用这个作为handler ,而不是一个task 。 这是做这件事的两个主要原因:

  • 代码重用 – 你可以使用一个处理程序的许多任务。 例如: 更改时区和更改内核后触发服务器重新启动,
  • 只触发一次 – 如果你为一些任务使用一个处理程序,并且其中多于一个的处理程序会做一些更改=>触发处理程序,那么处理程序所做的事情只会发生一次。 例如:如果您有一个httpd重新启动处理程序连接到httpd config更改和SSL证书更新,则configuration和SSL证书更改httpd将只重新启动一次。

在这里阅读更多关于处理程序: http : //docs.ansible.com/ansible/playbooks_intro.html#handlers-running-operations-on-change

作为处理程序重新启动并等待重新启动:

  handlers: - name: Restart server command: shutdown -r now "Reboot triggered by Ansible" async: 0 poll: 0 ignore_errors: true - name: Wait for server to restart local_action: module: wait_for host={{ inventory_hostname }} port=22 delay=1 timeout=300 sudo: false 

..并按顺序在你的任务中使用它,像这样,在这里配对重新启动服务器处理程序:

  tasks: - name: Set hostname hostname: name=somename notify: - Restart server - Wait for server to restart 

请注意,处理程序按照它们定义的顺序运行,而不是它们在notify中列出的顺序!

我用1.9.4得到的最可靠的是(这是更新,原始版本是在底部):

 - name: Example ansible play that requires reboot sudo: yes gather_facts: no hosts: - myhosts tasks: - name: example task that requires reboot yum: name=* state=latest notify: reboot sequence handlers: - name: reboot sequence changed_when: "true" debug: msg='trigger machine reboot sequence' notify: - get current time - reboot system - waiting for server to come back - verify a reboot was actually initiated - name: get current time command: /bin/date +%s register: before_reboot sudo: false - name: reboot system shell: sleep 2 && shutdown -r now "Ansible package updates triggered" async: 1 poll: 0 ignore_errors: true - name: waiting for server to come back local_action: wait_for host={{ inventory_hostname }} state=started delay=30 timeout=220 sudo: false - name: verify a reboot was actually initiated # machine should have started after it has been rebooted shell: (( `date +%s` - `awk -F . '{print $1}' /proc/uptime` > {{ before_reboot.stdout }} )) sudo: false 

请注意async选项。 1.8和2.0可以用0来生活,但是1.9要用1 。 以上也检查机器是否真的重新启动。 这是很好的,因为一旦我有一个错误的重新启动失败,没有迹象。

最大的问题是等待机器启动。 这个版本在那里只有330秒,从来没有尝试访问主机。 其他一些答案build议使用端口22.这是好的,如果这两个都是真的:

  • 你可以直接访问机器
  • 您的机器可以在22号端口打开后立即进入

这些并不总是如此,所以我决定浪费5分钟的计算时间。我希望能够扩展wait_for模块来实际检查主机状态以避免浪费时间。

顺便说一句,build议使用处理程序的答案是很好的。 来自我的处理程序+1(我更新了使用处理程序的答案)。

这里是原来的版本,但它不是很好,不太可靠:

 - name: Reboot sudo: yes gather_facts: no hosts: - OSEv3:children tasks: - name: get current uptime shell: cat /proc/uptime | awk -F . '{print $1}' register: uptime sudo: false - name: reboot system shell: sleep 2 && shutdown -r now "Ansible package updates triggered" async: 1 poll: 0 ignore_errors: true - name: waiting for server to come back local_action: wait_for host={{ inventory_hostname }} state=started delay=30 timeout=300 sudo: false - name: verify a reboot was actually initiated # uptime after reboot should be smaller than before reboot shell: (( `cat /proc/uptime | awk -F . '{print $1}'` < {{ uptime.stdout }} )) sudo: false 

我想对Shahar发表评论,他使用硬编码的主机地址更好的是让它有一个variables来引用当前主机,因为他正在configuration{{inventory_hostname}},所以他的代码将如下所示:

 - name: Wait for server to restart local_action: module: wait_for host={{ inventory_hostname }} port=22 delay=1 timeout=300 

随着更新版本的Ansible(即我的1.9.1),轮询和asynchronous参数设置为0有时是不够的(可能取决于什么分配是可行的?)。 正如https://github.com/ansible/ansible/issues/10616中所解释的,一种解决方法是:;

 - name: Reboot shell: sleep 2 && shutdown -r now "Ansible updates triggered" async: 1 poll: 0 ignore_errors: true 

然后,等待重新启动完成,如本页的许多答案中所述。

通过试验和错误+很多阅读这是什么最终为我使用Ansible的2.0版本:

 $ ansible --version ansible 2.0.0 (devel 974b69d236) last updated 2015/09/01 13:37:26 (GMT -400) lib/ansible/modules/core: (detached HEAD bbcfb1092a) last updated 2015/09/01 13:37:29 (GMT -400) lib/ansible/modules/extras: (detached HEAD b8803306d1) last updated 2015/09/01 13:37:29 (GMT -400) config file = /Users/sammingolelli/projects/git_repos/devops/ansible/playbooks/test-2/ansible.cfg configured module search path = None 

我的解决scheme禁用SELinux并在需要时重新启动节点:

 --- - name: disable SELinux selinux: state=disabled register: st - name: reboot if SELinux changed shell: shutdown -r now "Ansible updates triggered" async: 0 poll: 0 ignore_errors: true when: st.changed - name: waiting for server to reboot wait_for: host="{{ ansible_ssh_host | default(inventory_hostname) }}" port={{ ansible_ssh_port | default(22) }} search_regex=OpenSSH delay=30 timeout=120 connection: local sudo: false when: st.changed # vim:ft=ansible: 
 - wait_for: port: 22 host: "{{ inventory_hostname }}" delegate_to: 127.0.0.1 

如果您还没有远程服务器的DNS设置,则可以传递IP地址而不是variables主机名:

 - name: Restart server command: shutdown -r now - name: Wait for server to restart successfully local_action: module: wait_for host={{ ansible_default_ipv4.address }} port=22 delay=1 timeout=120 

这些是我添加到我的交换剧本结束的两个任务(在新的数字海洋水滴上安装4GB交换。