Making Service Restart Idempotent in Ansible

Aman Jhagrolia
3 min readMar 19, 2021

Ansible is an open-source software provisioning, configuration management, and application-deployment tool enabling infrastructure as code.

Ansible works with Modules. Modules are the units of work that Ansible ships out to remote machines. Mostly Ansible modules are idempotent in nature.

But in some use-cases, Ansible lacks idempotency. One of the situations is restarting any service using the service module. Even though the service module is idempotent in nature but if we use it to restart the service (i.e. state: restarted) then the service will be restarted every time when this module runs.

Restarting of service every time is not a good practice because service restart can take some seconds of time that can lead to some downtime of the service on the client-side. And in real production environments, we can never think of a single second of downtime.

So we have to make this idempotent, i.e. only restart the service when needed like if some changes are done in the configuration.

In ansible, we have two ways to make service restart idempotent -

  • Using Conditions (when keyword)
  • Using Handlers

Using Condition (when keyword)

In Ansible, ‘when’ is the simplest conditional statement that applies to a single task. If ‘when’ test results as true then that particular ansible task will run otherwise will be skipped.

So we can use the ‘when’ conditional statement on our service restart task. In the example below, the output of the task which is copying httpd conf file (i.e. doing some changes in configuration) is registered in the ‘conf_status’ variable and then ‘conf_status.changed’ is passed as a condition to ‘when’ keyword of service restart task. This ‘conf_status.changed’ will only become true if some changes are made in the configuration file.

Using when keyword
Output of using when keyword

So in the image above we can see that -

  • When we run the playbook first time, the Task ‘Copy apache httpd conf’ is changed. So the Task ‘Restart httpd’ is also changed which means service restarted.
  • And when we run the playbook second time, the Task ‘Copy apache httpd conf’ is not changed i.e. no changes are done in the conf file. So the Task ‘Restart httpd’ is skipped which means the service not restarted.

Using Handlers

Using Handlers is a more efficient and good practice than using the ‘when’ keyword because Handlers are meant for this kind of uses cases.

Handlers are just like regular tasks in an Ansible playbook but will only run if the Task contains a notify directive and also indicates that it changed something. For example, if a config file is changed, then the task referencing the config file templating operation may notify a service restart handler. This means services can be bounced only if they need to be restarted. Handlers can be used for things other than service restarts, but service restarts are the most common usage.

Using Handler
Output of using Handler

So in the image above we can see that -

  • When we run the playbook first time, the Task ‘Copy apache httpd conf’ is changed. On change, it will notify the ‘Restart httpd Handler’. So the handler ‘Restart httpd’ will run and service restarted.
  • And when we run the playbook second time, the Task ‘Copy apache httpd conf’ is not changed i.e. no changes are done in the conf file. So in this case the ‘Restart httpd’ handler is not notified that means service not restarted.

Thanks, Hope it’s Informative!!🙂

--

--