Recently, I started using Ansible. Just when an Ansible guide book “Ansible Perfect Guide” was available on Kindle Unlimited, so I read it. Omitting installation methods and usage, I’ll just note down points that might be tricky in the future.
- Configuration files are written in YAML format.
When handling arrays and associative arrays, basically write one element per line.
Arrays have
-as prefix, and associative arrays havekey:, followed by elements. Be careful as syntax errors occur if there are no spaces. As an exception, you can define associative arrays using=, but it’s better not to use it since the syntax becomes inconsistent. - To restart a daemon after editing a configuration file, use Handler. Handler prevents the daemon from being restarted multiple times.
- To embed server-dependent values in configuration files, use the Jinja2 module.
In this case, add
.j2to the configuration file name, likenginx.conf.j2. - To make it clear that a configuration file was edited by Ansible, it’s good to add
ansible_managedas a comment at the beginning of the configuration file. This gets replaced with date, etc. - When editing configuration files, setting
backup: trueallows creating backup files. Also, settingvalidate: ...prevents daemon startup failures due to syntax errors in configuration files. - The server list is managed as an Inventory file. There are static Inventory files and dynamic Inventory files in Inventory files, and interpretation is determined by whether execution permissions are granted to the file. Static Inventory files list host names in text. On the other hand, dynamic Inventory files are written as scripts and determine host names at execution time. You can also flexibly manipulate Inventory through tasks. This is useful when you want to create a new VM by hitting the OpenStack API, then initialize the VM.
- The
ansible-playbookcommand implicitly executes the setup task prior to the tasks specified in the Playbook. The setup task stores information about the server called Facts, such as OS type and hostname. If target servers are managed by OpenStack or AWS EC2, additional information can be added to Facts. - Since Version 2, there is a concept called Block one layer outside of Task, and you can write exception handling like try, catch, and finally processing for each Block.
- Furthermore, there is a concept called Role outside of Block. Basically, it’s good to manage Roles independently for each service. Also, there’s a repository called Ansible Galaxy that collects Roles.
- To repeat common processing, use
with*commands likewith_items. However, since there are many types ofwith*commands, it might be good to search each time. - For processing you want to execute on only one server or processing you want to execute locally, exceptionally use
run_onceorlocal_action. - The number of simultaneous SSH connections is set by the forks option (default is 5).
- Develop Playbooks by combining step execution and specific task execution. If existing modules are insufficient, you can create modules yourself in Python.
Directory Structure
It’s good to have a structure where you create Roles for each service and call them from site.yml. Since the directory structure becomes complex, it might be good to download a template.
site.yml # Playbook file
hosts # Inventory file
roles/
role_name/ # Role name
tasks/
main.yml # Tasks that compose the Role
handlers/
main.yml # Handlers
vars/
main.yml # Variables that are not overwritten
defaults/
main.yml # Variables that are overwritten
meta/
main.yml # Role dependencies
files/
index.html # Files transferred by Copy
templates/
nginx.conf.j2 # Jinja2 module templates