Tips for using Ansible
Tags: ansible, devops, iac
Published: 2020-07-14 18:38:03

I use Ansible on a daily basis and it brings me so much joy when I finally write up a new Role or update a Playbook and everything works.

But that’s usually after a while of failures - a lot of failures. But that’s okay, if Ansible is used in the right way then you’ll always make progress.

So here’s some tips that help!

##1. Use ‘ansible-lint’

Such a simple but useful tool will help keep your Playbooks and Roles clean of errors and provide useful hints to improve them e.g. ensuring Tasks are named.
Best run when creating or editing Roles and Playbooks.

```
ansible-lint playbook.yaml
```


##2. Be Verbose

With certain Modules there is Default values set and whilst it may be fine to not mention them when writing up Tasks, there can be consequences for your future self or others when they come to update the Task. For instance [apt](https://docs.ansible.com/ansible/latest/modules/apt_module.html) install packages by default but doesn't update the cache. So you can end up with a Task like this:

```
- name: Install Nginx
  apt:
    name: nginx
```

But future self or others might hit an issue with this if the cache hasn't been updated prior, so by making it more verbose the state and Task provide more clarity of what's actually being run:

```
- name: Install Nginx
  apt:
    name: nginx
    state: present
    update_cache: yes
```


##3. Don’t be afraid to use ‘shell’ or ‘command’

There is lot of Modules out there but sometimes it's easier to write a simple one liner to do what you want done - although not recommended by Ansible. [ACME Certificate Module](https://docs.ansible.com/ansible/latest/modules/acme_certificate_module.html) is very complex to use, and it has to be run twice to work. When I can tried to implement Let's Encrypt/Certbot with a Wildcard, I found it easier to use shell instead:

```
- name: Get TLS Certificates
  shell: "certbot certonly --dns-route53 -d {{ server_name }} -n --agree-tos --email {{ email }}"
```

It's clearer what's being run and it can easily be changed in the future by others.


##4. Enable Timer

Add this to your `ansible.cfg`:
```
callback_whitelist = timer, profile_tasks
```
And this will allow you to see how long each Task and the Playbook took to run. This gives both estimates for when others run them but also allows insight into what tasks are slow and could be improved.

```
PLAY RECAP
**************************************************************
rpi2                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
rpi3                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tinker                     : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Tuesday 14 July 2020  19:20:11 +0100 (0:00:00.603)       0:01:19.673 ********** 
==============================================================
Gathering Facts - 13.72s
/Users/tomwatt/DEV/Ansible-Local/playbooks/test.yaml:2 
--------------------------------------------------------------
test-connection : Ensure the right sudo password - 6.13s
/Users/tomwatt/DEV/Ansible-Local/roles/test-connection/tasks/main.yaml:2 
--------------------------------------------------------------
debug-host-info : Print Host Information - 0.60s
/Users/tomwatt/DEV/Ansible-Local/roles/debug-host-info/tasks/main.yaml:2 
--------------------------------------------------------------
Playbook run took 0 days, 0 hours, 1 minutes, 19 seconds
```


##5. Keep Ansible up to date

Newer versions have more functionality and fixes. One caveat, though, is being aware of changes between versions e.g. modules renamed, deprecations, etc. So check the [Porting Guides](https://docs.ansible.com/ansible/latest/porting_guides/porting_guides.html) when prior to updating.
Running your Playbooks with Verbose - `-vvvvv` - on will give hints of what’s being changed/removed in later versions.


##6. Many and Small Roles

I've done it and it's easily done, creating a Playbook that does everything that needs doing. It will work but will it work in the future? What happens when it needs a minor change to work on a different server? This is where having more, smaller Roles helps.

Keeping a Role to a simple grouping of Tasks, with any needed variables, handlers or templates improves the reusability of it. It's also organises the code, for easier testing and maintenance.


##7. Use ‘ansible-galaxy role init’ to create Roles

Following on, be lazy and use it to create the basic structure for your new Roles, then remove what you don’t need.


Hope some of these are helpful for those who use Ansible or looking to use it. But let me know and share any tips you all have as well!