Skip to content

Projects

Selecting Hosts with Host Patterns

Host patterns are used to specify the hosts to target by a play. At its most basic the name of a managed host or a host group in the inventory is a host pattern.

Hosts can be defined using hostname or IP address and must be explicitly defined for use.

Groups can also be used, an when used as a host pattern, it specifies that Ansible will act on the hosts that are members of the group.

There is a special group named all that matches all managed hosts in the inventory, which can also be accomplished using a wildcard '*'.

There is a special group named ungrouped, which includes all managed hosts in the inventory that are not members of any other group.

Wildcards can also be used to match any managed hosts or groups that contain a substring for example - hosts: '*.example.com'.

Multiple entries in an inventory can be referenced using logical lists using a comma-separated list of host patterns. For example - hosts: labhost1.example.com,test2.example.com,192.168.2.2

A logical AND can be used, host patterns match machines in a group only if they are also in another group. For example - hosts: lab,&datacenter1.

A logical NOT can be used to exclude hosts, for example target all hosts in a group except test2: - hosts: datacenter,!test2.example.com.

Managing Dynamic Inventories

Ansible supports dynamic inventory scripts that retrieve current information from sources such as cloud providers, VMware, RHV or AD for example.

These scripts are executable programs that collect information from some external source and output the inventory in JSON format.

If the inventory file is executable, then it is treated as a dynamic inventory program and Ansible attempts to run it to generate the inventory. If the file is not executable, then it is treated as a static inventory.

A number of existing dynamic inventory scripts from the open source community, which are not included in the ansible package or officially supported by Red Hat can be found at https://github.com/ansible/ansible/tree/devel/contrib/inventory.

Scripts are mostly written in Python, but that is not a requirement for dynamic inventory scripts.

Writing Dynamic Inventory Programs

Inventory scripts can be written in any programming language, but must return inventory information in JSON format when passed appropriate options.

You can use the ansible-inventory command to examine inventories in the JSON format. For example ansible-inventory -i inventory --list.

Custom script must include the following requirements:

  • When passed the --list option, the script must print a JSON-encoded hash/dictionary of all the hosts and groups in the inventory.
  • The script should also support the --host managed-host option. This option must print a JSON hash/dictionary consisting of variables which are associated with that host.

Managing Multiple Inventories

If the location of the inventory is a directory then all inventory files included in the directory, either static or dynamic, are combined to determine the inventory.

  • when multiple inventory files exist, they are parsed in alphabetical order.

Ansible ignores files in an inventory directory if they end with certain suffixes. This can be controlled with the inventory_ignore_extensions directive in the Ansible configuration file.

Configuring Parallelism

The maximum number of simultaneous connections that Ansible makes is controlled by the forks parameter in the Ansible configuration file. It is set to 5 by default, which can be verified with:

grep forks ansible.cfg
forks = 5

ansible-config dump |grep -i forks
DEFAULT_FORKS(default) = 5

Be careful when increasing this for load on the control node.

You can override the default setting for forks from the command line in the Ansible configuration file. Both the ansible and the ansible-playbook commands offer the -f or --forks options to specify the number of forks to use.

**Managing Rolling Updates

Use the serial keyword to run the hosts through the play in batches. Each batch of hosts will be run through the entire play before the next batch is started.

Example:

---
- name: Rolling update
  hosts: webservers
  serial: 2
  tasks:
  • The serial keyword can also be specified as a percentage.

Including and Importing Files

You can divide playbooks up into smaller files to make it easier to manage. You can combine multiple playbooks into a main playbook modularity, or insert lists of tasks from a file into a play.

  • When you include content, it is a dynamic operation. Ansible processes included content during the run of the playbook, as content is reached.

  • When you import content, it is a static operation. Ansible pre-processes imported content when the playbook is initially parsed, before the run starts.

Importing multiple playbooks will be imported and run in order using import_playbook.

Example:

- name: Prepare the web server
  import_playbook: web.yml

- name: Prepare the database server
  import_playbook: db.yml

Statically import a task file into a play inside a playbook by using import_tasks.

Example:

- name: Install web server
  hosts: webservers
  tasks:
  - import_tasks: webserver_tasks.yml

Dynamically include a task file into a play inside a playbook by using the include_tasks.

Example:

- name: Install web server
  hosts: webservers
  tasks:
  - include_tasks: webserver_tasks.yml

Defining Variables for External Plays and Tasks

To maximize the possibility of reuse, these task and play files should be as generic as possible. Variables can be used to parameterize play and task elements to expand the application of tasks and plays.

The following example could be included and used to install and manage packages or services:

---
  - name: Install the {{ package }} package
    yum:
      name: "{{ package }}"
      state: latest
  - name: Start the {{ service }} service
    service:
      name: "{{ service }}"
      enabled: true
      state: started