it-swarm.com.de

Wie kann ich mit Ansible auf den Server-Neustart warten?

Ich versuche den Server neu zu starten und warte dann mit folgendem Befehl:

- name: Restart server
  Shell: reboot

- name: Wait for server to restart
  wait_for:
    port=22
    delay=1
    timeout=300

Aber ich bekomme diesen Fehler:

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

Sie sollten die wait_for-Task so ändern, dass sie als local_action ausgeführt wird, und den Host angeben, auf den Sie warten. Zum Beispiel:

- 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 (veröffentlicht im Oktober 2018)

Verwenden Sie das neue Modul Neustart .

Ansible <2,7

Starten Sie als Aufgabe neu

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

Dadurch wird der Shell-Befehl als asynchrone Task ausgeführt, sodass Ansible nicht auf das Ende des Befehls wartet. Normalerweise gibt async param die maximale Zeit für die Aufgabe an. Da jedoch poll auf 0 gesetzt ist, wird Ansible niemals abfragen, ob der Befehl abgeschlossen ist. Dadurch wird dieser Befehl zu "Feuer und Vergessen". Sleeps vor und nach shutdown sollen verhindern, dass die SSH-Verbindung während des Neustarts unterbrochen wird, während Ansible noch mit Ihrem Remote-Host verbunden ist.

Warten Sie als Aufgabe

Sie könnten einfach verwenden:

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

Sie können jedoch die {{ ansible_ssh_Host }}-Variable als Hostnamen und/oder {{ ansible_ssh_port }} als SSH-Host und -Port verwenden, wenn Sie folgende Einträge verwenden:

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

..in Ihrem Inventar (Ansible hosts-Datei).

Dadurch wird die wait_for task auf dem Rechner, auf dem Ansible läuft ausgeführt. Diese Task wartet darauf, dass Port 22 auf Ihrem Remote-Host geöffnet wird, und zwar nach einer Verzögerung von 10 Sekunden.

Starten Sie neu und warten Sie als Handler

Ich schlage jedoch vor, beide als Handler zu verwenden, nicht als Aufgaben.

Dafür gibt es zwei Hauptgründe:

  • wiederverwendung von Code - Sie können einen Handler für viele Aufgaben verwenden. Beispiel: Trigger Server Restart nach dem Ändern der Zeitzone und nach dem Ändern des Kernels

  • nur einmal auslösen - wenn Sie einen Handler für einige Aufgaben verwenden und mehr als eine von ihnen etwas ändert => den Handler auslösen, wird der Vorgang nur einmal ausgeführt. Beispiel: Wenn Sie einen httpd-Neustart-Handler mit der Änderung von httpd config und dem Aktualisieren des SSL-Zertifikats verbunden haben, wird httpd nur einmal neu gestartet, wenn sowohl die Konfiguration als auch das SSL-Zertifikat geändert werden. 

Lesen Sie mehr über Handler hier .

Neustart und Warten auf den Neustart als Handler:

  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

..und verwenden Sie es in Ihrer Task in einer Reihenfolge, wie hier, hier gepaart mit einem Neustart des Server-Handlers:

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

Beachten Sie, dass HANDLER WERDEN IN DER REIHENFOLGE AUSGEF&UUML;HRT, IN DER SIE DEFINIERT SIND, NICHT IN DER REIHENFOLGE, IN DER SIE IN notify AUFGEF&UUML;HRT SIND.!

49
Greg Dubicki

Am zuverlässigsten habe ich mit 1.9.4 bekommen (das ist aktualisiert, Originalversion ist unten):

- 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

Beachten Sie die Option async. 1.8 und 2.0 können mit 0 leben, aber 1.9 möchte 1. Das obige überprüft auch, ob der Computer tatsächlich neu gestartet wurde. Das ist gut, weil ich einmal einen Tippfehler hatte und der Neustart fehlgeschlagen ist und kein Hinweis auf den Fehler vorliegt.

Das große Problem ist das Warten auf die Maschine. Diese Version sitzt nur 330 Sekunden lang dort und versucht nicht, früher auf den Host zuzugreifen. Einige andere Antworten schlagen vor, Port 22 zu verwenden. Dies ist gut, wenn beide zutreffen:

  • sie haben direkten Zugriff auf die Maschinen
  • ihr Gerät ist sofort nach dem Öffnen von Port 22 verfügbar

Diese sind nicht immer wahr, also habe ich beschlossen, 5 Minuten Rechenzeit zu verschwenden.

die Antwort auf die Verwendung von Handlern lautet übrigens Nizza. +1 für Handler von mir (und ich habe die Antwort aktualisiert, um Handler zu verwenden).

Hier ist Originalversion aber es ist nicht so gut und nicht so zuverlässig:

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

Ansible wird ab 2.3 mit dem Modul wait_for_connection ausgeliefert, das genau zu diesem Zweck verwendet werden kann.

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

Das Herunterfahren -r +1 verhindert, dass ein Rückkehrcode von 1 zurückgegeben wird und dass Ansible die Aufgabe nicht erfüllen kann. Das Herunterfahren wird als asynchrone Task ausgeführt, daher müssen wir die wait_for_connection-Task um mindestens 60 Sekunden verzögern. 75 gibt uns einen Puffer für diese Schneeflockenkoffer.

wait_for_connection - Wartet, bis das entfernte System erreichbar ist/verwendbar

8
infrascripting

Ich wollte in Shahars Beitrag kommentieren, dass er eine hartcodierte Host-Adresse verwendet. Besser ist es, eine Variable zum Verweisen darauf zu haben, dass der aktuelle Host anpassbar {{inventory_hostname}} konfiguriert, sodass sein Code folgendermaßen lautet:

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

Bei neueren Versionen von Ansible (d. H. 1.9.1 in meinem Fall) sind die auf 0 gesetzten Abfrage- und Asynchronparameter manchmal nicht ausreichend (hängt davon ab, welche Verteilung ansässig ist?). Wie in https://github.com/ansible/ansible/issues/10616 erläutert, ist eine Problemumgehung:

- name: Reboot
  Shell: sleep 2 && shutdown -r now "Ansible updates triggered"
  async: 1
  poll: 0
  ignore_errors: true

Warten Sie dann, bis der Neustart abgeschlossen ist, wie in vielen Antworten auf dieser Seite erläutert.

5
amichaud

Durch Versuch und Irrtum + viel Lektüre hat dies letztendlich bei der 2.0-Version von Ansible funktioniert:

$ 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

Meine Lösung zum Deaktivieren von SELinux und Neustarten eines Knotens bei Bedarf:

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

Ich habe eine reboot_server-fähige Rolle erstellt, die dynamisch von anderen Rollen aufgerufen werden kann:

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

Der Rolleninhalt ist:

- 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

Dies war ursprünglich für die Verwendung mit Ubuntu OS konzipiert.

0
Gio Salvador

Ich habe nicht viel Sichtbarkeit in diesem Bereich gesehen, aber eine kürzlich vorgenommene Änderung ( https://github.com/ansible/ansible/pull/43857 ) hat das Schlüsselwort "ignore_unreachable" hinzugefügt. So können Sie etwa Folgendes tun:

- 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

Falls Sie noch kein DNS-Setup für den Remote-Server eingerichtet haben, können Sie die IP-Adresse anstelle eines variablen Hostnamens übergeben:

- 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

Dies sind die beiden Aufgaben, die ich am Ende meines ansible-swap-Playbooks hinzugefügt habe (um 4 GB Swap auf neue Digital Ocean-Droplets zu installieren.

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