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

Cho*_*per 42 linux deployment ssh ansible ansible-playbook

我正在尝试重新启动服务器,然后等待,使用此:

- name: Restart server
  shell: reboot

- name: Wait for server to restart
  wait_for:
    port=22
    delay=1
    timeout=300
Run Code Online (Sandbox Code Playgroud)

但我得到这个错误:

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
Run Code Online (Sandbox Code Playgroud)

Gre*_*cki 53

Ansible> = 2.7(2018年10月发布)

使用新的重新启动模块.

Ansible <2.7

作为任务重新启动

- name: restart server
  shell: 'sleep 1 && shutdown -r now "Reboot triggered by Ansible" && sleep 1'
  async: 1
  poll: 0
  become: true
Run Code Online (Sandbox Code Playgroud)

这将shell命令作为异步任务运行,因此Ansible不会等待命令的结束.通常asyncparam给出了任务的最大时间,但是当poll设置为0时,Ansible将永远不会轮询该命令是否已完成 - 它将使该命令成为"一次又一次忘记".之前和之后的睡眠shutdown是为了防止在Ansible仍然连接到远程主机时重启期间断开SSH连接.

等待任务

你可以使用:

- name: Wait for server to restart
  local_action:
    module: wait_for
      host={{ inventory_hostname }}
      port=22
      delay=10
    become: false
Run Code Online (Sandbox Code Playgroud)

.. 如果使用以下条目,您可能更喜欢使用{{ ansible_ssh_host }}变量作为主机名和/或{{ ansible_ssh_port }}使用SSH主机和端口:

hostname         ansible_ssh_host=some.other.name.com ansible_ssh_port=2222 
Run Code Online (Sandbox Code Playgroud)

..在你的库存(Ansible hosts文件).

这将在运行Ansible的计算机上运行wait_for任务.此任务将等待端口22在远程主机上打开,在10秒延迟后启动.

重新启动并等待处理程序

但我建议将这两者用作处理程序,而不是任务.

这有两个主要原因:

  • 代码重用 - 您可以为许多任务使用处理程序.示例:更改时区后更改内核后触发服务器重启,

  • 只触发一次 - 如果你为一些任务使用一个处理程序,并且其中一个以上将进行一些更改=>触发处理程序,那么处理程序执行的操作只会发生一次.示例:如果您将httpd重新启动处理程序附加到httpd配置更改和SSL证书更新,那么如果配置和SSL证书更改httpd将仅重新启动一次.

了解更多关于处理程序在这里.

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

  handlers:

    - name: Restart server
      command: 'sleep 1 && shutdown -r now "Reboot triggered by Ansible" && sleep 1'
      async: 1
      poll: 0
      ignore_errors: true
      become: true

    - name: Wait for server to restart
      local_action:
        module: wait_for
          host={{ inventory_hostname }}
          port=22
          delay=10
        become: false
Run Code Online (Sandbox Code Playgroud)

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

  tasks:
    - name: Set hostname
        hostname: name=somename
        notify:
          - Restart server
          - Wait for server to restart
Run Code Online (Sandbox Code Playgroud)

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

  • 处理程序不一定按顺序执行.请检查:[处理程序](http://docs.ansible.com/ansible/playbooks_intro.html)或者我可能误解了? (2认同)

Sha*_*har 35

您应该将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
Run Code Online (Sandbox Code Playgroud)

  • 也可能需要"sudo:false". (5认同)
  • Ansible也有关于这个主题的博客文章也很有帮助:https://support.ansible.com/hc/en-us/articles/201958037-Reboot-a-server-and-wait-for-it-to-come -背部 (3认同)
  • @chachra在博客中他提到了版本[1.9.4]的设置(https://github.com/ansible/ansible/releases/tag/v1.9.4-1).那么对于非1.9.4的情况,它是1.9.4之前,还是1.9.4之后? (2认同)

ako*_*nov 10

最可靠的我有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
Run Code Online (Sandbox Code Playgroud)

请注意该async选项.1.8和2.0可能会一起生活0但1.9需要它1.以上还检查机器是否实际重启.这很好,因为一旦我输入错误,重启失败并且没有失败的迹象.

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

  • 您可以直接访问这些机器
  • 端口22打开后,您的机器可立即访问

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

顺便说一句,建议使用处理程序的答案很好.来自我的处理程序+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
Run Code Online (Sandbox Code Playgroud)


小智 8

2018年更新

从2.3开始,Ansible现在随附wait_for_connection模块,可用于此目的.

#
## Reboot
#

- name: (reboot) Reboot triggered
  command: /sbin/shutdown -r +1 "Ansible-triggered Reboot"
  async: 0
  poll: 0

- name: (reboot) Wait for server to restart
  wait_for_connection:
    delay: 75
Run Code Online (Sandbox Code Playgroud)

shutdown -r +1会阻止返回1的返回码,并且ansible会使任务失败.关闭作为异步任务运行,因此我们必须将wait_for_connection任务延迟至少60秒.75为我们提供了雪花盒的缓冲区.

wait_for_connection - 等待远程系统可达/可用


Wal*_*lid 6

我想评论一下Shahar帖子,他正在使用硬编码的主机地址更好的是让它变量来引用当前主机ansible正在配置{{inventory_hostname}},所以他的代码将是这样的:

- name: Wait for server to restart
  local_action:
    module: wait_for
     host={{ inventory_hostname }}
     port=22
     delay=1
     timeout=300
Run Code Online (Sandbox Code Playgroud)


ami*_*aud 5

对于较新版本的Ansible(在我的情况下为1.9.1),轮询和异步参数设置为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
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么`睡2 &&`而不只是'shutdown -r 2`? (3认同)
  • 并注意不要在这里使用`command`模块,而是使用`shell`模块 (2认同)