2015-04-29 8 views
17

Ich versuche, Server unter CentOS 7 auf VirtualBox neu zu starten. Ich benutze diese Aufgabe:Wie startet man CentOS 7 mit Ansible?

- name: Restart server 
    command: /sbin/reboot 
    async: 0 
    poll: 0 
    ignore_errors: true 

Server neu gestartet wird, aber ich habe diesen Fehler:

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 

Was mache ich falsch? Wie kann ich das beheben?

+0

Auf der Grundlage der Antwort zur Verfügung gestellt von Marcin Skarbek Ich bereitete und veröffentlichte zu Ansible Galaxy Rolle, was diese Methode verwendet. Die Rolle Reboot-And-Wait finden Sie [hier] (https://galaxy.ansible.com/it-praktyk/Reboot-And-Wait/). Danke für die Verwendung, Feedbacks sind willkommen. –

+0

Aufgrund der schnellen Entwicklung von Ansible funktionieren die älteren Antworten nicht mehr für mich. Bitte werfen Sie einen Blick auf meine Antwort. – Telegrapher

Antwort

22

Sie tun wahrscheinlich nichts wirklich falsch, es ist nur, dass/sbin/reboot den Server so schnell herunterfährt, dass der Server die von Ansible verwendete SSH-Verbindung herunterbricht, bevor Ansible selbst sie schließen kann. Aus diesem Grund meldet Ansible einen Fehler, weil die SSH-Verbindung aus einem unerwarteten Grund fehlschlägt.

Um dies zu umgehen, können Sie statt /sbin/reboot stattdessen /sbin/shutdown verwenden. Mit dem Befehl shutdown können Sie eine Zeit verstreichen lassen und in Verbindung mit dem Schalter -r wird ein Neustart durchgeführt, statt tatsächlich herunterzufahren. So möchten Sie vielleicht eine Aufgabe wie diese versuchen:

- name: Restart server 
    command: /sbin/shutdown -r +1 
    async: 0 
    poll: 0 
    ignore_errors: true 

Dies wird den Neustart des Servers für 1 Minute verzögern, aber es sollte so geben ansible genug Zeit, um zu schließen und die SSH-Verbindung selbst, was zu tun Vermeidung der Fehler das du gerade bekommst.

+4

Danke, das funktioniert super! Es gab nur einen kleinen Haken: Ich habe '' 'Fehler beim Parsen der Zeitangabe: + 1m''' Fehler, also musste ich' '' + 1m''' durch '' '+ 1''' ersetzen. –

+0

Hinweis: Neustart ist keine gute Idee, wenn Sie nicht wissen, was Sie tun.Es ist vielleicht in vielen Linux-Distributionen in Ordnung, aber auf anderen Unixen kann es viele System-Shutdown-Skripte umgehen und ist sehr schwierig. Dies kann zu inkonsistenten dbs usw. so schlechte Praxis führen. Besser, Shutdown oder Init zu verwenden. – krad

9

Nach der Neustartaufgabe sollten Sie eine -Task haben, die darauf wartet, dass der Remote-Host den Neustart beendet, andernfalls wird die SSH-Verbindung beendet und damit auch das 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 

Ich schrieb auch eine Blog-Post über eine ähnliche Lösung zu erreichen: https://oguya.github.io/linux/2015/02/22/ansible-reboot-servers/

1

Bei Neustart Zeit alle SSH-Verbindungen geschlossen sind. Deshalb schlägt die Ansible-Aufgabe fehl. Die Zusätze ignore_errors: true oder failed_when: false funktionieren nicht mehr ab Ansible 1.9.x, da sich die Handhabung von SSH-Verbindungen geändert hat und eine geschlossene Verbindung jetzt ein schwerwiegender Fehler ist, der während der Wiedergabe nicht aufgefangen werden kann.

Der einzige Weg, wie ich es herausgefunden habe, ist eine lokale Shell-Task auszuführen, die dann eine separate ssh-Verbindung startet, die dann fehlschlagen kann.

- name: Rebooting 
    delegate_to: localhost 
    shell: ssh -S "none" {{ inventory_hostname }} sudo /usr/sbin/reboot" 
    failed_when: false 
    changed_when: true 
+0

Vielen Dank für die Erklärung, aber Ihre Vorgehensweise erfordert wahrscheinlich passwordless sudo (oder habe ich etwas vermisst?), So kann ich es nicht in der Produktion verwenden. –

+0

Ja, das ist richtig. – udondan

4

Eine andere Lösung:

- 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 schafft "on the fly" neue Service, der systemctl reboot nach 10 Sekunden Verzögerung beginnen (--on-active=10). delay=30 in wait_for, um zusätzliche 20 Sekunden hinzuzufügen, um sicherzustellen, dass der Host tatsächlich neu gestartet wurde.

+1

Wirklich danke, ich denke, deine Lösung ist die beste, mit dem wait_for. –

5

Keine der obigen Lösungen funktionierte zuverlässig für mich.

ein /sbin/reboot Issuing stürzt das Spiel (die SSH-Verbindung geschlossen wird, bevor ansible die Aufgabe beendete, stürzt auch mit ignore_errors: true) und /usr/bin/systemd-run --on-active=2 /usr/bin/systemctl reboot wird nach 2 Sekunden nicht neu gestartet, aber nach unbestimmter Zeit zwischen 20 Sekunden und einer Minute , so ist die Verzögerung manchmal nicht ausreichend und dies ist nicht vorhersehbar.

Auch ich möchte nicht Minuten warten, während ein Cloud-Server in wenigen Sekunden neu starten kann.

So, hier ist meine Lösung:

- 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 

dass die shell: (sleep 3 && /sbin/reboot &) Linie ist, dass der Trick funktioniert.

Mit in Shell-Skript läuft ein Programm im Hintergrund und löst es: Der Befehl ist sofort erfolgreich, aber bleibt bestehen, nachdem die Shell zerstört wird.

Ansible erhält sofort seine Antwort und der Server wird 3 Sekunden später neu gestartet.

6
- 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 
+0

Das funktioniert gut für mich, vor allem die 'async: 1'. Ansible 2.3 fügt die hilfreiche 'wait_for_connection delay = 20' hinzu. –

1

Noch eine andere (kombiniert aus anderen Antworten) Version:

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

ansible entwickelt schnell und die älteren Antworten waren nicht für mich arbeiten.

fand ich zwei Fragen:

  • Die empfohlene Art und Weise von dem Neustart des SSH-Verbindung kann töten, bevor ansible die Aufgabe beendet hat.

Es ist besser laufen: nohup bash -c "sleep 2s && reboot" &

Dies startet eine Shell mit den sleep & & reboot, aber nicht für den Shell wartet aufgrund der letzten & zu beenden. Der Ruhezustand gibt der Ansible-Task einige Zeit, um sie vor dem Neustart zu beenden, und nohup garantiert, dass die Bash nicht beendet wird, wenn die Task beendet wird.

  • Das Modul wait_for wartet nicht zuverlässig auf den SSH-Dienst.
  • Es erkennt den offenen Port, wahrscheinlich von Systemd geöffnet, aber wenn die nächste Aufgabe ausgeführt wird, ist SSH immer noch nicht bereit.

    Wenn Sie Ansible 2.3+ verwenden, funktioniert wait_for_connection zuverlässig.

    Das beste ‚Neustart und warten‘ in meiner Erfahrung (ich benutze ansible 2.4) ist die folgende:

    - name: Reboot the machine 
        shell: nohup bash -c "sleep 2s && reboot" & 
    
    - name: Wait for machine to come back 
        wait_for_connection: 
        timeout: 120 
    

    Ich habe den Befehl nohup von bekam: https://github.com/keithchambers/microservices-playground/blob/master/playbooks/upgrade-packages.yml

    +0

    laut meinen vorherigen Kommentaren ist es wirklich schlecht, den Neustart zu verwenden – krad

    +0

    Klingt vernünftig in einer Nicht-Linux-Welt. Ich habe noch nie einen Linux gefunden, wo Reboot keinen ordentlichen organisierten Neustart durchführen würde. – Telegrapher

    +0

    Ein weiterer Vorteil ist, dass der Befehl zum Herunterfahren eine Zeitüberschreitung enthalten kann, ohne dass der Ruhezustand verwendet werden muss. Ich mag Ihren Vorschlag der Portabilität, aber ich werde es testen, bevor Sie es hier ändern, nur für den Fall. Die Antwort, die ich gepostet habe, ist die einfachste und funktioniert in der Zwischenzeit zuverlässig. – Telegrapher