issue #78082 separate inventory user guide (#78555)

pull/78568/head
Don Naro 2 years ago committed by GitHub
parent 811093f022
commit ccf1a63158
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -42,6 +42,7 @@ Ansible releases a new major release approximately twice a year. The core applic
:caption: Using Ansible
user_guide/index
inventory_guide/index
playbook_guide/index
win_guide/index
tips_tricks/index

@ -49,6 +49,7 @@ This documentation covers the version of ``ansible-core`` noted in the upper lef
:caption: Using Ansible Core
user_guide/index
inventory_guide/index
playbook_guide/index
win_guide/index
tips_tricks/index

@ -0,0 +1,123 @@
.. _connections:
******************************
Connection methods and details
******************************
This section shows you how to expand and refine the connection methods Ansible uses for your inventory.
ControlPersist and paramiko
---------------------------
By default, Ansible uses native OpenSSH, because it supports ControlPersist (a performance feature), Kerberos, and options in ``~/.ssh/config`` such as Jump Host setup. If your control machine uses an older version of OpenSSH that does not support ControlPersist, Ansible will fallback to a Python implementation of OpenSSH called 'paramiko'.
.. _connection_set_user:
Setting a remote user
---------------------
By default, Ansible connects to all remote devices with the user name you are using on the control node. If that user name does not exist on a remote device, you can set a different user name for the connection. If you just need to do some tasks as a different user, look at :ref:`become`. You can set the connection user in a playbook:
.. code-block:: yaml
---
- name: update webservers
hosts: webservers
remote_user: admin
tasks:
- name: thing to do first in this playbook
. . .
as a host variable in inventory:
.. code-block:: text
other1.example.com ansible_connection=ssh ansible_user=myuser
other2.example.com ansible_connection=ssh ansible_user=myotheruser
or as a group variable in inventory:
.. code-block:: yaml
cloud:
hosts:
cloud1: my_backup.cloud.com
cloud2: my_backup2.cloud.com
vars:
ansible_user: admin
.. seealso::
:ref:`ssh_connection`
Details on the ``remote_user`` keyword and ``ansible_user`` variable.
:ref:`general_precedence_rules`
Details on Ansible precedence rules.
Setting up SSH keys
-------------------
By default, Ansible assumes you are using SSH keys to connect to remote machines. SSH keys are encouraged, but you can use password authentication if needed with the ``--ask-pass`` option. If you need to provide a password for :ref:`privilege escalation <become>` (sudo, pbrun, and so on), use ``--ask-become-pass``.
.. include:: shared_snippets/SSH_password_prompt.txt
To set up SSH agent to avoid retyping passwords, you can do:
.. code-block:: bash
$ ssh-agent bash
$ ssh-add ~/.ssh/id_rsa
Depending on your setup, you may wish to use Ansible's ``--private-key`` command line option to specify a pem file instead. You can also add the private key file:
.. code-block:: bash
$ ssh-agent bash
$ ssh-add ~/.ssh/keypair.pem
Another way to add private key files without using ssh-agent is using ``ansible_ssh_private_key_file`` in an inventory file as explained here: :ref:`intro_inventory`.
Running against localhost
-------------------------
You can run commands against the control node by using "localhost" or "127.0.0.1" for the server name:
.. code-block:: bash
$ ansible localhost -m ping -e 'ansible_python_interpreter="/usr/bin/env python"'
You can specify localhost explicitly by adding this to your inventory file:
.. code-block:: bash
localhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"
.. _host_key_checking_on:
Managing host key checking
--------------------------
Ansible enables host key checking by default. Checking host keys guards against server spoofing and man-in-the-middle attacks, but it does require some maintenance.
If a host is reinstalled and has a different key in 'known_hosts', this will result in an error message until corrected. If a new host is not in 'known_hosts' your control node may prompt for confirmation of the key, which results in an interactive experience if using Ansible, from say, cron. You might not want this.
If you understand the implications and wish to disable this behavior, you can do so by editing ``/etc/ansible/ansible.cfg`` or ``~/.ansible.cfg``:
.. code-block:: text
[defaults]
host_key_checking = False
Alternatively this can be set by the :envvar:`ANSIBLE_HOST_KEY_CHECKING` environment variable:
.. code-block:: bash
$ export ANSIBLE_HOST_KEY_CHECKING=False
Also note that host key checking in paramiko mode is reasonably slow, therefore switching to 'ssh' is also recommended when using this feature.
Other connection methods
------------------------
Ansible can use a variety of connection methods beyond SSH. You can select any connection plugin, including managing things locally and managing chroot, lxc, and jail containers.
A mode called 'ansible-pull' can also invert the system and have systems 'phone home' via scheduled git checkouts to pull configuration directives from a central repository.

@ -0,0 +1,28 @@
.. _inventory_guide_index:
############################
Building Ansible inventories
############################
.. note::
**Making Open Source More Inclusive**
Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. We ask that you open an issue or pull request if you come upon a term that we have missed. For more details, see `our CTO Chris Wright's message <https://www.redhat.com/en/blog/making-open-source-more-inclusive-eradicating-problematic-language>`_.
Welcome to the guide to building Ansible inventory.
An inventory is a list of managed nodes, or hosts, that Ansible deploys and configures.
This guide introduces you to inventories and covers the following topics:
* Creating inventories to track list of servers and devices that you want to automate.
* Using dynamic inventories to track cloud services with servers and devices that are constantly starting and stopping.
* Using patterns to automate specific sub-sets of an inventory.
* Expanding and refining the connection methods Ansible uses for your inventory.
.. toctree::
:maxdepth: 2
intro_inventory
intro_dynamic_inventory
intro_patterns
connection_details

@ -0,0 +1,260 @@
.. _intro_dynamic_inventory:
.. _dynamic_inventory:
******************************
Working with dynamic inventory
******************************
.. contents::
:local:
If your Ansible inventory fluctuates over time, with hosts spinning up and shutting down in response to business demands, the static inventory solutions described in :ref:`inventory` will not serve your needs.
You may need to track hosts from multiple sources: cloud providers, LDAP, `Cobbler <https://cobbler.github.io>`_, and/or enterprise CMDB systems.
Ansible integrates all of these options through a dynamic external inventory system.
Ansible supports two ways to connect with external inventory: :ref:`inventory_plugins` and `inventory scripts`.
Inventory plugins take advantage of the most recent updates to the Ansible core code.
We recommend plugins over scripts for dynamic inventory.
You can :ref:`write your own plugin <developing_inventory>` to connect to additional dynamic inventory sources.
You can still use inventory scripts if you choose.
When we implemented inventory plugins, we ensured backwards compatibility through the script inventory plugin.
The examples below illustrate how to use inventory scripts.
If you prefer a GUI for handling dynamic inventory, the inventory database on AWX or :ref:`ansible_platform` syncs with all your dynamic inventory sources, provides web and REST access to the results, and offers a graphical inventory editor.
With a database record of all of your hosts, you can correlate past event history and see which hosts have had failures on their last playbook runs.
.. _cobbler_example:
Inventory script example: Cobbler
=================================
Ansible integrates seamlessly with `Cobbler <https://cobbler.github.io>`_, a Linux installation server originally written by Michael DeHaan and now led by James Cammarata, who works for Ansible.
While primarily used to kickoff OS installations and manage DHCP and DNS, Cobbler has a generic
layer that can represent data for multiple configuration management systems (even at the same time) and serve as a 'lightweight CMDB'.
To tie your Ansible inventory to Cobbler, copy `this script <https://raw.githubusercontent.com/ansible-community/contrib-scripts/main/inventory/cobbler.py>`_ to ``/etc/ansible`` and ``chmod +x`` the file. Run ``cobblerd`` any time you use Ansible and use the ``-i`` command line option (for example, ``-i /etc/ansible/cobbler.py``) to communicate with Cobbler using Cobbler's XMLRPC API.
Add a ``cobbler.ini`` file in ``/etc/ansible`` so Ansible knows where the Cobbler server is and some cache improvements can be used. For example:
.. code-block:: text
[cobbler]
# Set Cobbler's hostname or IP address
host = http://127.0.0.1/cobbler_api
# API calls to Cobbler can be slow. For this reason, we cache the results of an API
# call. Set this to the path you want cache files to be written to. Two files
# will be written to this directory:
# - ansible-cobbler.cache
# - ansible-cobbler.index
cache_path = /tmp
# The number of seconds a cache file is considered valid. After this many
# seconds, a new API call will be made, and the cache file will be updated.
cache_max_age = 900
First test the script by running ``/etc/ansible/cobbler.py`` directly. You should see some JSON data output, but it may not have anything in it just yet.
Let's explore what this does. In Cobbler, assume a scenario somewhat like the following:
.. code-block:: bash
cobbler profile add --name=webserver --distro=CentOS6-x86_64
cobbler profile edit --name=webserver --mgmt-classes="webserver" --ksmeta="a=2 b=3"
cobbler system edit --name=foo --dns-name="foo.example.com" --mgmt-classes="atlanta" --ksmeta="c=4"
cobbler system edit --name=bar --dns-name="bar.example.com" --mgmt-classes="atlanta" --ksmeta="c=5"
In the example above, the system 'foo.example.com' is addressable by ansible directly, but is also addressable when using the group names 'webserver' or 'atlanta'. Since Ansible uses SSH, it contacts system foo over 'foo.example.com', only, never just 'foo'. Similarly, if you tried "ansible foo", it would not find the system... but "ansible 'foo*'" would do, because the system DNS name starts with 'foo'.
The script provides more than host and group info. In addition, as a bonus, when the 'setup' module is run (which happens automatically when using playbooks), the variables 'a', 'b', and 'c' will all be auto-populated in the templates:
.. code-block:: text
# file: /srv/motd.j2
Welcome, I am templated with a value of a={{ a }}, b={{ b }}, and c={{ c }}
Which could be executed just like this:
.. code-block:: bash
ansible webserver -m setup
ansible webserver -m template -a "src=/tmp/motd.j2 dest=/etc/motd"
.. note::
The name 'webserver' came from Cobbler, as did the variables for
the config file. You can still pass in your own variables like
normal in Ansible, but variables from the external inventory script
will override any that have the same name.
So, with the template above (``motd.j2``), this results in the following data being written to ``/etc/motd`` for system 'foo':
.. code-block:: text
Welcome, I am templated with a value of a=2, b=3, and c=4
And on system 'bar' (bar.example.com):
.. code-block:: text
Welcome, I am templated with a value of a=2, b=3, and c=5
And technically, though there is no major good reason to do it, this also works:
.. code-block:: bash
ansible webserver -m ansible.builtin.shell -a "echo {{ a }}"
So, in other words, you can use those variables in arguments/actions as well.
.. _openstack_example:
Inventory script example: OpenStack
===================================
If you use an OpenStack-based cloud, instead of manually maintaining your own inventory file, you can use the ``openstack_inventory.py`` dynamic inventory to pull information about your compute instances directly from OpenStack.
You can download the latest version of the OpenStack inventory script `here <https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack_inventory.py>`_.
You can use the inventory script explicitly (by passing the `-i openstack_inventory.py` argument to Ansible) or implicitly (by placing the script at `/etc/ansible/hosts`).
Explicit use of OpenStack inventory script
------------------------------------------
Download the latest version of the OpenStack dynamic inventory script and make it executable.
.. code-block:: bash
wget https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack_inventory.py
chmod +x openstack_inventory.py
.. note::
Do not name it `openstack.py`. This name will conflict with imports from openstacksdk.
Source an OpenStack RC file:
.. code-block:: bash
source openstack.rc
.. note::
An OpenStack RC file contains the environment variables required by the client tools to establish a connection with the cloud provider, such as the authentication URL, user name, password and region name. For more information on how to download, create or source an OpenStack RC file, please refer to `Set environment variables using the OpenStack RC file <https://docs.openstack.org/user-guide/common/cli_set_environment_variables_using_openstack_rc.html>`_.
You can confirm the file has been successfully sourced by running a simple command, such as `nova list` and ensuring it returns no errors.
.. note::
The OpenStack command line clients are required to run the `nova list` command. For more information on how to install them, please refer to `Install the OpenStack command-line clients <https://docs.openstack.org/user-guide/common/cli_install_openstack_command_line_clients.html>`_.
You can test the OpenStack dynamic inventory script manually to confirm it is working as expected:
.. code-block:: bash
./openstack_inventory.py --list
After a few moments you should see some JSON output with information about your compute instances.
Once you confirm the dynamic inventory script is working as expected, you can tell Ansible to use the `openstack_inventory.py` script as an inventory file, as illustrated below:
.. code-block:: bash
ansible -i openstack_inventory.py all -m ansible.builtin.ping
Implicit use of OpenStack inventory script
------------------------------------------
Download the latest version of the OpenStack dynamic inventory script, make it executable and copy it to `/etc/ansible/hosts`:
.. code-block:: bash
wget https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack_inventory.py
chmod +x openstack_inventory.py
sudo cp openstack_inventory.py /etc/ansible/hosts
Download the sample configuration file, modify it to suit your needs and copy it to `/etc/ansible/openstack.yml`:
.. code-block:: bash
wget https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack.yml
vi openstack.yml
sudo cp openstack.yml /etc/ansible/
You can test the OpenStack dynamic inventory script manually to confirm it is working as expected:
.. code-block:: bash
/etc/ansible/hosts --list
After a few moments you should see some JSON output with information about your compute instances.
Refreshing the cache
--------------------
Note that the OpenStack dynamic inventory script will cache results to avoid repeated API calls. To explicitly clear the cache, you can run the openstack_inventory.py (or hosts) script with the ``--refresh`` parameter:
.. code-block:: bash
./openstack_inventory.py --refresh --list
.. _other_inventory_scripts:
Other inventory scripts
=======================
In Ansible 2.10 and later, inventory scripts moved to their associated collections. Many are now in the `community.general scripts/inventory directory <https://github.com/ansible-collections/community.general/tree/main/scripts/inventory>`_. We recommend you use :ref:`inventory_plugins` instead.
.. _using_multiple_sources:
Using inventory directories and multiple inventory sources
==========================================================
If the location given to ``-i`` in Ansible is a directory (or as so configured in ``ansible.cfg``), Ansible can use multiple inventory sources
at the same time. When doing so, it is possible to mix both dynamic and statically managed inventory sources in the same ansible run. Instant
hybrid cloud!
In an inventory directory, executable files are treated as dynamic inventory sources and most other files as static sources. Files which end with any of the following are ignored:
.. code-block:: text
~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo
You can replace this list with your own selection by configuring an ``inventory_ignore_extensions`` list in ``ansible.cfg``, or setting the :envvar:`ANSIBLE_INVENTORY_IGNORE` environment variable. The value in either case must be a comma-separated list of patterns, as shown above.
Any ``group_vars`` and ``host_vars`` subdirectories in an inventory directory are interpreted as expected, making inventory directories a powerful way to organize different sets of configurations. See :ref:`using_multiple_inventory_sources` for more information.
.. _static_groups_of_dynamic:
Static groups of dynamic groups
===============================
When defining groups of groups in the static inventory file, the child groups
must also be defined in the static inventory file, otherwise ansible returns an
error. If you want to define a static group of dynamic child groups, define
the dynamic groups as empty in the static inventory file. For example:
.. code-block:: text
[tag_Name_staging_foo]
[tag_Name_staging_bar]
[staging:children]
tag_Name_staging_foo
tag_Name_staging_bar
.. seealso::
:ref:`intro_inventory`
All about static inventory files
`Mailing List <https://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
:ref:`communication_irc`
How to join Ansible chat channels

@ -0,0 +1,800 @@
.. _intro_inventory:
.. _inventory:
***************************
How to build your inventory
***************************
Ansible works against multiple managed nodes or "hosts" in your infrastructure at the same time, using a list or group of lists known as inventory.
Once your inventory is defined, you use :ref:`patterns <intro_patterns>` to select the hosts or groups you want Ansible to run against.
The default location for inventory is a file called ``/etc/ansible/hosts``.
You can specify a different inventory file at the command line using the ``-i <path>`` option.
You can also use multiple inventory files at the same time as described in :ref:`using_multiple_inventory_sources`, and/or pull inventory from dynamic or cloud sources or different formats (YAML, ini, and so on), as described in :ref:`intro_dynamic_inventory`.
Introduced in version 2.4, Ansible has :ref:`inventory_plugins` to make this flexible and customizable.
.. contents::
:local:
.. _inventoryformat:
Inventory basics: formats, hosts, and groups
============================================
The inventory file can be in one of many formats, depending on the inventory plugins you have.
The most common formats are INI and YAML. A basic INI ``/etc/ansible/hosts`` might look like this:
.. code-block:: text
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
The headings in brackets are group names, which are used in classifying hosts
and deciding what hosts you are controlling at what times and for what purpose.
Group names should follow the same guidelines as :ref:`valid_variable_names`.
Here's that same basic inventory file in YAML format:
.. code-block:: yaml
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
.. _default_groups:
Default groups
--------------
There are two default groups: ``all`` and ``ungrouped``. The ``all`` group contains every host.
The ``ungrouped`` group contains all hosts that don't have another group aside from ``all``.
Every host will always belong to at least 2 groups (``all`` and ``ungrouped`` or ``all`` and some other group). Though ``all`` and ``ungrouped`` are always present, they can be implicit and not appear in group listings like ``group_names``.
.. _host_multiple_groups:
Hosts in multiple groups
------------------------
You can (and probably will) put each host in more than one group. For example a production webserver in a datacenter in Atlanta might be included in groups called [prod] and [atlanta] and [webservers]. You can create groups that track:
* What - An application, stack or microservice (for example, database servers, web servers, and so on).
* Where - A datacenter or region, to talk to local DNS, storage, and so on (for example, east, west).
* When - The development stage, to avoid testing on production resources (for example, prod, test).
Extending the previous YAML inventory to include what, when, and where would look like:
.. code-block:: yaml
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
hosts:
foo.example.com:
one.example.com:
two.example.com:
test:
hosts:
bar.example.com:
three.example.com:
You can see that ``one.example.com`` exists in the ``dbservers``, ``east``, and ``prod`` groups.
You can also use nested groups to simplify ``prod`` and ``test`` in this inventory, for the same result:
.. code-block:: yaml
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
children:
east:
test:
children:
west:
You can find more examples on how to organize your inventories and group your hosts in :ref:`inventory_setup_examples`.
Adding ranges of hosts
----------------------
If you have a lot of hosts with a similar pattern, you can add them as a range rather than listing each hostname separately:
In INI:
.. code-block:: text
[webservers]
www[01:50].example.com
In YAML:
.. code-block:: yaml
...
webservers:
hosts:
www[01:50].example.com:
You can specify a stride (increments between sequence numbers) when defining a numeric range of hosts:
In INI:
.. code-block:: text
[webservers]
www[01:50:2].example.com
In YAML:
.. code-block:: yaml
...
webservers:
hosts:
www[01:50:2].example.com:
The example above would make the subdomains www01, www03, www05, ..., www49 match, but not www00, www02, www50 and so on, because the stride (increment) is 2 units each step.
For numeric patterns, leading zeros can be included or removed, as desired. Ranges are inclusive. You can also define alphabetic ranges:
.. code-block:: text
[databases]
db-[a:f].example.com
.. _variables_in_inventory:
Adding variables to inventory
=============================
You can store variable values that relate to a specific host or group in inventory. To start with, you may add variables directly to the hosts and groups in your main inventory file. As you add more and more managed nodes to your Ansible inventory, however, you will likely want to store variables in separate host and group variable files. See :ref:`define_variables_in_inventory` for details.
.. _host_variables:
Assigning a variable to one machine: host variables
===================================================
You can easily assign a variable to a single host, then use it later in playbooks. In INI:
.. code-block:: text
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
In YAML:
.. code-block:: yaml
atlanta:
hosts:
host1:
http_port: 80
maxRequestsPerChild: 808
host2:
http_port: 303
maxRequestsPerChild: 909
Unique values like non-standard SSH ports work well as host variables. You can add them to your Ansible inventory by adding the port number after the hostname with a colon:
.. code-block:: text
badwolf.example.com:5309
Connection variables also work well as host variables:
.. code-block:: text
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=myuser
other2.example.com ansible_connection=ssh ansible_user=myotheruser
.. note:: If you list non-standard SSH ports in your SSH config file, the ``openssh`` connection will find and use them, but the ``paramiko`` connection will not.
.. _inventory_aliases:
Inventory aliases
-----------------
You can also define aliases in your inventory:
In INI:
.. code-block:: text
jumper ansible_port=5555 ansible_host=192.0.2.50
In YAML:
.. code-block:: yaml
...
hosts:
jumper:
ansible_port: 5555
ansible_host: 192.0.2.50
In the above example, running Ansible against the host alias "jumper" will connect to 192.0.2.50 on port 5555. See :ref:`behavioral inventory parameters <behavioral_parameters>` to further customize the connection to hosts.
.. note::
Values passed in the INI format using the ``key=value`` syntax are interpreted differently depending on where they are declared:
* When declared inline with the host, INI values are interpreted as Python literal structures (strings, numbers, tuples, lists, dicts, booleans, None). Host lines accept multiple ``key=value`` parameters per line. Therefore they need a way to indicate that a space is part of a value rather than a separator. Values that contain whitespace can be quoted (single or double). See the `Python shlex parsing rules`_ for details.
* When declared in a ``:vars`` section, INI values are interpreted as strings. For example ``var=FALSE`` would create a string equal to 'FALSE'. Unlike host lines, ``:vars`` sections accept only a single entry per line, so everything after the ``=`` must be the value for the entry.
* If a variable value set in an INI inventory must be a certain type (for example, a string or a boolean value), always specify the type with a filter in your task. Do not rely on types set in INI inventories when consuming variables.
* Consider using YAML format for inventory sources to avoid confusion on the actual type of a variable. The YAML inventory plugin processes variable values consistently and correctly.
Generally speaking, this is not the best way to define variables that describe your system policy. Setting variables in the main inventory file is only a shorthand. See :ref:`splitting_out_vars` for guidelines on storing variable values in individual files in the 'host_vars' directory.
.. _Python shlex parsing rules: https://docs.python.org/3/library/shlex.html#parsing-rules
.. _group_variables:
Assigning a variable to many machines: group variables
======================================================
If all hosts in a group share a variable value, you can apply that variable to an entire group at once. In INI:
.. code-block:: text
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
In YAML:
.. code-block:: yaml
atlanta:
hosts:
host1:
host2:
vars:
ntp_server: ntp.atlanta.example.com
proxy: proxy.atlanta.example.com
Group variables are a convenient way to apply variables to multiple hosts at once. Before executing, however, Ansible always flattens variables, including inventory variables, to the host level. If a host is a member of multiple groups, Ansible reads variable values from all of those groups. If you assign different values to the same variable in different groups, Ansible chooses which value to use based on internal :ref:`rules for merging <how_we_merge>`.
.. _subgroups:
Inheriting variable values: group variables for groups of groups
----------------------------------------------------------------
You can make groups of groups using the ``:children`` suffix in INI or the ``children:`` entry in YAML.
You can apply variables to these groups of groups using ``:vars`` or ``vars:``:
In INI:
.. code-block:: text
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[usa:children]
southeast
northeast
southwest
northwest
In YAML:
.. code-block:: yaml
all:
children:
usa:
children:
southeast:
children:
atlanta:
hosts:
host1:
host2:
raleigh:
hosts:
host2:
host3:
vars:
some_server: foo.southeast.example.com
halon_system_timeout: 30
self_destruct_countdown: 60
escape_pods: 2
northeast:
northwest:
southwest:
If you need to store lists or hash data, or prefer to keep host and group specific variables separate from the inventory file, see :ref:`splitting_out_vars`.
Child groups have a couple of properties to note:
- Any host that is member of a child group is automatically a member of the parent group.
- A child group's variables will have higher precedence (override) a parent group's variables.
- Groups can have multiple parents and children, but not circular relationships.
- Hosts can also be in multiple groups, but there will only be **one** instance of a host, merging the data from the multiple groups.
.. _splitting_out_vars:
Organizing host and group variables
===================================
Although you can store variables in the main inventory file, storing separate host and group variables files may help you organize your variable values more easily. Host and group variable files must use YAML syntax. Valid file extensions include '.yml', '.yaml', '.json', or no file extension.
See :ref:`yaml_syntax` if you are new to YAML.
Ansible loads host and group variable files by searching paths relative to the inventory file or the playbook file. If your inventory file at ``/etc/ansible/hosts`` contains a host named 'foosball' that belongs to two groups, 'raleigh' and 'webservers', that host will use variables in YAML files at the following locations:
.. code-block:: bash
/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
For example, if you group hosts in your inventory by datacenter, and each datacenter uses its own NTP server and database server, you can create a file called ``/etc/ansible/group_vars/raleigh`` to store the variables for the ``raleigh`` group:
.. code-block:: yaml
---
ntp_server: acme.example.org
database_server: storage.example.org
You can also create *directories* named after your groups or hosts. Ansible will read all the files in these directories in lexicographical order. An example with the 'raleigh' group:
.. code-block:: bash
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
All hosts in the 'raleigh' group will have the variables defined in these files
available to them. This can be very useful to keep your variables organized when a single
file gets too big, or when you want to use :ref:`Ansible Vault<playbooks_vault>` on some group variables.
For ``ansible-playbook`` you can also add ``group_vars/`` and ``host_vars/`` directories to your playbook directory. Other Ansible commands (for example, ``ansible``, ``ansible-console``, and so on) will only look for ``group_vars/`` and ``host_vars/`` in the inventory directory. If you want other commands to load group and host variables from a playbook directory, you must provide the ``--playbook-dir`` option on the command line.
If you load inventory files from both the playbook directory and the inventory directory, variables in the playbook directory will override variables set in the inventory directory.
Keeping your inventory file and variables in a git repo (or other version control)
is an excellent way to track changes to your inventory and host variables.
.. _how_we_merge:
How variables are merged
========================
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 (see :ref:`DEFAULT_HASH_BEHAVIOUR<DEFAULT_HASH_BEHAVIOUR>`). 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. For example, an a_group will be merged with b_group and b_group vars that match will overwrite the ones in a_group.
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. For example:
.. code-block:: yaml
a_group:
vars:
testvar: a
ansible_group_priority: 10
b_group:
vars:
testvar: b
In this example, if both groups have the same priority, the result would normally have been ``testvar == b``, but since we are giving the ``a_group`` a higher priority the result will be ``testvar == a``.
.. note:: ``ansible_group_priority`` can only be set in the inventory source and not in group_vars/, as the variable is used in the loading of group_vars.
.. _using_multiple_inventory_sources:
Using multiple inventory sources
================================
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 :envvar:`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:
.. code-block:: bash
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 in :ref:`how_we_merge` and :ref:`ansible_variable_precedence`.
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:
.. code-block:: text
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:
.. code-block:: bash
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:
.. code-block:: text
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``.
For more details on inventory plugins and dynamic inventory scripts see :ref:`inventory_plugins` and :ref:`intro_dynamic_inventory`.
.. _behavioral_parameters:
Connecting to hosts: behavioral inventory parameters
====================================================
As described above, setting the following variables control how Ansible interacts with remote hosts.
Host connection:
.. include:: shared_snippets/SSH_password_prompt.txt
ansible_connection
Connection type to the host. This can be the name of any of ansible's connection plugins. SSH protocol types are ``smart``, ``ssh`` or ``paramiko``. The default is smart. Non-SSH based types are described in the next section.
General for all connections:
ansible_host
The name of the host to connect to, if different from the alias you wish to give to it.
ansible_port
The connection port number, if not the default (22 for ssh)
ansible_user
The user name to use when connecting to the host
ansible_password
The password to use to authenticate to the host (never store this variable in plain text; always use a vault. See :ref:`tip_for_variables_and_vaults`)
Specific to the SSH connection:
ansible_ssh_private_key_file
Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent.
ansible_ssh_common_args
This setting is always appended to the default command line for :command:`sftp`, :command:`scp`,
and :command:`ssh`. Useful to configure a ``ProxyCommand`` for a certain host (or
group).
ansible_sftp_extra_args
This setting is always appended to the default :command:`sftp` command line.
ansible_scp_extra_args
This setting is always appended to the default :command:`scp` command line.
ansible_ssh_extra_args
This setting is always appended to the default :command:`ssh` command line.
ansible_ssh_pipelining
Determines whether or not to use SSH pipelining. This can override the ``pipelining`` setting in :file:`ansible.cfg`.
ansible_ssh_executable (added in version 2.2)
This setting overrides the default behavior to use the system :command:`ssh`. This can override the ``ssh_executable`` setting in :file:`ansible.cfg`.
Privilege escalation (see :ref:`Ansible Privilege Escalation<become>` for further details):
ansible_become
Equivalent to ``ansible_sudo`` or ``ansible_su``, allows to force privilege escalation
ansible_become_method
Allows to set privilege escalation method
ansible_become_user
Equivalent to ``ansible_sudo_user`` or ``ansible_su_user``, allows to set the user you become through privilege escalation
ansible_become_password
Equivalent to ``ansible_sudo_password`` or ``ansible_su_password``, allows you to set the privilege escalation password (never store this variable in plain text; always use a vault. See :ref:`tip_for_variables_and_vaults`)
ansible_become_exe
Equivalent to ``ansible_sudo_exe`` or ``ansible_su_exe``, allows you to set the executable for the escalation method selected
ansible_become_flags
Equivalent to ``ansible_sudo_flags`` or ``ansible_su_flags``, allows you to set the flags passed to the selected escalation method. This can be also set globally in :file:`ansible.cfg` in the ``sudo_flags`` option
Remote host environment parameters:
.. _ansible_shell_type:
ansible_shell_type
The shell type of the target system. You should not use this setting unless you have set the
:ref:`ansible_shell_executable<ansible_shell_executable>` to a non-Bourne (sh) compatible shell. By default commands are
formatted using ``sh``-style syntax. Setting this to ``csh`` or ``fish`` will cause commands
executed on target systems to follow those shell's syntax instead.
.. _ansible_python_interpreter:
ansible_python_interpreter
The target host python path. This is useful for systems with more
than one Python or not located at :command:`/usr/bin/python` such as \*BSD, or where :command:`/usr/bin/python`
is not a 2.X series Python. We do not use the :command:`/usr/bin/env` mechanism as that requires the remote user's
path to be set right and also assumes the :program:`python` executable is named python, where the executable might
be named something like :program:`python2.6`.
ansible_*_interpreter
Works for anything such as ruby or perl and works just like :ref:`ansible_python_interpreter<ansible_python_interpreter>`.
This replaces shebang of modules which will run on that host.
.. versionadded:: 2.1
.. _ansible_shell_executable:
ansible_shell_executable
This sets the shell the ansible controller will use on the target machine,
overrides ``executable`` in :file:`ansible.cfg` which defaults to
:command:`/bin/sh`. You should really only change it if is not possible
to use :command:`/bin/sh` (in other words, if :command:`/bin/sh` is not installed on the target
machine or cannot be run from sudo.).
Examples from an Ansible-INI host file:
.. code-block:: text
some_host ansible_port=2222 ansible_user=manager
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
Non-SSH connection types
------------------------
As stated in the previous section, Ansible executes playbooks over SSH but it is not limited to this connection type.
With the host specific parameter ``ansible_connection=<connector>``, the connection type can be changed.
The following non-SSH based connectors are available:
**local**
This connector can be used to deploy the playbook to the control machine itself.
**docker**
This connector deploys the playbook directly into Docker containers using the local Docker client. The following parameters are processed by this connector:
ansible_host
The name of the Docker container to connect to.
ansible_user
The user name to operate within the container. The user must exist inside the container.
ansible_become
If set to ``true`` the ``become_user`` will be used to operate within the container.
ansible_docker_extra_args
Could be a string with any additional arguments understood by Docker, which are not command specific. This parameter is mainly used to configure a remote Docker daemon to use.
Here is an example of how to instantly deploy to created containers:
.. code-block:: yaml
- name: Create a jenkins container
community.general.docker_container:
docker_host: myserver.net:4243
name: my_jenkins
image: jenkins
- name: Add the container to inventory
ansible.builtin.add_host:
name: my_jenkins
ansible_connection: docker
ansible_docker_extra_args: "--tlsverify --tlscacert=/path/to/ca.pem --tlscert=/path/to/client-cert.pem --tlskey=/path/to/client-key.pem -H=tcp://myserver.net:4243"
ansible_user: jenkins
changed_when: false
- name: Create a directory for ssh keys
delegate_to: my_jenkins
ansible.builtin.file:
path: "/var/jenkins_home/.ssh/jupiter"
state: directory
For a full list with available plugins and examples, see :ref:`connection_plugin_list`.
.. note:: If you're reading the docs from the beginning, this may be the first example you've seen of an Ansible playbook. This is not an inventory file.
Playbooks will be covered in great detail later in the docs.
.. _inventory_setup_examples:
Inventory setup examples
========================
See also :ref:`sample_setup`, which shows inventory along with playbooks and other Ansible artifacts.
.. _inventory_setup-per_environment:
Example: One inventory per environment
--------------------------------------
If you need to manage multiple environments it's sometimes prudent to
have only hosts of a single environment defined per inventory. This
way, it is harder to, for instance, accidentally change the state of
nodes inside the "test" environment when you actually wanted to update
some "staging" servers.
For the example mentioned above you could have an
:file:`inventory_test` file:
.. code-block:: ini
[dbservers]
db01.test.example.com
db02.test.example.com
[appservers]
app01.test.example.com
app02.test.example.com
app03.test.example.com
That file only includes hosts that are part of the "test"
environment. Define the "staging" machines in another file
called :file:`inventory_staging`:
.. code-block:: ini
[dbservers]
db01.staging.example.com
db02.staging.example.com
[appservers]
app01.staging.example.com
app02.staging.example.com
app03.staging.example.com
To apply a playbook called :file:`site.yml`
to all the app servers in the test environment, use the
following command:
.. code-block:: bash
ansible-playbook -i inventory_test -l appservers site.yml
.. _inventory_setup-per_function:
Example: Group by function
--------------------------
In the previous section you already saw an example for using groups in
order to cluster hosts that have the same function. This allows you,
for instance, to define firewall rules inside a playbook or role
affecting only database servers:
.. code-block:: yaml
- hosts: dbservers
tasks:
- name: Allow access from 10.0.0.1
ansible.builtin.iptables:
chain: INPUT
jump: ACCEPT
source: 10.0.0.1
.. _inventory_setup-per_location:
Example: Group by location
--------------------------
Other tasks might be focused on where a certain host is located. Let's
say that ``db01.test.example.com`` and ``app01.test.example.com`` are
located in DC1 while ``db02.test.example.com`` is in DC2:
.. code-block:: ini
[dc1]
db01.test.example.com
app01.test.example.com
[dc2]
db02.test.example.com
In practice, you might even end up mixing all these setups as you
might need to, on one day, update all nodes in a specific data center
while, on another day, update all the application servers no matter
their location.
.. seealso::
:ref:`inventory_plugins`
Pulling inventory from dynamic or static sources
:ref:`intro_dynamic_inventory`
Pulling inventory from dynamic sources, such as cloud providers
:ref:`intro_adhoc`
Examples of basic commands
:ref:`working_with_playbooks`
Learning Ansible's configuration, deployment, and orchestration language.
`Mailing List <https://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
:ref:`communication_irc`
How to join Ansible chat channels

@ -0,0 +1,250 @@
.. _intro_patterns:
Patterns: targeting hosts and groups
====================================
When you execute Ansible through an ad hoc command or by running a playbook, you must choose which managed nodes or groups you want to execute against.
Patterns let you run commands and playbooks against specific hosts and/or groups in your inventory.
An Ansible pattern can refer to a single host, an IP address, an inventory group, a set of groups, or all hosts in your inventory.
Patterns are highly flexible - you can exclude or require subsets of hosts, use wildcards or regular expressions, and more.
Ansible executes on all inventory hosts included in the pattern.
.. contents::
:local:
Using patterns
--------------
You use a pattern almost any time you execute an ad hoc command or a playbook. The pattern is the only element of an :ref:`ad hoc command<intro_adhoc>` that has no flag. It is usually the second element:
.. code-block:: bash
ansible <pattern> -m <module_name> -a "<module options>"
For example:
.. code-block:: bash
ansible webservers -m service -a "name=httpd state=restarted"
In a playbook the pattern is the content of the ``hosts:`` line for each play:
.. code-block:: yaml
- name: <play_name>
hosts: <pattern>
For example:
.. code-block:: yaml
- name: restart webservers
hosts: webservers
Since you often want to run a command or playbook against multiple hosts at once, patterns often refer to inventory groups. Both the ad hoc command and the playbook above will execute against all machines in the ``webservers`` group.
.. _common_patterns:
Common patterns
---------------
This table lists common patterns for targeting inventory hosts and groups.
.. table::
:class: documentation-table
====================== ================================ ===================================================
Description Pattern(s) Targets
====================== ================================ ===================================================
All hosts all (or \*)
One host host1
Multiple hosts host1:host2 (or host1,host2)
One group webservers
Multiple groups webservers:dbservers all hosts in webservers plus all hosts in dbservers
Excluding groups webservers:!atlanta all hosts in webservers except those in atlanta
Intersection of groups webservers:&staging any hosts in webservers that are also in staging
====================== ================================ ===================================================
.. note:: You can use either a comma (``,``) or a colon (``:``) to separate a list of hosts. The comma is preferred when dealing with ranges and IPv6 addresses.
Once you know the basic patterns, you can combine them. This example:
.. code-block:: yaml
webservers:dbservers:&staging:!phoenix
targets all machines in the groups 'webservers' and 'dbservers' that are also in
the group 'staging', except any machines in the group 'phoenix'.
You can use wildcard patterns with FQDNs or IP addresses, as long as the hosts are named in your inventory by FQDN or IP address:
.. code-block:: yaml
192.0.*
*.example.com
*.com
You can mix wildcard patterns and groups at the same time:
.. code-block:: yaml
one*.com:dbservers
Limitations of patterns
-----------------------
Patterns depend on inventory. If a host or group is not listed in your inventory, you cannot use a pattern to target it. If your pattern includes an IP address or hostname that does not appear in your inventory, you will see an error like this:
.. code-block:: text
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: Could not match supplied host pattern, ignoring: *.not_in_inventory.com
Your pattern must match your inventory syntax. If you define a host as an :ref:`alias<inventory_aliases>`:
.. code-block:: yaml
atlanta:
host1:
http_port: 80
maxRequestsPerChild: 808
host: 127.0.0.2
you must use the alias in your pattern. In the example above, you must use ``host1`` in your pattern. If you use the IP address, you will once again get the error:
.. code-block:: console
[WARNING]: Could not match supplied host pattern, ignoring: 127.0.0.2
Pattern processing order
------------------------
The processing is a bit special and happens in the following order:
1. ``:`` and ``,``
2. `` &``
3. ``!``
This positioning only accounts for processing order inside each operation:
``a:b:&c:!d:!e == &c:a:!d:b:!e == !d:a:!e:&c:b``
All of these result in the following:
Host in/is (a or b) AND host in/is all(c) AND host NOT in/is all(d, e).
Now ``a:b:!e:!d:&c`` is a slight change as the ``!e`` gets processed before the ``!d``, though this doesn't make much of a difference:
Host in/is (a or b) AND host in/is all(c) AND host NOT in/is all(e, d).
Advanced pattern options
------------------------
The common patterns described above will meet most of your needs, but Ansible offers several other ways to define the hosts and groups you want to target.
Using variables in patterns
^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can use variables to enable passing group specifiers via the ``-e`` argument to ansible-playbook:
.. code-block:: bash
webservers:!{{ excluded }}:&{{ required }}
Using group position in patterns
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can define a host or subset of hosts by its position in a group. For example, given the following group:
.. code-block:: ini
[webservers]
cobweb
webbing
weber
you can use subscripts to select individual hosts or ranges within the webservers group:
.. code-block:: yaml
webservers[0] # == cobweb
webservers[-1] # == weber
webservers[0:2] # == webservers[0],webservers[1]
# == cobweb,webbing
webservers[1:] # == webbing,weber
webservers[:3] # == cobweb,webbing,weber
Using regexes in patterns
^^^^^^^^^^^^^^^^^^^^^^^^^
You can specify a pattern as a regular expression by starting the pattern with ``~``:
.. code-block:: yaml
~(web|db).*\.example\.com
Patterns and ad-hoc commands
----------------------------
You can change the behavior of the patterns defined in ad-hoc commands using command-line options.
You can also limit the hosts you target on a particular run with the ``--limit`` flag.
* Limit to one host
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit "host1"
* Limit to multiple hosts
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit "host1,host2"
* Negated limit. Note that single quotes MUST be used to prevent bash interpolation.
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit 'all:!host1'
* Limit to host group
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit 'group1'
Patterns and ansible-playbook flags
-----------------------------------
You can change the behavior of the patterns defined in playbooks using command-line options. For example, you can run a playbook that defines ``hosts: all`` on a single host by specifying ``-i 127.0.0.2,`` (note the trailing comma). This works even if the host you target is not defined in your inventory, but this method will NOT read your inventory for variables tied to this host and any variables required by the playbook will need to be specified manually at the command line. You can also limit the hosts you target on a particular run with the ``--limit`` flag, which will reference your inventory:
.. code-block:: bash
ansible-playbook site.yml --limit datacenter2
Finally, you can use ``--limit`` to read the list of hosts from a file by prefixing the file name with ``@``:
.. code-block:: bash
ansible-playbook site.yml --limit @retry_hosts.txt
If :ref:`RETRY_FILES_ENABLED` is set to ``True``, a ``.retry`` file will be created after the ``ansible-playbook`` run containing a list of failed hosts from all plays. This file is overwritten each time ``ansible-playbook`` finishes running.
ansible-playbook site.yml --limit @site.retry
To apply your knowledge of patterns with Ansible commands and playbooks, read :ref:`intro_adhoc` and :ref:`playbooks_intro`.
.. seealso::
:ref:`intro_adhoc`
Examples of basic commands
:ref:`working_with_playbooks`
Learning the Ansible configuration management language
`Mailing List <https://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
:ref:`communication_irc`
How to join Ansible chat channels

@ -1,123 +1,7 @@
.. _connections:
:orphan:
******************************
Connection methods and details
******************************
This section shows you how to expand and refine the connection methods Ansible uses for your inventory.
ControlPersist and paramiko
---------------------------
By default, Ansible uses native OpenSSH, because it supports ControlPersist (a performance feature), Kerberos, and options in ``~/.ssh/config`` such as Jump Host setup. If your control machine uses an older version of OpenSSH that does not support ControlPersist, Ansible will fallback to a Python implementation of OpenSSH called 'paramiko'.
.. _connection_set_user:
Setting a remote user
---------------------
By default, Ansible connects to all remote devices with the user name you are using on the control node. If that user name does not exist on a remote device, you can set a different user name for the connection. If you just need to do some tasks as a different user, look at :ref:`become`. You can set the connection user in a playbook:
.. code-block:: yaml
---
- name: update webservers
hosts: webservers
remote_user: admin
tasks:
- name: thing to do first in this playbook
. . .
as a host variable in inventory:
.. code-block:: text
other1.example.com ansible_connection=ssh ansible_user=myuser
other2.example.com ansible_connection=ssh ansible_user=myotheruser
or as a group variable in inventory:
.. code-block:: yaml
cloud:
hosts:
cloud1: my_backup.cloud.com
cloud2: my_backup2.cloud.com
vars:
ansible_user: admin
.. seealso::
:ref:`ssh_connection`
Details on the ``remote_user`` keyword and ``ansible_user`` variable.
:ref:`general_precedence_rules`
Details on Ansible precedence rules.
Setting up SSH keys
-------------------
By default, Ansible assumes you are using SSH keys to connect to remote machines. SSH keys are encouraged, but you can use password authentication if needed with the ``--ask-pass`` option. If you need to provide a password for :ref:`privilege escalation <become>` (sudo, pbrun, and so on), use ``--ask-become-pass``.
.. include:: shared_snippets/SSH_password_prompt.txt
To set up SSH agent to avoid retyping passwords, you can do:
.. code-block:: bash
$ ssh-agent bash
$ ssh-add ~/.ssh/id_rsa
Depending on your setup, you may wish to use Ansible's ``--private-key`` command line option to specify a pem file instead. You can also add the private key file:
.. code-block:: bash
$ ssh-agent bash
$ ssh-add ~/.ssh/keypair.pem
Another way to add private key files without using ssh-agent is using ``ansible_ssh_private_key_file`` in an inventory file as explained here: :ref:`intro_inventory`.
Running against localhost
-------------------------
You can run commands against the control node by using "localhost" or "127.0.0.1" for the server name:
.. code-block:: bash
$ ansible localhost -m ping -e 'ansible_python_interpreter="/usr/bin/env python"'
You can specify localhost explicitly by adding this to your inventory file:
.. code-block:: bash
localhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"
.. _host_key_checking_on:
Managing host key checking
--------------------------
Ansible enables host key checking by default. Checking host keys guards against server spoofing and man-in-the-middle attacks, but it does require some maintenance.
If a host is reinstalled and has a different key in 'known_hosts', this will result in an error message until corrected. If a new host is not in 'known_hosts' your control node may prompt for confirmation of the key, which results in an interactive experience if using Ansible, from say, cron. You might not want this.
If you understand the implications and wish to disable this behavior, you can do so by editing ``/etc/ansible/ansible.cfg`` or ``~/.ansible.cfg``:
.. code-block:: text
[defaults]
host_key_checking = False
Alternatively this can be set by the :envvar:`ANSIBLE_HOST_KEY_CHECKING` environment variable:
.. code-block:: bash
$ export ANSIBLE_HOST_KEY_CHECKING=False
Also note that host key checking in paramiko mode is reasonably slow, therefore switching to 'ssh' is also recommended when using this feature.
Other connection methods
------------------------
Ansible can use a variety of connection methods beyond SSH. You can select any connection plugin, including managing things locally and managing chroot, lxc, and jail containers.
A mode called 'ansible-pull' can also invert the system and have systems 'phone home' via scheduled git checkouts to pull configuration directives from a central repository.
This page has moved to :ref:`connections`.

@ -13,13 +13,6 @@ User Guide
Welcome to the Ansible User Guide! This guide covers how to work with Ansible, including using the command line, working with inventory, interacting with data, writing tasks, plays, and playbooks; executing playbooks, and reference materials.
Quickly find answers in the following sections or expand the table of contents below to scroll through all resources.
Working with inventory
======================
* I have a list of servers and devices I want to automate. How do I create :ref:`inventory <intro_inventory>` to track them?
* I use cloud services and constantly have servers and devices starting and stopping. How do I track them using :ref:`dynamic inventory <intro_dynamic_inventory>`?
* I want to automate specific sub-sets of my inventory. How do I use :ref:`patterns <intro_patterns>`?
Interacting with data
=====================
@ -45,10 +38,6 @@ Here is the complete list of resources in the Ansible User Guide:
intro_adhoc
cheatsheet
intro_inventory
intro_dynamic_inventory
intro_patterns
connection_details
command_line_tools
vault
complex_data_manipulation

@ -1,253 +1,7 @@
.. _intro_dynamic_inventory:
.. _dynamic_inventory:
:orphan:
******************************
Working with dynamic inventory
******************************
.. contents::
:local:
If your Ansible inventory fluctuates over time, with hosts spinning up and shutting down in response to business demands, the static inventory solutions described in :ref:`inventory` will not serve your needs. You may need to track hosts from multiple sources: cloud providers, LDAP, `Cobbler <https://cobbler.github.io>`_, and/or enterprise CMDB systems.
Ansible integrates all of these options through a dynamic external inventory system. Ansible supports two ways to connect with external inventory: :ref:`inventory_plugins` and `inventory scripts`.
Inventory plugins take advantage of the most recent updates to the Ansible core code. We recommend plugins over scripts for dynamic inventory. You can :ref:`write your own plugin <developing_inventory>` to connect to additional dynamic inventory sources.
You can still use inventory scripts if you choose. When we implemented inventory plugins, we ensured backwards compatibility through the script inventory plugin. The examples below illustrate how to use inventory scripts.
If you prefer a GUI for handling dynamic inventory, the inventory database on AWX or :ref:`ansible_platform` syncs with all your dynamic inventory sources, provides web and REST access to the results, and offers a graphical inventory editor. With a database record of all of your hosts, you can correlate past event history and see which hosts have had failures on their last playbook runs.
.. _cobbler_example:
Inventory script example: Cobbler
=================================
Ansible integrates seamlessly with `Cobbler <https://cobbler.github.io>`_, a Linux installation server originally written by Michael DeHaan and now led by James Cammarata, who works for Ansible.
While primarily used to kickoff OS installations and manage DHCP and DNS, Cobbler has a generic
layer that can represent data for multiple configuration management systems (even at the same time) and serve as a 'lightweight CMDB'.
To tie your Ansible inventory to Cobbler, copy `this script <https://raw.githubusercontent.com/ansible-community/contrib-scripts/main/inventory/cobbler.py>`_ to ``/etc/ansible`` and ``chmod +x`` the file. Run ``cobblerd`` any time you use Ansible and use the ``-i`` command line option (for example, ``-i /etc/ansible/cobbler.py``) to communicate with Cobbler using Cobbler's XMLRPC API.
Add a ``cobbler.ini`` file in ``/etc/ansible`` so Ansible knows where the Cobbler server is and some cache improvements can be used. For example:
.. code-block:: text
[cobbler]
# Set Cobbler's hostname or IP address
host = http://127.0.0.1/cobbler_api
# API calls to Cobbler can be slow. For this reason, we cache the results of an API
# call. Set this to the path you want cache files to be written to. Two files
# will be written to this directory:
# - ansible-cobbler.cache
# - ansible-cobbler.index
cache_path = /tmp
# The number of seconds a cache file is considered valid. After this many
# seconds, a new API call will be made, and the cache file will be updated.
cache_max_age = 900
First test the script by running ``/etc/ansible/cobbler.py`` directly. You should see some JSON data output, but it may not have anything in it just yet.
Let's explore what this does. In Cobbler, assume a scenario somewhat like the following:
.. code-block:: bash
cobbler profile add --name=webserver --distro=CentOS6-x86_64
cobbler profile edit --name=webserver --mgmt-classes="webserver" --ksmeta="a=2 b=3"
cobbler system edit --name=foo --dns-name="foo.example.com" --mgmt-classes="atlanta" --ksmeta="c=4"
cobbler system edit --name=bar --dns-name="bar.example.com" --mgmt-classes="atlanta" --ksmeta="c=5"
In the example above, the system 'foo.example.com' is addressable by ansible directly, but is also addressable when using the group names 'webserver' or 'atlanta'. Since Ansible uses SSH, it contacts system foo over 'foo.example.com', only, never just 'foo'. Similarly, if you tried "ansible foo", it would not find the system... but "ansible 'foo*'" would do, because the system DNS name starts with 'foo'.
The script provides more than host and group info. In addition, as a bonus, when the 'setup' module is run (which happens automatically when using playbooks), the variables 'a', 'b', and 'c' will all be auto-populated in the templates:
.. code-block:: text
# file: /srv/motd.j2
Welcome, I am templated with a value of a={{ a }}, b={{ b }}, and c={{ c }}
Which could be executed just like this:
.. code-block:: bash
ansible webserver -m setup
ansible webserver -m template -a "src=/tmp/motd.j2 dest=/etc/motd"
.. note::
The name 'webserver' came from Cobbler, as did the variables for
the config file. You can still pass in your own variables like
normal in Ansible, but variables from the external inventory script
will override any that have the same name.
So, with the template above (``motd.j2``), this results in the following data being written to ``/etc/motd`` for system 'foo':
.. code-block:: text
Welcome, I am templated with a value of a=2, b=3, and c=4
And on system 'bar' (bar.example.com):
.. code-block:: text
Welcome, I am templated with a value of a=2, b=3, and c=5
And technically, though there is no major good reason to do it, this also works:
.. code-block:: bash
ansible webserver -m ansible.builtin.shell -a "echo {{ a }}"
So, in other words, you can use those variables in arguments/actions as well.
.. _openstack_example:
Inventory script example: OpenStack
===================================
If you use an OpenStack-based cloud, instead of manually maintaining your own inventory file, you can use the ``openstack_inventory.py`` dynamic inventory to pull information about your compute instances directly from OpenStack.
You can download the latest version of the OpenStack inventory script `here <https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack_inventory.py>`_.
You can use the inventory script explicitly (by passing the `-i openstack_inventory.py` argument to Ansible) or implicitly (by placing the script at `/etc/ansible/hosts`).
Explicit use of OpenStack inventory script
------------------------------------------
Download the latest version of the OpenStack dynamic inventory script and make it executable.
.. code-block:: bash
wget https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack_inventory.py
chmod +x openstack_inventory.py
.. note::
Do not name it `openstack.py`. This name will conflict with imports from openstacksdk.
Source an OpenStack RC file:
.. code-block:: bash
source openstack.rc
.. note::
An OpenStack RC file contains the environment variables required by the client tools to establish a connection with the cloud provider, such as the authentication URL, user name, password and region name. For more information on how to download, create or source an OpenStack RC file, please refer to `Set environment variables using the OpenStack RC file <https://docs.openstack.org/user-guide/common/cli_set_environment_variables_using_openstack_rc.html>`_.
You can confirm the file has been successfully sourced by running a simple command, such as `nova list` and ensuring it returns no errors.
.. note::
The OpenStack command line clients are required to run the `nova list` command. For more information on how to install them, please refer to `Install the OpenStack command-line clients <https://docs.openstack.org/user-guide/common/cli_install_openstack_command_line_clients.html>`_.
You can test the OpenStack dynamic inventory script manually to confirm it is working as expected:
.. code-block:: bash
./openstack_inventory.py --list
After a few moments you should see some JSON output with information about your compute instances.
Once you confirm the dynamic inventory script is working as expected, you can tell Ansible to use the `openstack_inventory.py` script as an inventory file, as illustrated below:
.. code-block:: bash
ansible -i openstack_inventory.py all -m ansible.builtin.ping
Implicit use of OpenStack inventory script
------------------------------------------
Download the latest version of the OpenStack dynamic inventory script, make it executable and copy it to `/etc/ansible/hosts`:
.. code-block:: bash
wget https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack_inventory.py
chmod +x openstack_inventory.py
sudo cp openstack_inventory.py /etc/ansible/hosts
Download the sample configuration file, modify it to suit your needs and copy it to `/etc/ansible/openstack.yml`:
.. code-block:: bash
wget https://raw.githubusercontent.com/openstack/ansible-collections-openstack/master/scripts/inventory/openstack.yml
vi openstack.yml
sudo cp openstack.yml /etc/ansible/
You can test the OpenStack dynamic inventory script manually to confirm it is working as expected:
.. code-block:: bash
/etc/ansible/hosts --list
After a few moments you should see some JSON output with information about your compute instances.
Refreshing the cache
--------------------
Note that the OpenStack dynamic inventory script will cache results to avoid repeated API calls. To explicitly clear the cache, you can run the openstack_inventory.py (or hosts) script with the ``--refresh`` parameter:
.. code-block:: bash
./openstack_inventory.py --refresh --list
.. _other_inventory_scripts:
Other inventory scripts
=======================
In Ansible 2.10 and later, inventory scripts moved to their associated collections. Many are now in the `community.general scripts/inventory directory <https://github.com/ansible-collections/community.general/tree/main/scripts/inventory>`_. We recommend you use :ref:`inventory_plugins` instead.
.. _using_multiple_sources:
Using inventory directories and multiple inventory sources
==========================================================
If the location given to ``-i`` in Ansible is a directory (or as so configured in ``ansible.cfg``), Ansible can use multiple inventory sources
at the same time. When doing so, it is possible to mix both dynamic and statically managed inventory sources in the same ansible run. Instant
hybrid cloud!
In an inventory directory, executable files are treated as dynamic inventory sources and most other files as static sources. Files which end with any of the following are ignored:
.. code-block:: text
~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo
You can replace this list with your own selection by configuring an ``inventory_ignore_extensions`` list in ``ansible.cfg``, or setting the :envvar:`ANSIBLE_INVENTORY_IGNORE` environment variable. The value in either case must be a comma-separated list of patterns, as shown above.
Any ``group_vars`` and ``host_vars`` subdirectories in an inventory directory are interpreted as expected, making inventory directories a powerful way to organize different sets of configurations. See :ref:`using_multiple_inventory_sources` for more information.
.. _static_groups_of_dynamic:
Static groups of dynamic groups
===============================
When defining groups of groups in the static inventory file, the child groups
must also be defined in the static inventory file, otherwise ansible returns an
error. If you want to define a static group of dynamic child groups, define
the dynamic groups as empty in the static inventory file. For example:
.. code-block:: text
[tag_Name_staging_foo]
[tag_Name_staging_bar]
[staging:children]
tag_Name_staging_foo
tag_Name_staging_bar
.. seealso::
:ref:`intro_inventory`
All about static inventory files
`Mailing List <https://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`intro_dynamic_inventory`.

@ -1,797 +1,7 @@
.. _intro_inventory:
.. _inventory:
:orphan:
***************************
How to build your inventory
***************************
Ansible works against multiple managed nodes or "hosts" in your infrastructure at the same time, using a list or group of lists known as inventory. Once your inventory is defined, you use :ref:`patterns <intro_patterns>` to select the hosts or groups you want Ansible to run against.
The default location for inventory is a file called ``/etc/ansible/hosts``. You can specify a different inventory file at the command line using the ``-i <path>`` option. You can also use multiple inventory files at the same time as described in :ref:`using_multiple_inventory_sources`, and/or pull inventory from dynamic or cloud sources or different formats (YAML, ini, and so on), as described in :ref:`intro_dynamic_inventory`.
Introduced in version 2.4, Ansible has :ref:`inventory_plugins` to make this flexible and customizable.
.. contents::
:local:
.. _inventoryformat:
Inventory basics: formats, hosts, and groups
============================================
The inventory file can be in one of many formats, depending on the inventory plugins you have.
The most common formats are INI and YAML. A basic INI ``/etc/ansible/hosts`` might look like this:
.. code-block:: text
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
The headings in brackets are group names, which are used in classifying hosts
and deciding what hosts you are controlling at what times and for what purpose.
Group names should follow the same guidelines as :ref:`valid_variable_names`.
Here's that same basic inventory file in YAML format:
.. code-block:: yaml
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
.. _default_groups:
Default groups
--------------
There are two default groups: ``all`` and ``ungrouped``. The ``all`` group contains every host.
The ``ungrouped`` group contains all hosts that don't have another group aside from ``all``.
Every host will always belong to at least 2 groups (``all`` and ``ungrouped`` or ``all`` and some other group). Though ``all`` and ``ungrouped`` are always present, they can be implicit and not appear in group listings like ``group_names``.
.. _host_multiple_groups:
Hosts in multiple groups
------------------------
You can (and probably will) put each host in more than one group. For example a production webserver in a datacenter in Atlanta might be included in groups called [prod] and [atlanta] and [webservers]. You can create groups that track:
* What - An application, stack or microservice (for example, database servers, web servers, and so on).
* Where - A datacenter or region, to talk to local DNS, storage, and so on (for example, east, west).
* When - The development stage, to avoid testing on production resources (for example, prod, test).
Extending the previous YAML inventory to include what, when, and where would look like:
.. code-block:: yaml
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
hosts:
foo.example.com:
one.example.com:
two.example.com:
test:
hosts:
bar.example.com:
three.example.com:
You can see that ``one.example.com`` exists in the ``dbservers``, ``east``, and ``prod`` groups.
You can also use nested groups to simplify ``prod`` and ``test`` in this inventory, for the same result:
.. code-block:: yaml
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
east:
hosts:
foo.example.com:
one.example.com:
two.example.com:
west:
hosts:
bar.example.com:
three.example.com:
prod:
children:
east:
test:
children:
west:
You can find more examples on how to organize your inventories and group your hosts in :ref:`inventory_setup_examples`.
Adding ranges of hosts
----------------------
If you have a lot of hosts with a similar pattern, you can add them as a range rather than listing each hostname separately:
In INI:
.. code-block:: text
[webservers]
www[01:50].example.com
In YAML:
.. code-block:: yaml
...
webservers:
hosts:
www[01:50].example.com:
You can specify a stride (increments between sequence numbers) when defining a numeric range of hosts:
In INI:
.. code-block:: text
[webservers]
www[01:50:2].example.com
In YAML:
.. code-block:: yaml
...
webservers:
hosts:
www[01:50:2].example.com:
The example above would make the subdomains www01, www03, www05, ..., www49 match, but not www00, www02, www50 and so on, because the stride (increment) is 2 units each step.
For numeric patterns, leading zeros can be included or removed, as desired. Ranges are inclusive. You can also define alphabetic ranges:
.. code-block:: text
[databases]
db-[a:f].example.com
.. _variables_in_inventory:
Adding variables to inventory
=============================
You can store variable values that relate to a specific host or group in inventory. To start with, you may add variables directly to the hosts and groups in your main inventory file. As you add more and more managed nodes to your Ansible inventory, however, you will likely want to store variables in separate host and group variable files. See :ref:`define_variables_in_inventory` for details.
.. _host_variables:
Assigning a variable to one machine: host variables
===================================================
You can easily assign a variable to a single host, then use it later in playbooks. In INI:
.. code-block:: text
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
In YAML:
.. code-block:: yaml
atlanta:
hosts:
host1:
http_port: 80
maxRequestsPerChild: 808
host2:
http_port: 303
maxRequestsPerChild: 909
Unique values like non-standard SSH ports work well as host variables. You can add them to your Ansible inventory by adding the port number after the hostname with a colon:
.. code-block:: text
badwolf.example.com:5309
Connection variables also work well as host variables:
.. code-block:: text
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=myuser
other2.example.com ansible_connection=ssh ansible_user=myotheruser
.. note:: If you list non-standard SSH ports in your SSH config file, the ``openssh`` connection will find and use them, but the ``paramiko`` connection will not.
.. _inventory_aliases:
Inventory aliases
-----------------
You can also define aliases in your inventory:
In INI:
.. code-block:: text
jumper ansible_port=5555 ansible_host=192.0.2.50
In YAML:
.. code-block:: yaml
...
hosts:
jumper:
ansible_port: 5555
ansible_host: 192.0.2.50
In the above example, running Ansible against the host alias "jumper" will connect to 192.0.2.50 on port 5555. See :ref:`behavioral inventory parameters <behavioral_parameters>` to further customize the connection to hosts.
.. note::
Values passed in the INI format using the ``key=value`` syntax are interpreted differently depending on where they are declared:
* When declared inline with the host, INI values are interpreted as Python literal structures (strings, numbers, tuples, lists, dicts, booleans, None). Host lines accept multiple ``key=value`` parameters per line. Therefore they need a way to indicate that a space is part of a value rather than a separator. Values that contain whitespace can be quoted (single or double). See the `Python shlex parsing rules`_ for details.
* When declared in a ``:vars`` section, INI values are interpreted as strings. For example ``var=FALSE`` would create a string equal to 'FALSE'. Unlike host lines, ``:vars`` sections accept only a single entry per line, so everything after the ``=`` must be the value for the entry.
* If a variable value set in an INI inventory must be a certain type (for example, a string or a boolean value), always specify the type with a filter in your task. Do not rely on types set in INI inventories when consuming variables.
* Consider using YAML format for inventory sources to avoid confusion on the actual type of a variable. The YAML inventory plugin processes variable values consistently and correctly.
Generally speaking, this is not the best way to define variables that describe your system policy. Setting variables in the main inventory file is only a shorthand. See :ref:`splitting_out_vars` for guidelines on storing variable values in individual files in the 'host_vars' directory.
.. _Python shlex parsing rules: https://docs.python.org/3/library/shlex.html#parsing-rules
.. _group_variables:
Assigning a variable to many machines: group variables
======================================================
If all hosts in a group share a variable value, you can apply that variable to an entire group at once. In INI:
.. code-block:: text
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
In YAML:
.. code-block:: yaml
atlanta:
hosts:
host1:
host2:
vars:
ntp_server: ntp.atlanta.example.com
proxy: proxy.atlanta.example.com
Group variables are a convenient way to apply variables to multiple hosts at once. Before executing, however, Ansible always flattens variables, including inventory variables, to the host level. If a host is a member of multiple groups, Ansible reads variable values from all of those groups. If you assign different values to the same variable in different groups, Ansible chooses which value to use based on internal :ref:`rules for merging <how_we_merge>`.
.. _subgroups:
Inheriting variable values: group variables for groups of groups
----------------------------------------------------------------
You can make groups of groups using the ``:children`` suffix in INI or the ``children:`` entry in YAML.
You can apply variables to these groups of groups using ``:vars`` or ``vars:``:
In INI:
.. code-block:: text
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[usa:children]
southeast
northeast
southwest
northwest
In YAML:
.. code-block:: yaml
all:
children:
usa:
children:
southeast:
children:
atlanta:
hosts:
host1:
host2:
raleigh:
hosts:
host2:
host3:
vars:
some_server: foo.southeast.example.com
halon_system_timeout: 30
self_destruct_countdown: 60
escape_pods: 2
northeast:
northwest:
southwest:
If you need to store lists or hash data, or prefer to keep host and group specific variables separate from the inventory file, see :ref:`splitting_out_vars`.
Child groups have a couple of properties to note:
- Any host that is member of a child group is automatically a member of the parent group.
- A child group's variables will have higher precedence (override) a parent group's variables.
- Groups can have multiple parents and children, but not circular relationships.
- Hosts can also be in multiple groups, but there will only be **one** instance of a host, merging the data from the multiple groups.
.. _splitting_out_vars:
Organizing host and group variables
===================================
Although you can store variables in the main inventory file, storing separate host and group variables files may help you organize your variable values more easily. Host and group variable files must use YAML syntax. Valid file extensions include '.yml', '.yaml', '.json', or no file extension.
See :ref:`yaml_syntax` if you are new to YAML.
Ansible loads host and group variable files by searching paths relative to the inventory file or the playbook file. If your inventory file at ``/etc/ansible/hosts`` contains a host named 'foosball' that belongs to two groups, 'raleigh' and 'webservers', that host will use variables in YAML files at the following locations:
.. code-block:: bash
/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
For example, if you group hosts in your inventory by datacenter, and each datacenter uses its own NTP server and database server, you can create a file called ``/etc/ansible/group_vars/raleigh`` to store the variables for the ``raleigh`` group:
.. code-block:: yaml
---
ntp_server: acme.example.org
database_server: storage.example.org
You can also create *directories* named after your groups or hosts. Ansible will read all the files in these directories in lexicographical order. An example with the 'raleigh' group:
.. code-block:: bash
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
All hosts in the 'raleigh' group will have the variables defined in these files
available to them. This can be very useful to keep your variables organized when a single
file gets too big, or when you want to use :ref:`Ansible Vault<playbooks_vault>` on some group variables.
For ``ansible-playbook`` you can also add ``group_vars/`` and ``host_vars/`` directories to your playbook directory. Other Ansible commands (for example, ``ansible``, ``ansible-console``, and so on) will only look for ``group_vars/`` and ``host_vars/`` in the inventory directory. If you want other commands to load group and host variables from a playbook directory, you must provide the ``--playbook-dir`` option on the command line.
If you load inventory files from both the playbook directory and the inventory directory, variables in the playbook directory will override variables set in the inventory directory.
Keeping your inventory file and variables in a git repo (or other version control)
is an excellent way to track changes to your inventory and host variables.
.. _how_we_merge:
How variables are merged
========================
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 (see :ref:`DEFAULT_HASH_BEHAVIOUR<DEFAULT_HASH_BEHAVIOUR>`). 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. For example, an a_group will be merged with b_group and b_group vars that match will overwrite the ones in a_group.
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. For example:
.. code-block:: yaml
a_group:
vars:
testvar: a
ansible_group_priority: 10
b_group:
vars:
testvar: b
In this example, if both groups have the same priority, the result would normally have been ``testvar == b``, but since we are giving the ``a_group`` a higher priority the result will be ``testvar == a``.
.. note:: ``ansible_group_priority`` can only be set in the inventory source and not in group_vars/, as the variable is used in the loading of group_vars.
.. _using_multiple_inventory_sources:
Using multiple inventory sources
================================
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 :envvar:`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:
.. code-block:: bash
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 in :ref:`how_we_merge` and :ref:`ansible_variable_precedence`.
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:
.. code-block:: text
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:
.. code-block:: bash
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:
.. code-block:: text
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``.
For more details on inventory plugins and dynamic inventory scripts see :ref:`inventory_plugins` and :ref:`intro_dynamic_inventory`.
.. _behavioral_parameters:
Connecting to hosts: behavioral inventory parameters
====================================================
As described above, setting the following variables control how Ansible interacts with remote hosts.
Host connection:
.. include:: shared_snippets/SSH_password_prompt.txt
ansible_connection
Connection type to the host. This can be the name of any of ansible's connection plugins. SSH protocol types are ``smart``, ``ssh`` or ``paramiko``. The default is smart. Non-SSH based types are described in the next section.
General for all connections:
ansible_host
The name of the host to connect to, if different from the alias you wish to give to it.
ansible_port
The connection port number, if not the default (22 for ssh)
ansible_user
The user name to use when connecting to the host
ansible_password
The password to use to authenticate to the host (never store this variable in plain text; always use a vault. See :ref:`tip_for_variables_and_vaults`)
Specific to the SSH connection:
ansible_ssh_private_key_file
Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent.
ansible_ssh_common_args
This setting is always appended to the default command line for :command:`sftp`, :command:`scp`,
and :command:`ssh`. Useful to configure a ``ProxyCommand`` for a certain host (or
group).
ansible_sftp_extra_args
This setting is always appended to the default :command:`sftp` command line.
ansible_scp_extra_args
This setting is always appended to the default :command:`scp` command line.
ansible_ssh_extra_args
This setting is always appended to the default :command:`ssh` command line.
ansible_ssh_pipelining
Determines whether or not to use SSH pipelining. This can override the ``pipelining`` setting in :file:`ansible.cfg`.
ansible_ssh_executable (added in version 2.2)
This setting overrides the default behavior to use the system :command:`ssh`. This can override the ``ssh_executable`` setting in :file:`ansible.cfg`.
Privilege escalation (see :ref:`Ansible Privilege Escalation<become>` for further details):
ansible_become
Equivalent to ``ansible_sudo`` or ``ansible_su``, allows to force privilege escalation
ansible_become_method
Allows to set privilege escalation method
ansible_become_user
Equivalent to ``ansible_sudo_user`` or ``ansible_su_user``, allows to set the user you become through privilege escalation
ansible_become_password
Equivalent to ``ansible_sudo_password`` or ``ansible_su_password``, allows you to set the privilege escalation password (never store this variable in plain text; always use a vault. See :ref:`tip_for_variables_and_vaults`)
ansible_become_exe
Equivalent to ``ansible_sudo_exe`` or ``ansible_su_exe``, allows you to set the executable for the escalation method selected
ansible_become_flags
Equivalent to ``ansible_sudo_flags`` or ``ansible_su_flags``, allows you to set the flags passed to the selected escalation method. This can be also set globally in :file:`ansible.cfg` in the ``sudo_flags`` option
Remote host environment parameters:
.. _ansible_shell_type:
ansible_shell_type
The shell type of the target system. You should not use this setting unless you have set the
:ref:`ansible_shell_executable<ansible_shell_executable>` to a non-Bourne (sh) compatible shell. By default commands are
formatted using ``sh``-style syntax. Setting this to ``csh`` or ``fish`` will cause commands
executed on target systems to follow those shell's syntax instead.
.. _ansible_python_interpreter:
ansible_python_interpreter
The target host python path. This is useful for systems with more
than one Python or not located at :command:`/usr/bin/python` such as \*BSD, or where :command:`/usr/bin/python`
is not a 2.X series Python. We do not use the :command:`/usr/bin/env` mechanism as that requires the remote user's
path to be set right and also assumes the :program:`python` executable is named python, where the executable might
be named something like :program:`python2.6`.
ansible_*_interpreter
Works for anything such as ruby or perl and works just like :ref:`ansible_python_interpreter<ansible_python_interpreter>`.
This replaces shebang of modules which will run on that host.
.. versionadded:: 2.1
.. _ansible_shell_executable:
ansible_shell_executable
This sets the shell the ansible controller will use on the target machine,
overrides ``executable`` in :file:`ansible.cfg` which defaults to
:command:`/bin/sh`. You should really only change it if is not possible
to use :command:`/bin/sh` (in other words, if :command:`/bin/sh` is not installed on the target
machine or cannot be run from sudo.).
Examples from an Ansible-INI host file:
.. code-block:: text
some_host ansible_port=2222 ansible_user=manager
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
Non-SSH connection types
------------------------
As stated in the previous section, Ansible executes playbooks over SSH but it is not limited to this connection type.
With the host specific parameter ``ansible_connection=<connector>``, the connection type can be changed.
The following non-SSH based connectors are available:
**local**
This connector can be used to deploy the playbook to the control machine itself.
**docker**
This connector deploys the playbook directly into Docker containers using the local Docker client. The following parameters are processed by this connector:
ansible_host
The name of the Docker container to connect to.
ansible_user
The user name to operate within the container. The user must exist inside the container.
ansible_become
If set to ``true`` the ``become_user`` will be used to operate within the container.
ansible_docker_extra_args
Could be a string with any additional arguments understood by Docker, which are not command specific. This parameter is mainly used to configure a remote Docker daemon to use.
Here is an example of how to instantly deploy to created containers:
.. code-block:: yaml
- name: Create a jenkins container
community.general.docker_container:
docker_host: myserver.net:4243
name: my_jenkins
image: jenkins
- name: Add the container to inventory
ansible.builtin.add_host:
name: my_jenkins
ansible_connection: docker
ansible_docker_extra_args: "--tlsverify --tlscacert=/path/to/ca.pem --tlscert=/path/to/client-cert.pem --tlskey=/path/to/client-key.pem -H=tcp://myserver.net:4243"
ansible_user: jenkins
changed_when: false
- name: Create a directory for ssh keys
delegate_to: my_jenkins
ansible.builtin.file:
path: "/var/jenkins_home/.ssh/jupiter"
state: directory
For a full list with available plugins and examples, see :ref:`connection_plugin_list`.
.. note:: If you're reading the docs from the beginning, this may be the first example you've seen of an Ansible playbook. This is not an inventory file.
Playbooks will be covered in great detail later in the docs.
.. _inventory_setup_examples:
Inventory setup examples
========================
See also :ref:`sample_setup`, which shows inventory along with playbooks and other Ansible artifacts.
.. _inventory_setup-per_environment:
Example: One inventory per environment
--------------------------------------
If you need to manage multiple environments it's sometimes prudent to
have only hosts of a single environment defined per inventory. This
way, it is harder to, for instance, accidentally change the state of
nodes inside the "test" environment when you actually wanted to update
some "staging" servers.
For the example mentioned above you could have an
:file:`inventory_test` file:
.. code-block:: ini
[dbservers]
db01.test.example.com
db02.test.example.com
[appservers]
app01.test.example.com
app02.test.example.com
app03.test.example.com
That file only includes hosts that are part of the "test"
environment. Define the "staging" machines in another file
called :file:`inventory_staging`:
.. code-block:: ini
[dbservers]
db01.staging.example.com
db02.staging.example.com
[appservers]
app01.staging.example.com
app02.staging.example.com
app03.staging.example.com
To apply a playbook called :file:`site.yml`
to all the app servers in the test environment, use the
following command:
.. code-block:: bash
ansible-playbook -i inventory_test -l appservers site.yml
.. _inventory_setup-per_function:
Example: Group by function
--------------------------
In the previous section you already saw an example for using groups in
order to cluster hosts that have the same function. This allows you,
for instance, to define firewall rules inside a playbook or role
affecting only database servers:
.. code-block:: yaml
- hosts: dbservers
tasks:
- name: Allow access from 10.0.0.1
ansible.builtin.iptables:
chain: INPUT
jump: ACCEPT
source: 10.0.0.1
.. _inventory_setup-per_location:
Example: Group by location
--------------------------
Other tasks might be focused on where a certain host is located. Let's
say that ``db01.test.example.com`` and ``app01.test.example.com`` are
located in DC1 while ``db02.test.example.com`` is in DC2:
.. code-block:: ini
[dc1]
db01.test.example.com
app01.test.example.com
[dc2]
db02.test.example.com
In practice, you might even end up mixing all these setups as you
might need to, on one day, update all nodes in a specific data center
while, on another day, update all the application servers no matter
their location.
.. seealso::
:ref:`inventory_plugins`
Pulling inventory from dynamic or static sources
:ref:`intro_dynamic_inventory`
Pulling inventory from dynamic sources, such as cloud providers
:ref:`intro_adhoc`
Examples of basic commands
:ref:`working_with_playbooks`
Learning Ansible's configuration, deployment, and orchestration language.
`Mailing List <https://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`intro_inventory`.

@ -1,246 +1,6 @@
.. _intro_patterns:
:orphan:
Patterns: targeting hosts and groups
====================================
When you execute Ansible through an ad hoc command or by running a playbook, you must choose which managed nodes or groups you want to execute against. Patterns let you run commands and playbooks against specific hosts and/or groups in your inventory. An Ansible pattern can refer to a single host, an IP address, an inventory group, a set of groups, or all hosts in your inventory. Patterns are highly flexible - you can exclude or require subsets of hosts, use wildcards or regular expressions, and more. Ansible executes on all inventory hosts included in the pattern.
.. contents::
:local:
Using patterns
--------------
You use a pattern almost any time you execute an ad hoc command or a playbook. The pattern is the only element of an :ref:`ad hoc command<intro_adhoc>` that has no flag. It is usually the second element:
.. code-block:: bash
ansible <pattern> -m <module_name> -a "<module options>"
For example:
.. code-block:: bash
ansible webservers -m service -a "name=httpd state=restarted"
In a playbook the pattern is the content of the ``hosts:`` line for each play:
.. code-block:: yaml
- name: <play_name>
hosts: <pattern>
For example:
.. code-block:: yaml
- name: restart webservers
hosts: webservers
Since you often want to run a command or playbook against multiple hosts at once, patterns often refer to inventory groups. Both the ad hoc command and the playbook above will execute against all machines in the ``webservers`` group.
.. _common_patterns:
Common patterns
---------------
This table lists common patterns for targeting inventory hosts and groups.
.. table::
:class: documentation-table
====================== ================================ ===================================================
Description Pattern(s) Targets
====================== ================================ ===================================================
All hosts all (or \*)
One host host1
Multiple hosts host1:host2 (or host1,host2)
One group webservers
Multiple groups webservers:dbservers all hosts in webservers plus all hosts in dbservers
Excluding groups webservers:!atlanta all hosts in webservers except those in atlanta
Intersection of groups webservers:&staging any hosts in webservers that are also in staging
====================== ================================ ===================================================
.. note:: You can use either a comma (``,``) or a colon (``:``) to separate a list of hosts. The comma is preferred when dealing with ranges and IPv6 addresses.
Once you know the basic patterns, you can combine them. This example:
.. code-block:: yaml
webservers:dbservers:&staging:!phoenix
targets all machines in the groups 'webservers' and 'dbservers' that are also in
the group 'staging', except any machines in the group 'phoenix'.
You can use wildcard patterns with FQDNs or IP addresses, as long as the hosts are named in your inventory by FQDN or IP address:
.. code-block:: yaml
192.0.*
*.example.com
*.com
You can mix wildcard patterns and groups at the same time:
.. code-block:: yaml
one*.com:dbservers
Limitations of patterns
-----------------------
Patterns depend on inventory. If a host or group is not listed in your inventory, you cannot use a pattern to target it. If your pattern includes an IP address or hostname that does not appear in your inventory, you will see an error like this:
.. code-block:: text
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: Could not match supplied host pattern, ignoring: *.not_in_inventory.com
Your pattern must match your inventory syntax. If you define a host as an :ref:`alias<inventory_aliases>`:
.. code-block:: yaml
atlanta:
host1:
http_port: 80
maxRequestsPerChild: 808
host: 127.0.0.2
you must use the alias in your pattern. In the example above, you must use ``host1`` in your pattern. If you use the IP address, you will once again get the error:
.. code-block:: console
[WARNING]: Could not match supplied host pattern, ignoring: 127.0.0.2
Pattern processing order
------------------------
The processing is a bit special and happens in the following order:
1. ``:`` and ``,``
2. `` &``
3. ``!``
This positioning only accounts for processing order inside each operation:
``a:b:&c:!d:!e == &c:a:!d:b:!e == !d:a:!e:&c:b``
All of these result in the following:
Host in/is (a or b) AND host in/is all(c) AND host NOT in/is all(d, e).
Now ``a:b:!e:!d:&c`` is a slight change as the ``!e`` gets processed before the ``!d``, though this doesn't make much of a difference:
Host in/is (a or b) AND host in/is all(c) AND host NOT in/is all(e, d).
Advanced pattern options
------------------------
The common patterns described above will meet most of your needs, but Ansible offers several other ways to define the hosts and groups you want to target.
Using variables in patterns
^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can use variables to enable passing group specifiers via the ``-e`` argument to ansible-playbook:
.. code-block:: bash
webservers:!{{ excluded }}:&{{ required }}
Using group position in patterns
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can define a host or subset of hosts by its position in a group. For example, given the following group:
.. code-block:: ini
[webservers]
cobweb
webbing
weber
you can use subscripts to select individual hosts or ranges within the webservers group:
.. code-block:: yaml
webservers[0] # == cobweb
webservers[-1] # == weber
webservers[0:2] # == webservers[0],webservers[1]
# == cobweb,webbing
webservers[1:] # == webbing,weber
webservers[:3] # == cobweb,webbing,weber
Using regexes in patterns
^^^^^^^^^^^^^^^^^^^^^^^^^
You can specify a pattern as a regular expression by starting the pattern with ``~``:
.. code-block:: yaml
~(web|db).*\.example\.com
Patterns and ad-hoc commands
----------------------------
You can change the behavior of the patterns defined in ad-hoc commands using command-line options.
You can also limit the hosts you target on a particular run with the ``--limit`` flag.
* Limit to one host
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit "host1"
* Limit to multiple hosts
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit "host1,host2"
* Negated limit. Note that single quotes MUST be used to prevent bash interpolation.
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit 'all:!host1'
* Limit to host group
.. code-block:: bash
$ ansible -m [module] -a "[module options]" --limit 'group1'
Patterns and ansible-playbook flags
-----------------------------------
You can change the behavior of the patterns defined in playbooks using command-line options. For example, you can run a playbook that defines ``hosts: all`` on a single host by specifying ``-i 127.0.0.2,`` (note the trailing comma). This works even if the host you target is not defined in your inventory, but this method will NOT read your inventory for variables tied to this host and any variables required by the playbook will need to be specified manually at the command line. You can also limit the hosts you target on a particular run with the ``--limit`` flag, which will reference your inventory:
.. code-block:: bash
ansible-playbook site.yml --limit datacenter2
Finally, you can use ``--limit`` to read the list of hosts from a file by prefixing the file name with ``@``:
.. code-block:: bash
ansible-playbook site.yml --limit @retry_hosts.txt
If :ref:`RETRY_FILES_ENABLED` is set to ``True``, a ``.retry`` file will be created after the ``ansible-playbook`` run containing a list of failed hosts from all plays. This file is overwritten each time ``ansible-playbook`` finishes running.
ansible-playbook site.yml --limit @site.retry
To apply your knowledge of patterns with Ansible commands and playbooks, read :ref:`intro_adhoc` and :ref:`playbooks_intro`.
.. seealso::
:ref:`intro_adhoc`
Examples of basic commands
:ref:`working_with_playbooks`
Learning the Ansible configuration management language
`Mailing List <https://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`intro_patterns`.
Loading…
Cancel
Save