it-swarm.com.ru

Как ждать перезагрузки сервера с помощью 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
40
ChocoDeveloper

Вам нужно изменить задачу 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
32
Shahar

Ansible> = 2.7 (выпущено в октябре 2018 г.)

Используйте новый модуль перезагрузка .

Ansible <2,7

Перезагрузка как задача

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

При этом команда Shell запускается как асинхронная задача , поэтому Ansible не будет ждать завершения команды. Обычно параметр async дает максимальное время для выполнения задачи, но, поскольку poll имеет значение 0, Ansible никогда не будет опрашивать, если команда завершилась - она ​​сделает эту команду "выстрелить и забыть". Спит до и после shutdown, чтобы предотвратить разрыв соединения SSH во время перезапуска, пока Ansible все еще подключен к вашему удаленному хосту.

Ждать как задание

Вы можете просто использовать:

- name: Wait for server to restart
  local_action:
    module: wait_for
      Host={{ inventory_hostname }}
      port=22
      delay=10
    become: false

..но вы можете предпочесть использовать переменную {{ ansible_ssh_Host }} в качестве имени хоста и/или {{ ansible_ssh_port }} в качестве хоста и порта SSH, если вы используете записи типа:

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

... в вашем инвентаре (файл Ansible hosts).

Это запустит wait_for task на машине с Ansible . Эта задача будет ожидать открытия порта 22 на удаленном хосте, начиная с 10-секундной задержки.

Перезапустите и ждите как обработчики

Но я предлагаю использовать оба из них как обработчики, а не задачи.

Есть две основные причины сделать это:

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

  • вызвать только один раз - если вы используете обработчик для нескольких задач, и более 1 из них внесут некоторые изменения => запустят обработчик, то то, что делает обработчик, произойдет только один раз. Пример: если у вас есть обработчик перезапуска 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

..и используйте его в своей задаче в такой последовательности, как здесь, в сочетании с перезагрузкой обработчика сервера:

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

Обратите внимание, что обработчики запускаются в том порядке, в котором они определены, а не в порядке, в котором они перечислены в notify!

49
Greg Dubicki

Самый надежный у меня с 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 секунд и никогда не пытается получить доступ к хосту ранее. Некоторые другие ответы предлагают использовать порт 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
10
akostadinov

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

Завершение работы -r +1 предотвращает возврат кода возврата 1 и приводит к сбою задания. Завершение работы выполняется как асинхронная задача, поэтому мы должны отложить задачу wait_for_connection как минимум на 60 секунд. 75 дает нам буфер для этих случаев снежинки.

wait_for_connection - ждет, пока удаленная система не станет доступной/пригодной для использования

8
infrascripting

Я хотел прокомментировать сообщение Шахара, что он лучше использует жестко закодированный адрес Хоста, так как он должен иметь переменную для ссылки на текущий Хост, который настраивает {{инвентарь_хост}}}, поэтому его код будет таким:

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

В более новых версиях Ansible (т. Е. 1.9.1 в моем случае), для параметров poll и async, установленных на 0, иногда недостаточно (может быть в зависимости от того, какой дистрибутив настроен как ansible?). Как объясняется в 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

Затем дождитесь полной перезагрузки, как описано во многих ответах на этой странице.

5
amichaud

Путем проб и ошибок + много чтения, вот что в конечном итоге сработало для меня, используя версию 2.0 Ansible:

$ 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

Мое решение для отключения 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:
4
slm

Я создал ответную роль reboot_server, которую можно динамически вызывать из других ролей с помощью:

- name: Reboot server if needed
  include_role:
    name: reboot_server
  vars:
    reboot_force: false

Содержание роли:

- name: Check if server restart is necessary
  stat:
    path: /var/run/reboot-required
  register: reboot_required

- name: Debug reboot_required
  debug: var=reboot_required

- name: Restart if it is needed
  Shell: |
    sleep 2 && /sbin/shutdown -r now "Reboot triggered by Ansible"
  async: 1
  poll: 0
  ignore_errors: true
  when: reboot_required.stat.exists == true
  register: reboot
  become: true

- name: Force Restart
  Shell: |
    sleep 2 && /sbin/shutdown -r now "Reboot triggered by Ansible"
  async: 1
  poll: 0
  ignore_errors: true
  when: reboot_force|default(false)|bool
  register: forced_reboot
  become: true

# # Debug reboot execution
# - name: Debug reboot var
#   debug: var=reboot

# - name: Debug forced_reboot var
#   debug: var=forced_reboot

# Don't assume the inventory_hostname is resolvable and delay 10 seconds at start
- name: Wait 300 seconds for port 22 to become open and contain "OpenSSH"
  wait_for:
    port: 22
    Host: '{{ (ansible_ssh_Host|default(ansible_Host))|default(inventory_hostname) }}'
    search_regex: OpenSSH
    delay: 10
  connection: local
  when: reboot.changed or forced_reboot.changed

Первоначально он был разработан для работы с ОС Ubuntu.

0
Gio Salvador

Я не видел много информации об этом, но недавнее изменение ( https://github.com/ansible/ansible/pull/43857 ) добавило ключевое слово ignore_unreachable. Это позволяет вам сделать что-то вроде этого:

- name: restart server
  Shell: reboot
  ignore_unreachable: true

- name: wait for server to come back
  wait_for_connection: 
      timeout: 120

- name: the next action
  ...
0
bagelbyte

Если у вас еще нет настройки DNS для удаленного сервера, вы можете передать IP-адрес вместо переменной hostname:

- 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

Это две задачи, которые я добавил в конец моей книги воспроизведения ansible-swap (чтобы установить 4 ГБ подкачки на новые капли Digital Ocean.

0
Aaron Tribou
- wait_for:
    port: 22
    Host: "{{ inventory_hostname }}"
  delegate_to: 127.0.0.1
0
Moriarty