Table of Contents
- The Objective
- How to reboot and wait for it to complete with ansible
- The Ansible Playbook with the wait_for module
- The Ansible playbook with the Wait_for_connection module
- The Execution Results
The Objective
The purpose of this post is to explain with an example how ansible initiates the reboot and waits for the reboot to complete.
In some cases, we want our remote nodes to be rebooted or restarted. For example, Take Patching as an example. As part of quarterly patching, we upgrade the installed software and packages and do various other stuff along with a final reboot to make the changes effective.
When we reboot the server(box), you might get your ansible to play failed with the error “Shared connection closed.”
But this can be avoided, and you can reboot the box and wait for the server to come back up and execute the post-reboot validations or checks.
How to update, reboot, and wait for it to complete with Ansible
There are many methods to accomplish this; here are two:
For Ansible 2.7 and more – There is a dedicated reboot module
For previous versions – Either use wait_for or wait_for_connection
Since the reboot module of Ansible 2.7 is straightforward and efficient and also considering that most people is still behind ansible 2.7. In this post, we will see the wait_for and wait_for_connection modules of ansible to get our task accomplished.
Consider the following playbook I have created for Linux patching. It performs yum update
and reboot
the box and print the uptime
.
The Ansible Playbook with the wait_for module
--- - name: Patch the server and Reboot hosts: app tasks: - name: Patch the server become: yes become_user: root tags: Patch shell: "yum -y update" register: patchresult - name: Reboot the server tags: reboot become: yes become_user: root shell: "sleep 5 && reboot" async: 1 poll: 0 - name: Wait for the reboot and reconnect wait_for: port: 22 host: '{{ (ansible_ssh_host|default(ansible_host))|default(inventory_hostname) }}' search_regex: OpenSSH delay: 10 timeout: 60 connection: local - name: Check the Uptime of the servers shell: "uptime" register: Uptime - debug: var=Uptime
Explanation
In the preceding playbook, we have four tasks.
The first task is running a single command, “yum -y update” over the shell module, which is responsible for updating the packages and software in the boxes.
The Second task is to reboot the server. We execute the reboot command over the shell module. The task contains two crucial arguments, which are async and poll.
If you try to take the sleep command away from the shell module, keep the reboot command. The Playbook will get terminated with the connection closed exception.
The Sleep
a command followed by a reboot on success using && symbols are strategically placed to give ansible a little time to get it all together. The ansible connection will be dropped if you execute reboot or shutdown -now commands.
So some Sleep is always good.
That’s also the reason we cannot use the command module Over shell cause the command module does not support logical and - &&
async: By default, the tasks in the playbook block the execution till it gets completed. If you mention async in the task. It will be run asynchronously; in other words, it runs detached and in the background. Ansible master keeps track of this task by using the poll interval. It accepts the time in seconds. It should keep the connection open before times out.
poll: Time in seconds, at what interval the ansible master should poll the Job/task to know whether it is completed.
When the poll is set to 0 seconds, Ansible will fire the task and forget it. which is used specifically in here so that despite the remote servers shutdown the playbook will still be on.
The Third task is wait_for. This is our primary focus, so let me explain all the arguments for this task.
port: we are waiting for port 22 (SSH Default port) to be open
host: we are using the ansible built-in variables here, inventory_hostname or ansible_host, which will represent the current host from the host group defined in the playbook (app)
search_regex: we are looking for the word OpenSSH once the Port is open.
delay: Delay in seconds before starting the validation
timeout: timeout the execution after defined seconds.
connection: Execute the connection from the local (master)
When the connection is set to local. The Master will try to connect to the remote boxes from the master. It is more like executing nc or telnet command to make sure the port is open.
Since the reboot module of Ansible 2.7 is straightforward and efficient and also considering that most people is still behind ansible 2.7. In this post, we will see the wait_for and wait_for_connection modules of ansible to get our task accomplished.
Consider the following playbook I have created for Linux patching. It performs yum update
and reboot
the box and print the uptime
.
The Ansible playbook with the Wait_for_connection module
--- - name: Patch the server and Reboot hosts: app gather_facts: no tasks: - name: Patch the server become: yes become_user: root tags: Patch shell: "yum -y update" register: patchresult - name: Reboot the server tags: reboot become: yes become_user: root shell: "sleep 5 && reboot" async: 1 poll: 0 - name: Wait for the reboot to complete if there was a change. wait_for_connection: connect_timeout: 10 sleep: 5 delay: 5 timeout: 300 - name: Check the Uptime of the servers shell: "uptime" register: Uptime - debug: var=Uptime
Explanation
connect_timeout : Maximum number of seconds to wait for a connection to happen before closing and retrying.
delay : Number of seconds to wait before starting to poll.
sleep : Number of seconds to sleep between checks.
timeout : Maximum number of seconds to wait for.
The Execution Results
Since, Ansible 2.7. You can do the reboot effortlessly and wait for the server to return using the reboot module.