Aggiornamento 2018
A partire dalla 2.3, Ansible ora viene fornito con wait_for_connection
modulo, che può essere utilizzato esattamente per questo scopo.
#
## 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
Lo shutdown -r +1 impedisce la restituzione di un codice di ritorno 1 e fa sì che ansible fallisca l'attività. L'arresto viene eseguito come un'attività asincrona, quindi dobbiamo ritardare il wait_for_connection
compito di almeno 60 secondi. 75 ci fornisce un buffer per quei casi di fiocchi di neve.
wait_for_connection - Attende che il sistema remoto sia raggiungibile/utilizzabile
Il più affidabile che ho ottenuto con 1.9.4 è (questo è aggiornato, la versione originale è in fondo):
- 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
Nota il async
opzione. 1.8 e 2.0 potrebbero vivere con 0
ma 1.9 lo vuole 1
. Quanto sopra controlla anche se la macchina è stata effettivamente riavviata. Questo è positivo perché una volta ho avuto un errore di battitura che non ha consentito il riavvio e nessuna indicazione dell'errore.
Il grosso problema è aspettare che la macchina sia attiva. Questa versione rimane lì per 330 secondi e non tenta mai di accedere all'host prima. Alcune altre risposte suggeriscono di utilizzare la porta 22. Questo va bene se entrambi sono veri:
- hai accesso diretto alle macchine
- la tua macchina è accessibile immediatamente dopo l'apertura della porta 22
Questi non sono sempre veri, quindi ho deciso di sprecare 5 minuti di tempo di elaborazione. Spero che Ansible estenda il modulo wait_for per controllare effettivamente lo stato dell'host per evitare perdite di tempo.
btw la risposta che suggerisce di usare i gestori è carina. +1 per i gestori da parte mia (e ho aggiornato la risposta per utilizzare i gestori).
Ecco la versione originale ma non è così buona e non così affidabile:
- 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 (rilasciato a ottobre 2018)
Utilizza il modulo di riavvio integrato:
- name: Wait for server to restart
reboot:
reboot_timeout: 3600
Ansible <2.7
Riavvia come attività
- name: restart server
shell: 'sleep 1 && shutdown -r now "Reboot triggered by Ansible" && sleep 1'
async: 1
poll: 0
become: true
Questo esegue il comando shell come attività asincrona, quindi Ansible non attenderà la fine del comando. Di solito async
param fornisce il tempo massimo per l'attività ma come poll
è impostato su 0, Ansible non eseguirà mai il polling se il comando è terminato:renderà questo comando un "spara e dimentica". Dorme prima e dopo shutdown
servono a impedire l'interruzione della connessione SSH durante il riavvio mentre Ansible è ancora connesso all'host remoto.
Aspetta come compito
Potresti semplicemente usare:
- name: Wait for server to restart
local_action:
module: wait_for
host={{ inventory_hostname }}
port=22
delay=10
become: false
..ma potresti preferire usare {{ ansible_ssh_host }}
variabile come nome host e/o {{ ansible_ssh_port }}
come host e porta SSH se utilizzi voci come:
hostname ansible_ssh_host=some.other.name.com ansible_ssh_port=2222
..nel tuo inventario (Ansible hosts
file).
Questo eseguirà l'attività wait_for sulla macchina che esegue Ansible. Questa attività attenderà che la porta 22 si apra sull'host remoto, iniziando dopo un ritardo di 10 secondi.
Riavvia e attendi come gestori
Ma suggerisco di usarli entrambi come gestori, non attività.
Ci sono 2 motivi principali per farlo:
-
riutilizzo del codice:puoi utilizzare un gestore per molte attività. Esempio: attiva il riavvio del server dopo aver cambiato il fuso orario e dopo aver cambiato il kernel,
-
trigger solo una volta:se usi un gestore per alcune attività e più di 1 di esse apporterà alcune modifiche => attiverà il gestore, allora la cosa che fa il gestore accadrà solo una volta. Esempio: se hai un gestore di riavvio httpd collegato alla modifica della configurazione httpd e all'aggiornamento del certificato SSL, nel caso in cui sia la configurazione sia le modifiche al certificato SSL httpd verrà riavviato solo una volta.
Maggiori informazioni sui gestori qui.
Riavvio e attesa del riavvio come gestori:
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
..e usalo nella tua attività in una sequenza, come questa, qui abbinato al riavvio del gestore del server:
tasks:
- name: Set hostname
hostname: name=somename
notify:
- Restart server
- Wait for server to restart
Tieni presente che i gestori vengono eseguiti nell'ordine in cui sono definiti, non nell'ordine in cui sono elencati in notify
!
Dovresti modificare l'attività wait_for in modo che venga eseguita come local_action e specificare l'host che stai aspettando. Ad esempio:
- name: Wait for server to restart
local_action:
module: wait_for
host=192.168.50.4
port=22
delay=1
timeout=300