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 have key: , 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 .j2 to the configuration file name, like nginx.conf.j2.
  • To make it clear that a configuration file was edited by Ansible, it’s good to add ansible_managed as a comment at the beginning of the configuration file. This gets replaced with date, etc.
  • When editing configuration files, setting backup: true allows creating backup files. Also, setting validate: ... 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-playbook command 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 like with_items. However, since there are many types of with* 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_once or local_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