Skip to main content

5 ways to make your Ansible modules work faster

Optimize how you use Ansible modules to speed up your playbooks.

Photo by Pixabay from Pexels

Ansible is a powerful open source tool that helps you automate many of your IT infrastructure operations, from the smallest of tasks to the largest. Ansible has hundreds of modules to help you accomplish your configuration needs, both official and community-developed. When it comes to complex and lengthy workflows, though, you need to consider how to optimize the way you use these modules so you can speed up your playbooks.

Previously, I wrote about making your Ansible playbooks run faster. Here are five ways I make my Ansible modules work faster for me.

[ New to automation or looking to boost your skills? Sign up for the free online Ansible Basics course. ]

1. Use multiple tasks in a single module and avoid module loops

It's easy to fall into linear thinking. For instance, you might want to install several packages, so you might think to do this in a terminal:

# Multiple `dnf` commands
$ sudo dnf install httpd
$ sudo dnf install firewalld
$ sudo dnf install git

But you can do the same thing more efficiently:

$ sudo dnf install -y httpd firewalld git

The same strategy applies to Ansible playbooks. Instead of installing packages using multiple yum or dnf modules, you can pass multiple packages to a single yum task.

This might be your old method:

- name: Install httpd
  ansible.builtin.yum:
    name: httpd
 
- name: Install firewalld
  ansible.builtin.yum:
    name: firewalld
 
- name: Install git
  ansible.builtin.yum:
    name: git

Or maybe you did this:

- name: Install Pacakages
  ansible.builtin.yum:
    name: "{{ item }}"
    state: latest
  loop:
    - httpd
    - firewalld
    - git

But the better and more efficient method is this:

- name: Install httpd and firewalld
  ansible.builtin.yum:
    name: 
      - httpd
      - firewalld
      - git
    state: latest

2. Avoid copy loops and use the synchronize module

When you have multiple files to copy into the same directory, synchronize modules rather than using multiple copy modules or loops:

- name: Copy application data
  synchronize:
    src: app_data/
    dest: /opt/web_app/data

3. Use the latest version of Ansible and its modules

Most of the time, new versions of Ansible include performance and optimization improvements. If possible, use the latest compatible version of Ansible for your environments to ensure you're getting the most recent features. Also, update your modules and roles or Ansible collections to get the current features and bug fixes.

Make sure you've tested the latest version of the module and Ansible before pushing to production and critical environments to avoid breaking any existing functionalities.

[ Get the latest on Red Hat Ansible Automation Platform 2 in this interactive guide. ]

4. Make configuration templates

You might use multiple lineinfile and blockinfile tasks to manage and configure a single file. This approach creates a very long playbook. And when there's configuration drift, you must edit this lineinfile task with a different regex. However, you can use a Jinja2 template to create any level of complex files and use the template module (or filter) to configure managed nodes.

For instance, you can copy a complex Nginx web server configuration using the template module with a Jinja2 template.

Your Jinja2 template: nginxd.conf.j2

# nginx configuration for wp-test
server {
    root /var/www/{{ website_root_dir }};
    index index.php index.html index.htm;
    server_name {{ website_name }}.com www.{{ website_name }}.com;
    access_log /var/log/nginx/access_{{ website_name }}-com.log;
    error_log /var/log/nginx/error_{{ website_name }}-com.log;
...<output removed>...
    ssl_certificate /etc/letsencrypt/live/{{ website_name }}.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/{{ website_name }}.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = www.{{ website_name }}.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
...<output removed>...
    server_name {{ website_name }}.com www.{{ website_name }}.com;
    return 404; # managed by Certbot
}

The template module replaces the variable (the code {{ website_root_dir }}) with values provided in your playbook:

---
- name: Configure the nginx Web Server
  hosts: web_servers
  become: True 
  vars:
    website_name: myawesomeblog
    website_root_dir: /var/www/myawesomeblogdata
  tasks:
    - name: Copy nginx configuration
      template:
        src: nginxd.conf.j2
        dest: /etc/nginx/sites-enabled/{{ website_name }}.conf

5. Use appropriate modules and avoid using shell or command modules

You can use Ansible shell or command modules to run basic Linux commands. It is highly recommended that you use appropriate modules and use these shell/command modules in the worst-case scenarios. The shell (or command) modules will simply execute the command without any validations, and most of the time, you need to take care of idempotency and error checks.

For example, the first task below (with shell) simply overwrites the file's content without checking or validating, but the second task (with the copy module) changes the file only if required, and it also updates the permissions and ownership of the destination file.

    - name: Create file using shell module
      shell: 'echo "Hello" > /tmp/foo.conf'
      
    - name: Create file with permission using file module
      ansible.builtin.copy:
        content: "Hello"
        dest: /tmp/foo.conf
        owner: root
        group: root
        mode: '0644'

Bonus: Optimize your syntax

Using appropriate modules and module arguments in your playbook saves a lot of time and avoids complications. Refer to the latest module documentation, whether it's in the official Ansible docs or elsewhere, to ensure that the keys and values you remember from the last time you used the module are still valid.

Optimization is a journey

The modules you select and how you use them can affect the global execution time of your Ansible playbooks. But that means each module is an opportunity to optimize your playbook, refine the process, and maximize automation speed.

This isn't a complete list, of course. You can use many other parameters to control and optimize your Ansible playbook execution, such as serial, throttle, run_once, and more. Refer to the documentation to learn more and apply optimization techniques based on your Ansible environment.

Topics:   Ansible   Automation   Troubleshooting  
Author’s photo

Gineesh Madapparambath

Gineesh Madapparambath is a Platform &amp; DevOps Consultant at Red Hat Singapore, specializing in automation and containerization with Ansible and OpenShift.  More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.