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:
--- # not strictly required, but marks the file as a YAML file # base host definitions # ============================================================================== hosts_raspberry_pis_armv7l: # DEFINES AN INVENTORY GROUP hosts: # marks the beginning of the host list vmm-dmz.labs: # the first (explicit) host definition ansible_host: 192.168.1.16 # explicitly specifies the host's IP address ansible_connection: ssh # connect via ssh, ansible_user: system # using the user 'system' rpi3-[0:3].container.labs: # a range of hosts (zero-padding also supported) ansible_connection: ssh ansible_user: system vars: # marks the beginning of the variables list OS_ARCH: "armv7l" # defines another set of group-level variables hosts_raspberry_pis: children: # the contents of other groups can be included as children hosts_raspberry_pis_armv7l: hosts_intel_nucs: hosts: vmm-0.container.labs: OS_RELEASE: "Debian GNU/Linux" # defined, but can be auto-populated via the 'service_facts' module OS_VERSION: "11 (bullseye)" vars: OS_ARCH: "x86_64" # functional- / role-based groups # ============================================================================== hosts_container_nodes: hosts: rpi3-[0:3].container.labs: hosts_container_lab: # A GROUP WITH BOTH HOSTS AND CHILD GROUPS hosts: vmm-0.container.labs: children: hosts_container_nodes: # the default groups # ============================================================================== # all: # contains every host # 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 variableansible_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 configuringANSIBLE_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
If01-openstack.yml
definesmyvar = 1
for the groupall
,02-dynamic-inventory.py
definesmyvar = 2
, and03-static-inventory
definesmyvar = 3
, the playbook will be run withmyvar = 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:
--- - name: Human-readable name / description of the first Play hosts: all # defines which hosts this play should be run over become: yes # sudo or not sudo tasks: - name: Populate service facts # name of the first Task of the first Play ansible.builtin.service_facts: # name of the module that will handle this task - name: Check hostname resolution ansible.builtin.shell: host server-to-be-resolved register: retval # places the results of the module's call into the register [retval] failed_when: retval.rc != 0 # conditionally fail / abort based upon the return code - name: Setup some global systemd-resolved server rules community.general.ini_file: # use a community module to edit an INI file dest: /etc/systemd/resolved.conf section: Resolve option: "{{ item.option }}" # use a structure and a member variable value: "{{ item.value }}" # ditto no_extra_spaces: yes state: present # define the desired state, not the action with_items: # declare that we'll be looping over a list - { option: "DNS", value: "10.6.1.1 10.6.1.2" } - { option: "Domains", value: "~domain1.net ~domain2.net" } when: "'systemd-resolved.service' in services" # only run when a condition is met - name: Human-readable name / description of the second, optional Play hosts: servers # defines which hosts this play should be run over become: yes # sudo or not sudo tasks: - name: Populate service facts ansible.builtin.service_facts: ...
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