Table of Contents

Getting Started with Ansible

Inventories

For a definitive starting point on Ansible Inventories, see docs.ansible.com/ansible/latest/user_guide/intro_inventory.html and docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html.

In the trivial case (reserved mostly for testing and/or bootstrapping purposes), a single-host inventory can be specified directly on the command line, thusly (note the trailing comma):

ansible-playbook -i 192.168.1.16, example.yml


As with other aspects of Ansible, inventories can be specified in INI or YAML formats; the following two inventory files are equivalent:

mail.example.com

[webservers]
www.example.com
www[01:20].example.com:

[dbservers]
one.example.com
two.example.com
three.example.com



all:
  hosts:
    mail.example.com:
  children:
    webservers:
      hosts:
        www.example.com:
        www[01:20].example.com:
    dbservers:
      hosts:
        one.example.com:
        two.example.com:
        three.example.com:


Although equivalent, we will use YAML formats for the rest of these notes. Using a more complex (albeit static) inventory file, we can see several other features and syntactic structures:

  1. --- # not strictly required, but marks the file as a YAML file
  2. # base host definitions
  3. # ==============================================================================
  4. hosts_raspberry_pis_armv7l: # DEFINES AN INVENTORY GROUP
  5.   hosts: # marks the beginning of the host list
  6.   vmm-dmz.labs: # the first (explicit) host definition
  7.   ansible_host: 192.168.1.16 # explicitly specifies the host's IP address
  8.   ansible_connection: ssh # connect via ssh,
  9.   ansible_user: system # using the user 'system'
  10.   rpi3-[0:3].container.labs: # a range of hosts (zero-padding also supported)
  11.   ansible_connection: ssh
  12.   ansible_user: system
  13.   vars: # marks the beginning of the variables list
  14.   OS_ARCH: "armv7l" # defines another set of group-level variables
  15.  
  16. hosts_raspberry_pis:
  17.   children: # the contents of other groups can be included as children
  18.   hosts_raspberry_pis_armv7l:
  19. hosts_intel_nucs:
  20.   hosts:
  21.   vmm-0.container.labs:
  22.   OS_RELEASE: "Debian GNU/Linux" # defined, but can be auto-populated via the 'service_facts' module
  23.   OS_VERSION: "11 (bullseye)"
  24.   vars:
  25.   OS_ARCH: "x86_64"
  26.  
  27.  
  28. # functional- / role-based groups
  29. # ==============================================================================
  30. hosts_container_nodes:
  31.   hosts:
  32.   rpi3-[0:3].container.labs:
  33. hosts_container_lab: # A GROUP WITH BOTH HOSTS AND CHILD GROUPS
  34.   hosts:
  35.   vmm-0.container.labs:
  36.   children:
  37.   hosts_container_nodes:
  38.  
  39. # the default groups
  40. # ==============================================================================
  41. # all: # contains every host
  42. # ungrouped: # contains all hosts that don't have any other groups besides 'all'

See docs.ansible.com/ansible/latest/user_guide/intro_inventory.html for the full list of host-connection-related inventory parameters.

How Variables are Merged

From docs.ansible.com/ansible/latest/user_guide/intro_inventory.html:

By default variables are merged/flattened to the specific host before a play is run. This keeps Ansible focused on the Host and Task, so groups don't really survive outside of inventory and host matching. By default, Ansible overwrites variables including the ones defined for a group and/or host. The order/precedence is (from lowest to highest):

* all group (because it is the 'parent' of all other groups)
* parent group
* child group
* host

By default Ansible merges groups at the same parent/child level in ASCII order, and the last group loaded overwrites the previous groups. You can change this behavior by setting the group variable ansible_group_priority to change the merge order for groups of the same level (after the parent/child order is resolved). The larger the number, the later it will be merged, giving it higher priority. This variable defaults to 1 if not set.

Using Multiple Inventory Sources

Also from docs.ansible.com/ansible/latest/user_guide/intro_inventory.html:

You can target multiple inventory sources (directories, dynamic inventory scripts or files supported by inventory plugins) at the same time by giving multiple inventory parameters from the command line or by configuring ANSIBLE_INVENTORY. This can be useful when you want to target normally separate environments, like staging and production, at the same time for a specific action.

Target two sources from the command line like this:

ansible-playbook get_logs.yml -i staging -i production



Keep in mind that if there are variable conflicts in the inventories, they are resolved according to the rules described above. The merging order is controlled by the order of the inventory source parameters. If [all:vars] in staging inventory defines myvar = 1, but production inventory defines myvar = 2, the playbook will be run with myvar = 2. The result would be reversed if the playbook was run with -i production -i staging.


Aggregating Inventory Sources with a Directory
You can also create an inventory by combining multiple inventory sources and source types under a directory. This can be useful for combining static and dynamic hosts and managing them as one inventory. The following inventory combines an inventory plugin source, a dynamic inventory script, and a file with static hosts:

inventory/
  openstack.yml          # configure inventory plugin to get hosts from Openstack cloud
  dynamic-inventory.py   # add additional hosts with dynamic inventory script
  static-inventory       # add static hosts and groups
  group_vars/
    all.yml              # assign variables to all hosts



You can target this inventory directory simply like this:

ansible-playbook example.yml -i inventory



It can be useful to control the merging order of the inventory sources if there's variable conflicts or group of groups dependencies to the other inventory sources. The inventories are merged in ASCII order according to the filenames so the result can be controlled by adding prefixes to the files:

inventory/
  01-openstack.yml          # configure inventory plugin to get hosts from Openstack cloud
  02-dynamic-inventory.py   # add additional hosts with dynamic inventory script
  03-static-inventory       # add static hosts
  group_vars/
    all.yml                 # assign variables to all hosts



If 01-openstack.yml defines myvar = 1 for the group all, 02-dynamic-inventory.py defines myvar = 2, and 03-static-inventory defines myvar = 3, the playbook will be run with myvar = 3.


Playbooks

In Ansible, Playbooks are YAML files that consist of one or more Plays, each of which defines a set of one or more Tasks that are applied to a set of hosts (that are also defined at the Play-level); they have the form illustrated by the following (admittedly unnecessarily complex) YAML file:

  1. ---
  2. - name: Human-readable name / description of the first Play
  3.   hosts: all # defines which hosts this play should be run over
  4.   become: yes # sudo or not sudo
  5.  
  6.   tasks:
  7.   - name: Populate service facts # name of the first Task of the first Play
  8.   ansible.builtin.service_facts: # name of the module that will handle this task
  9.  
  10.   - name: Check hostname resolution
  11.   ansible.builtin.shell: host server-to-be-resolved
  12.   register: retval # places the results of the module's call into the register [retval]
  13.   failed_when: retval.rc != 0 # conditionally fail / abort based upon the return code
  14.  
  15.   - name: Setup some global systemd-resolved server rules
  16.   community.general.ini_file: # use a community module to edit an INI file
  17.   dest: /etc/systemd/resolved.conf
  18.   section: Resolve
  19.   option: "{{ item.option }}" # use a structure and a member variable
  20.   value: "{{ item.value }}" # ditto
  21.   no_extra_spaces: yes
  22.   state: present # define the desired state, not the action
  23.   with_items: # declare that we'll be looping over a list
  24.   - { option: "DNS", value: "10.6.1.1 10.6.1.2" }
  25.   - { option: "Domains", value: "~domain1.net ~domain2.net" }
  26.   when: "'systemd-resolved.service' in services" # only run when a condition is met
  27.  
  28.  
  29. - name: Human-readable name / description of the second, optional Play
  30.   hosts: servers # defines which hosts this play should be run over
  31.   become: yes # sudo or not sudo
  32.  
  33.   tasks:
  34.   - name: Populate service facts
  35.   ansible.builtin.service_facts:
  36. ...

Modules

To say that Ansible supports many modules 'out of the box' would be something of an understatement. Documentation for all of modules in the ansible namespace can be found over at docs.ansible.com/ansible/latest/collections/ansible, while the full list of third-party and community collections and modules can be found at docs.ansible.com/ansible/latest/collections.


Category Module Description and Important Parameters
Command ansible.builtin.command
ansible.builtin.debug
ansible.builtin.expect Executes a command and responds to prompts on all selected nodes; it will not be processed through the shell, so variables like $HOME and operations like “<”, “>”, “|”, and “&” will not work
ansible.builtin.local Allows tasks to be executed on the Ansible 'controller' instead of on a remote host
ansible.builtin.raw
ansible.builtin.script
ansible.builtin.setup ansible -i ${TARGET}, all -u system -m ansible.builtin.setup
ansible.builtin.shell
File ansible.builtin.acl
ansible.builtin.archive
ansible.builtin.copy
ansible.builtin.file
ansible.builtin.find
ansible.builtin.lineinfile
ansible.builtin.replace
ansible.builtin.stat
ansible.builtin.template
ansible.builtin.unarchive
community.general.ini_file
System ansible.builtin.user
ansible.builtin.group
ansible.builtin.hostname
ansible.builtin.iptables
ansible.builtin.lvg
ansible.builtin.lvol
ansible.builtin.mount
ansible.builtin.ping
ansible.builtin.service
ansible.builtin.service_facts
ansible.builtin.systemd
ansible.builtin.timezone
Package Management ansible.buildin.apt
ansible.builtin.apt_key
ansible.builtin.apt_repository
ansible.builtin.apt_key
ansible.builtin.package
Windows ansible.windows.win_acl
ansible.windows.command
ansible.windows.copy
ansible.windows.domain
ansible.windows.file
ansible.windows.msi
ansible.windows.ping
ansible.windows.path
ansible.windows.regedit
ansible.windows.shell
ansible.windows.service
ansible.windows.user
Category Collection Description and Important Modules
Database community.mongodb
community.mssql
community.mysql
community.postgresql
Networking cisco.ios And many more — see docs.ansible.com/ansible/latest/collections/cisco
vyos.vyos
Cloud amazon.aws
community.aws
community.digitalocean
community.docker
community.google
community.kubernetes
community.libvirt
community.vmware
community.windows
kubernetes.core
openstack.cloud
openvswitch.openvswitch.

Variables

Conditionals

Loops


Roles


Resources and References

See Also