Actualización de 2018
A partir de la versión 2.3, Ansible ahora viene con el wait_for_connection
módulo, que se puede utilizar exactamente para este propósito.
#
## 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
El apagado -r +1 evita que se devuelva un código de retorno de 1 y que ansible falle en la tarea. El apagado se ejecuta como una tarea asíncrona, por lo que debemos retrasar el wait_for_connection
tarea por lo menos 60 segundos. 75 nos da un búfer para esos casos de copos de nieve.
wait_for_connection:espera hasta que el sistema remoto sea accesible/utilizable
Lo más confiable que tengo con 1.9.4 es (esto está actualizado, la versión original está en la parte inferior):
- 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
Tenga en cuenta el async
opción. 1.8 y 2.0 pueden vivir con 0
pero 1.9 lo quiere 1
. Lo anterior también verifica si la máquina realmente se ha reiniciado. Esto es bueno porque una vez tuve un error tipográfico que falló al reiniciar y no hay indicación de la falla.
El gran problema es esperar a que la máquina esté encendida. Esta versión solo permanece allí durante 330 segundos y nunca intenta acceder al host antes. Algunas otras respuestas sugieren usar el puerto 22. Esto es bueno si ambos son ciertos:
- tienes acceso directo a las máquinas
- se puede acceder a su máquina inmediatamente después de que el puerto 22 esté abierto
Estos no siempre son ciertos, así que decidí perder 5 minutos de tiempo de cálculo. Espero que ansible amplíe el módulo wait_for para comprobar el estado del host y evitar perder el tiempo.
por cierto, la respuesta que sugiere usar controladores es buena. +1 para controladores de mi parte (y actualicé la respuesta para usar controladores).
Aquí está la versión original, pero no es tan buena ni tan confiable:
- 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
Ansible>=2.7 (lanzado en octubre de 2018)
Use el módulo de reinicio incorporado:
- name: Wait for server to restart
reboot:
reboot_timeout: 3600
Ansible <2.7
Reiniciar como tarea
- name: restart server
shell: 'sleep 1 && shutdown -r now "Reboot triggered by Ansible" && sleep 1'
async: 1
poll: 0
become: true
Esto ejecuta el comando de shell como una tarea asincrónica, por lo que Ansible no esperará a que finalice el comando. Normalmente async
param da el tiempo máximo para la tarea pero como poll
se establece en 0, Ansible nunca sondeará si el comando ha finalizado; hará que este comando sea "disparar y olvidar". Duerme antes y después de shutdown
son para evitar que se interrumpa la conexión SSH durante el reinicio mientras Ansible aún está conectado a su host remoto.
Esperar como tarea
Podrías simplemente usar:
- name: Wait for server to restart
local_action:
module: wait_for
host={{ inventory_hostname }}
port=22
delay=10
become: false
..pero quizás prefieras usar {{ ansible_ssh_host }}
variable como nombre de host y/o {{ ansible_ssh_port }}
como host y puerto SSH si usa entradas como:
hostname ansible_ssh_host=some.other.name.com ansible_ssh_port=2222
..en su inventario (Ansible hosts
archivo).
Esto ejecutará la tarea wait_for en la máquina que ejecuta Ansible. Esta tarea esperará a que el puerto 22 se abra en su host remoto, comenzando después de 10 segundos de retraso.
Reiniciar y esperar como controladores
Pero sugiero usar ambos como controladores, no como tareas.
Hay 2 razones principales para hacer esto:
-
reutilización de código:puede usar un controlador para muchas tareas. Ejemplo: desencadenar el reinicio del servidor después de cambiar la zona horaria y después de cambiar el kernel,
-
desencadenar solo una vez:si usa un controlador para algunas tareas, y más de 1 de ellos hará algún cambio => desencadenar el controlador, entonces lo que hace el controlador sucederá solo una vez. Ejemplo: si tiene un controlador de reinicio de httpd adjunto al cambio de configuración de httpd y la actualización del certificado SSL, en caso de que tanto la configuración como el certificado SSL cambien, httpd se reiniciará solo una vez.
Obtenga más información sobre los controladores aquí.
Reiniciando y esperando el reinicio como controladores:
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
..y utilícelo en su tarea en una secuencia, como esta, aquí junto con el reinicio del controlador del servidor:
tasks:
- name: Set hostname
hostname: name=somename
notify:
- Restart server
- Wait for server to restart
Tenga en cuenta que los controladores se ejecutan en el orden en que están definidos, no en el orden en que aparecen en notify
!
Debe cambiar la tarea wait_for para que se ejecute como local_action y especificar el host que está esperando. Por ejemplo:
- name: Wait for server to restart
local_action:
module: wait_for
host=192.168.50.4
port=22
delay=1
timeout=300