【问题标题】:How to reboot CentOS 7 with Ansible?如何使用 Ansible 重启 CentOS 7?
【发布时间】:2015-07-09 10:33:13
【问题描述】:

我正在尝试重新启动在 VirtualBox 上运行 CentOS 7 的服务器。我使用这个任务:

- name: Restart server
  command: /sbin/reboot
  async: 0
  poll: 0
  ignore_errors: true

服务器已重新启动,但出现此错误:

TASK: [common | Restart server] ***********************************************
fatal: [rolcabox] => SSH Error: Shared connection to 127.0.0.1 closed.
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.

FATAL: all hosts have already failed -- aborting

我做错了什么?我该如何解决这个问题?

【问题讨论】:

  • 根据 Marcin Skarbek 提供的答案,我准备并向 Ansible Galaxy 角色发布了使用该方法的内容。角色 Reboot-And-Wait 你可以找到here。感谢您的使用,欢迎反馈。
  • 由于 Ansible 的快速发展,旧的答案不再适合我。请看我的回答。

标签: centos ansible centos7


【解决方案1】:

您可能没有做任何真正的错误,只是 /sbin/reboot 关闭服务器的速度如此之快,以至于服务器在 Ansible 本身可以关闭它之前就断开了 Ansible 使用的 SSH 连接。结果,Ansible 报告错误,因为它发现 SSH 连接因意外原因而失败。

您可能想要做的就是从使用/sbin/reboot 切换到使用/sbin/shutdown。关闭命令可以让您消磨时间,当与-r 开关结合使用时,它将执行重新启动而不是实际关闭。所以你可能想尝试这样的任务:

- name: Restart server
  command: /sbin/shutdown -r +1
  async: 0
  poll: 0
  ignore_errors: true

这将使服务器重启延迟 1 分钟,但这样做应该给 Ansible 足够的时间来关闭 SSH 连接本身,从而避免您当前遇到的错误。

【讨论】:

  • 谢谢,这很好用!只有一个小问题:我遇到了Failed to parse time specification: +1m 错误,所以我不得不将+1m 替换为+1
  • 注意:除非您知道自己在做什么,否则使用重启不是一个好主意。在很多 linux 发行版中它可能没问题,但在其他 unix 上它可以绕过很多系统关闭脚本,而且非常困难。这可能会导致不一致的 dbs 等,这是不好的做法。最好使用 shutdown 或 init。
  • 这里异步和轮询的目的是什么?
  • @Basil,see the docs here。 ;)
【解决方案2】:

重启任务后,你应该有一个local_action任务等待远程主机完成重启,否则ssh连接将被终止,playbook也会被终止。


- name: Reboot server
  command: /sbin/reboot

- name: Wait for the server to finish rebooting
  sudo: no
  local_action: wait_for host="{{ inventory_hostname }}" search_regex=OpenSSH port=22 timeout=300

我还写了一篇关于实现类似解决方案的博文:https://oguya.github.io/linux/2015/02/22/ansible-reboot-servers/

【讨论】:

    【解决方案3】:

    在重新启动时,所有 ssh 连接都将关闭。这就是 Ansible 任务失败的原因。从 Ansible 1.9.x 开始,ignore_errors: truefailed_when: false 新增功能不再起作用,因为 ssh 连接的处理方式发生了变化,现在关闭的连接是一个致命错误,在播放过程中无法捕获。

    我想出的唯一方法是运行一个本地 shell 任务,然后启动一个单独的 ssh 连接,然后可能会失败。

    - name: Rebooting
      delegate_to: localhost
      shell: ssh -S "none" {{ inventory_hostname }} sudo /usr/sbin/reboot"
      failed_when: false
      changed_when: true
    

    【讨论】:

    • 感谢您的解释,但您的方法可能需要无密码 sudo(或者我错过了什么?),所以我无法在生产中使用它。
    【解决方案4】:

    另一种解决方案:

    - name: reboot host
      command: /usr/bin/systemd-run --on-active=10 /usr/bin/systemctl reboot
      async: 0
      poll: 0
    
    - name: wait for host sshd
      local_action: wait_for host="{{ inventory_hostname }}" search_regex=OpenSSH port=22 timeout=300 delay=30
    

    systemd-run 创建“即时”新服务,该服务将在延迟 10 秒 (--on-active=10) 后启动 systemctl rebootdelay=30wait_for 中添加额外的 20 秒以确保主机实际开始重新启动。

    【讨论】:

    • 非常感谢,我认为您的解决方案是最好的,带有 wait_for。
    • 谢谢,多等一分钟!
    【解决方案5】:

    以上解决方案都不适合我。

    发出/sbin/reboot 会导致播放崩溃(SSH 连接在 ansible 完成任务之前关闭,即使使用ignore_errors: true 也会崩溃)并且/usr/bin/systemd-run --on-active=2 /usr/bin/systemctl reboot 不会在 2 秒后重新启动,而是在随机时间之间20 秒 1 分钟,所以延迟有时不够,这是不可预测的。

    我也不想等待几分钟,而云服务器可以在几秒钟内重新启动。

    所以这是我的解决方案:

    - name: Reboot the server for kernel update
      shell: ( sleep 3 && /sbin/reboot & )
      async: 0
      poll: 0 
    
    - name: Wait for the server to reboot
      local_action: wait_for host="{{ansible_host}}" delay=15 state=started port="{{ansible_port}}" connect_timeout=10 timeout=180
    

    这就是 shell: ( sleep 3 && /sbin/reboot & ) 行的作用。

    在 shell 脚本中使用( command & ) 在后台运行程序并将其分离:该命令立即成功,但在 shell 销毁后仍然存在。

    Ansible 立即得到响应,3 秒后服务器重启。

    【讨论】:

    • 把/sbin/reboot命令放到后台有什么帮助?
    • @mbigras 因为没有阻塞 Ansible 的执行,所以第二个动作立即执行。没有它,它将无法工作:Ansible 将等待命令返回,但在系统关闭期间将失去连接。我相信最新的 Ansible 版本有更好的解决方案,但我没有进一步调查。
    • @mbigras 无论如何,不​​管是什么原因,其他答案对我来说根本不可靠。
    【解决方案6】:
    - name: restart server
      shell: sleep 2 && shutdown -r now "Ansible updates triggered"
      async: 1
      poll: 0
      become: true
      ignore_errors: true
    
    
    - name: waiting for the server to come back
      local_action: wait_for host=testcentos state=started delay=30 timeout=300
      sudo: false
    

    【讨论】:

    • 这对我很有用,尤其是async: 1。 Ansible 2.3 添加了有用的wait_for_connection delay=20
    • wait_for_connection 更好
    【解决方案7】:

    另一个(结合其他答案)版本:

    ---
    - name: restart server
      command: /usr/bin/systemd-run --on-active=5 --timer-property=AccuracySec=100ms /usr/bin/systemctl reboot
      async: 0
      poll: 0
      ignore_errors: true
      become: yes
    
    - name: wait for server {{ ansible_ssh_host | default(inventory_hostname) }} to come back online
      wait_for:
        port: 22
        state: started
        host: '{{ ansible_ssh_host | default(inventory_hostname) }}'
        delay: 30
      delegate_to: localhost
    

    【讨论】:

      【解决方案8】:

      Ansible 发展迅速,旧的答案对我不起作用。

      我发现了两个问题:

      • 推荐的重启方式可能会在 Ansible 完成任务之前终止 SSH 连接。

      最好跑:nohup bash -c "sleep 2s && shutdown -r now" &

      这将使用sleep && shutdown 启动一个shell,但由于最后一个& 而不会等待shell 结束。睡眠将为 Ansible 任务在重新启动之前结束提供一些时间,nohup 将保证 bash 在任务结束时不会被杀死。

      • wait_for 模块无法可靠地等待 SSH 服务。

      它检测到端口打开,可能是systemd打开的,但是当下一个任务运行时,SSH仍然没有准备好。

      如果您使用的是 Ansible 2.3+,wait_for_connection 可以可靠地工作。

      根据我的经验(我使用的是 Ansible 2.4),最好的“重启并等待”如下:

      - name: Reboot the machine
        shell: nohup bash -c "sleep 2s && shutdown -r now" &
      
      - name: Wait for machine to come back
        wait_for_connection:
          timeout: 240
          delay: 20
      

      我从 https://github.com/keithchambers/microservices-playground/blob/master/playbooks/upgrade-packages.yml 获得了 nohup 命令

      我将此消息编辑为:

      • 添加 krad 的可移植性建议,使用 shutdown -r now 而不是重新启动
      • 添加延迟。如果重启很慢,需要避免 Ansible 执行下一步
      • 增加超时时间,对于某些慢速 BIOS 来说,120 秒太少了。

      【讨论】:

      • 根据我以前的 cmets 使用 reboot 真的很糟糕
      • 在非 Linux 世界中听起来很明智。我从来没有发现一个 linux 的重启不会执行适当的有组织的重启。
      • 另一个优点是关闭命令可以包含超时,无需使用睡眠,更干净。我喜欢您关于可移植性的建议,但我会在此处更改之前对其进行测试,以防万一。我发布的答案是最简单的,同时也可以可靠地工作。
      • 我看过了,我不喜欢关机的一件事。延迟的最小粒度是 1 分钟,这很浪费,所以我们不能停止使用睡眠。
      • 只需使用 'shutdown now' 并在前面休眠。世界比 linux 还大。
      【解决方案9】:

      我正在使用 Ansible 2.5.3。 下面的代码可以轻松运行,

      - name: Rebooting host
        shell: 'shutdown -r +1 "Reboot triggered by Ansible"'
      
      - wait_for_connection:
          delay: 90
          timeout: 300
      

      您可以立即重新启动,然后如果您的机器需要一段时间才能关闭,请插入延迟:

          - name: Rebooting host
            shell: 'shutdown -r now "Reboot triggered by Ansible"'
            async: 1
            poll: 1
            ignore_errors: true
      
      # Wait 120 seconds to make sure the machine won't connect immediately in the next section.
          - name: Delay for the host to go down
            local_action: shell /bin/sleep 120
      

      然后轮询让剧本尽快返回:

          - name: Wait for the server to finish rebooting
            wait_for_connection:
              delay: 15
              sleep: 15
              timeout: 300
      

      这将使 playbook 在重启后尽快返回。

      【讨论】:

      • 您好,我发现这个解决方案可能有效,但不是最佳的。我在回答的评论中指定了原因,这些原因是:-shutdown -r +1 是安全的并且将始终有效,但是 +1 会为重启增加一分钟的延迟,这可能是不可取的。 - shutdown -r now 是不安全的,因为 ssh 可能在 Ansible 得到答案之前被杀死,返回失败,因此需要 +1 或 nohup + sleep 组合。我想找一个更简单的解决方案,比如shutdown -r +1,但我不想要1分钟的延迟。
      • 看来您的 nohup 答案只是另一种剥猫皮的方法。您已经为 shell 提供了干净退出的工作,因此您不必告诉 Ansible 忽略该错误。你说potaytoh,我说potahtoe。
      • 嗯,避免触发错误通常比忽略错误要好。通过忽略所有可能的关闭错误,您可能会忽略另一个应该注意的错误。
      【解决方案10】:

      以下解决方案非常适合我:

      - name: Restart machine
        shell: "sleep 5 && sudo shutdown -r now"
        async: 1
        poll: 0
      
      - name: wait for ssh again available.
        wait_for_connection:
          connect_timeout: 20
          sleep: 5
          delay: 5
          timeout: 300
      

      需要睡眠,因为 ansible 需要几秒钟来结束连接。 关于这个问题的优秀帖子写在这里: https://www.jeffgeerling.com/blog/2018/reboot-and-wait-reboot-complete-ansible-playbook

      【讨论】:

        【解决方案11】:

        如果您使用 Ansible 版本 >=2.7,则可以使用 reboot 模块,如 here 所述

        reboot 模块本身的概要:

        重新启动一台机器,等待它停机、恢复并响应命令。

        通过一种简单的方式,您可以像这样定义一个简单的任务:

            - name: reboot server
              reboot:
        

        但是您可以添加一些参数,例如 test_command 来测试您的服务器是否准备好接受进一步的任务

            - name: reboot server
              reboot:
                test_command: whoami
        

        希望这会有所帮助!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-12-18
          • 1970-01-01
          • 2019-02-18
          • 1970-01-01
          • 1970-01-01
          • 2020-10-21
          • 2018-02-12
          相关资源
          最近更新 更多