Как перезагрузить CentOS 7 с помощью Ansible?



Я пытаюсь перезагрузить сервер под управлением CentOS 7 на VirtualBox. Я использую эту задачу:



- 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


Что я делаю не так? Как я могу это исправить?

736   10  

10 ответов:

Вы, вероятно, не делаете ничего по-настоящему плохого, просто /sbin/reboot закрывает сервер так быстро, что сервер разрывает SSH-соединение, используемое Ansible, прежде чем Ansible сам может закрыть его. В результате Ansible сообщает об ошибке, потому что видит, что SSH-соединение не работает по неожиданной причине.

Что вы можете сделать, чтобы обойти это, так это переключиться с использования /sbin/reboot на использование /sbin/shutdown вместо этого. Команда shutdown позволяет вам пройти некоторое время, и когда в сочетании с переключателем -r он будет выполнять перезагрузку, а не фактическое выключение. Поэтому вы можете попробовать выполнить такую задачу:

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

Это задержит перезагрузку сервера на 1 минуту, но при этом должно дать Ansible достаточно времени, чтобы закрыть само SSH-соединение, тем самым избегая ошибки, которую вы сейчас получаете.

После выполнения задачи перезагрузки у вас должна быть задача 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/

- 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

Другое решение:

- 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 создает "на лету" новую службу, которая запустится systemctl reboot через 10 секунд задержки (--on-active=10). delay=30 в wait_for добавить дополнительные 20 секунд, чтобы убедиться, что хост действительно начал перезагрузку.

Ни одно из вышеперечисленных решений не работало для меня надежно.

Выдача /sbin/reboot завершает игру (SSH-соединение закрывается до того, как ansible завершит задачу, оно завершается даже с ignore_errors: true) и /usr/bin/systemd-run --on-active=2 /usr/bin/systemctl reboot не перезагрузится через 2 секунды, но через случайное количество времени между 20 секундами и одной минутой, поэтому задержка иногда не достаточна, и это не предсказуемо.

Также я не хочу ждать несколько минут, пока облачный сервер может перезагрузиться за несколько секунд.

Итак, вот мой решение:

- 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 & ), которая делает трюк.

С помощью скрипта ( command & ) в оболочке запускает программу в фоновом режиме и отсоединяет ее: команда выполняется немедленно, но сохраняется после разрушения оболочки.

Ansible получает свой ответ немедленно, и сервер перезагружается через 3 секунды.

Ансибль развивается быстро, и старые ответы не работали для меня.

Я нашел две проблемы:

  • рекомендуемый способ перезагрузки может убить SSH-соединение до того, как Ansible завершит задачу.

Лучше запустить: nohup bash -c "sleep 2s && shutdown -r now" &

Это запустит оболочку с sleep && shutdown, но не будет ждать окончания оболочки из-за последнего &. Сон даст некоторое время для завершения задачи Ansible до перезагрузки, и nohup будет гарантирую, что Баша не убьют, когда задание закончится.

  • модуль 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

Я получил команду nohup от: https://github.com/keithchambers/microservices-playground/blob/master/playbooks/upgrade-packages.yml

Я отредактировал это сообщение следующим образом:

  • добавьте предложение по переносимости krad, используя shutdown-r теперь вместо перезагрузки
  • добавьте задержку. Это необходимо, чтобы избежать Ansible для выполнения следующего шага, если перезагрузка медленная
  • увеличьте время ожидания, 120s было слишком мало для некоторых медленных BIOS.

Еще одна (объединенная из других ответов) версия:

---
- 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

Во время перезагрузки все ssh-соединения закрываются. Вот почему задача Ансибля терпит неудачу. Дополнения ignore_errors: true или failed_when: false больше не работают по состоянию на Ansible 1.9.x потому что обработка ssh-соединений изменилась, и закрытое соединение теперь является фатальной ошибкой, которую нельзя поймать во время игры.

Единственный способ, которым я понял, как это сделать, - это запустить локальную задачу оболочки, которая затем запускает отдельное ssh-соединение, которое затем может завершиться неудачей.

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

Я использую 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

Затем опрос, чтобы сделать playbook вернуться как можно скорее:

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

Это позволит вернуть playbook как можно скорее после перезагрузки.

Следующее решение работает для меня идеально:

- 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

Comments

    Ничего не найдено.