Как перезагрузить 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
Что я делаю неправильно? Как я могу это исправить?
Ответы
Ответ 1
Вероятно, вы ничего не делаете неправильно, просто это /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-соединения, тем самым избегая ошибки, которую вы сейчас получаете.
Ответ 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
- 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
Ответ 4
Ни одно из вышеперечисленных решений не было надежным для меня.
Выдача /sbin/reboot
приводит к сбою воспроизведения (соединение SSH закрывается до того, как закончена задача, она сработает даже с 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 & )
в оболочке script запускает программу в фоновом режиме и отделяет ее: команда выполняется немедленно, но сохраняется после уничтожения оболочки.
Ansible немедленно получит ответ, и сервер перезагрузится через 3 секунды.
Ответ 5
Другое решение:
- 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 секунд, чтобы убедиться, что хост действительно начал перезагружаться.
Ответ 6
Во время перезагрузки все соединения ssh закрыты. Вот почему задача Ansible не работает. Добавления 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
Ответ 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 быстро развивается, и старые ответы не работают для меня.
Я нашел два вопроса:
- Рекомендуемый способ перезагрузки может убить SSH-соединение до того, как Ansible завершит задачу.
Лучше запустить: nohup bash -c "sleep 2s && shutdown -r now" &
Это запустит оболочку с sleep
&& & shutdown
, но не будет ждать завершения оболочки из-за последнего &
. Сон даст некоторое время для завершения задачи 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
У меня есть команда nohup из: https://github.com/keithchambers/microservices-playground/blob/master/playbooks/upgrade-packages.yml
Я отредактировал это сообщение:
- добавить предложение krad portability, используя shutdown -r вместо перезагрузки
- добавить задержку. Необходимо, чтобы Ansible выполнил следующий шаг, если перезагрузка будет медленной.
- увеличить таймаут, 120 секунд было слишком мало для некоторых медленных BIOS.