web-dev-qa-db-fra.com

Comment redémarrer CentOS 7 avec Ansible?

J'essaie de redémarrer le serveur exécutant CentOS 7 sur VirtualBox. J'utilise cette tâche:

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

Le serveur est redémarré, mais j'obtiens cette erreur:

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

Qu'est-ce que je fais mal? Comment puis-je réparer cela?

27
Domen Blenkuš

Vous ne faites probablement rien de vraiment faux, c'est simplement que/sbin/reboot arrête le serveur si rapidement que le serveur supprime la connexion SSH utilisée par Ansible avant qu'Ansible puisse le fermer. En conséquence, Ansible signale une erreur car il voit la connexion SSH échouer pour une raison inattendue.

Ce que vous voudrez peut-être faire pour contourner ce problème est de passer de /sbin/reboot à /sbin/shutdown à la place. La commande shutdown vous laisse passer un temps et, lorsqu'elle est combinée avec le commutateur -r, elle effectuera un redémarrage plutôt que de s'éteindre réellement. Donc, vous voudrez peut-être essayer une tâche comme celle-ci:

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

Cela retardera le redémarrage du serveur pendant une minute, mais vous devrez ainsi laisser à Ansible le temps de fermer la connexion SSH elle-même, évitant ainsi l'erreur que vous obtenez actuellement.

38
Bruce P

Après la tâche de redémarrage, vous devriez avoir une tâche local_action qui attend que l'hôte distant ait fini de redémarrer, sinon la connexion ssh sera terminée, de même que le livre de lecture.


- 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

J'ai également écrit un article de blog sur la réalisation d'une solution similaire: https://oguya.github.io/linux/2015/02/22/ansible-reboot-servers/

12
James Oguya
- 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
10
Syed Saad Ahmed

Une autre solution:

- 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 crée un nouveau service "à la volée" qui démarrera systemctl reboot après 10 secondes de retard (--on-active=10) .delay=30 dans wait_for afin d'ajouter 20 secondes supplémentaires pour être sûr que l'hôte a réellement commencé à redémarrer.

7
Marcin Skarbek

Aucune des solutions ci-dessus n'a fonctionné de manière fiable pour moi.

L’émission de /sbin/reboot bloque la lecture (la connexion SSH est fermée avant qu ’ansible ait terminé la tâche, elle se bloque même avec ignore_errors: true) et /usr/bin/systemd-run --on-active=2 /usr/bin/systemctl reboot ne redémarre pas après 2 secondes, mais après un délai aléatoire entre 20 secondes et une minute est parfois insuffisant et ce n’est pas prévisible.

De plus, je ne veux pas attendre des minutes pendant lesquelles un serveur cloud peut redémarrer en quelques secondes.

Alors voici ma solution:

- 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

C'est la ligne Shell: ( sleep 3 && /sbin/reboot & ) qui fait l'affaire.

L'utilisation de ( command & ) dans le script Shell exécute un programme en arrière-plan et le détache: la commande aboutit immédiatement mais persiste après la destruction du shell.

Ansible obtient sa réponse immédiatement et le serveur redémarre 3 secondes plus tard.

6
cronvel

Ansible se développe rapidement et les réponses plus anciennes ne fonctionnaient pas pour moi.

J'ai trouvé deux problèmes: 

  • La méthode de redémarrage recommandée peut tuer la connexion SSH avant qu'Ansible ait terminé la tâche.

Il vaut mieux exécuter: Nohup bash -c "sleep 2s && shutdown -r now" &

Ceci lancera un Shell avec les sleep && shutdown, mais n'attendra pas la fin du Shell en raison du dernier &. La mise en veille laissera un peu de temps pour que la tâche Ansible se termine avant le redémarrage et la variable Nohup garantira que bash ne sera pas tué à la fin de la tâche.

  • Le module wait_for n'attend pas de manière fiable le service SSH. 

Il détecte le port ouvert, probablement ouvert par systemd, mais lors de l'exécution de la tâche suivante, SSH n'est toujours pas prêt.

Si vous utilisez Ansible 2.3+, wait_for_connection fonctionne de manière fiable.

Le meilleur «redémarrage et attente» de mon expérience (j'utilise Ansible 2.4) est le suivant:

- name: Reboot the machine
  Shell: Nohup bash -c "sleep 2s && shutdown -r now" &

- name: Wait for machine to come back
  wait_for_connection:
    timeout: 240
    delay: 20

J'ai la commande Nohup de: https://github.com/keithchambers/microservices-playground/blob/master/playbooks/upgrade-packages.yml

J'ai édité ce message pour:

  • ajoute la suggestion de portabilité de krad, en utilisant shutdown -r maintenant au lieu de redémarrer 
  • ajouter un délai. Il est nécessaire d'éviter Ansible pour exécuter l'étape suivante si le redémarrage est lent
  • augmenter le délai d'attente, 120 s était trop peu pour certains BIOS lents.
5
Telegrapher

Encore une autre version (combinée d’autres réponses):

---
- 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
3
Andrzej Rehmann

J'utilise Ansible 2.5.3 . Le code ci-dessous fonctionne avec facilité,

- name: Rebooting Host
  Shell: 'shutdown -r +1 "Reboot triggered by Ansible"'

- wait_for_connection:
    delay: 90
    timeout: 300

Vous pouvez redémarrer immédiatement, puis insérer un délai si votre machine met un certain temps à s’éteindre:

    - name: Rebooting Host
      Shell: 'shutdown -r now "Reboot triggered by Ansible"'
      async: 1
      poll: 1
      ignore_errors: true

# Wait 120 seconds to make sure the machine won't connect immediately in the next section.
    - name: Delay for the Host to go down
      local_action: Shell /bin/sleep 120

Ensuite, faites un sondage pour que le livre de jeu revienne le plus rapidement possible:

    - name: Wait for the server to finish rebooting
      wait_for_connection:
        delay: 15
        sleep: 15
        timeout: 300

Cela rendra le livre de jeu le plus tôt possible après le redémarrage.

1
Ashwin

si vous utilisez la version Ansible> = 2.7, vous pouvez utiliser le module reboot comme décrit ici

Le synopsis du module reboot lui-même:

Redémarrez une machine, attendez qu’elle s’effondre, revenez en arrière et répondez aux commandes.

De manière simple, vous pouvez définir une tâche simple comme celle-ci:

    - name: reboot server
      reboot:

Mais vous pouvez ajouter des paramètres comme test_command pour vérifier si votre serveur est prêt à exécuter d'autres tâches.

    - name: reboot server
      reboot:
        test_command: whoami

J'espère que cela t'aides!

1
kxu

Au moment du redémarrage, toutes les connexions SSH sont fermées. C'est pourquoi la tâche Ansible échoue. Les ajouts ignore_errors: true ou failed_when: false ne fonctionnent plus à partir de Ansible 1.9.x car la gestion des connexions ssh a changé et une connexion fermée est maintenant une erreur fatale qui ne peut pas être interceptée pendant la lecture.

La seule façon pour moi de le faire est d'exécuter une tâche Shell locale qui démarre ensuite une connexion ssh distincte, qui peut ensuite échouer.

- name: Rebooting
  delegate_to: localhost
  Shell: ssh -S "none" {{ inventory_hostname }} Sudo /usr/sbin/reboot"
  failed_when: false
  changed_when: true
1
udondan