Lab 001 - Verify Ansible configuration¶
- In this lab we will create the Ansible configuration and verify that it is configured correctly.
- This lab is based upon the previous lab and its
docker-compose. - In this lab we will learn how to use:
ansible.cfginventoryssh.config
Pre-Requirements¶
- Complete the previous lab in order to have the
Ansiblecontroller and theLinuxservers up and running.
01. Create configuration files¶
IMPORTANT!
- In this lab we will be placing the files under the
/labs-scriptsdirectory. - The directory is mounted to our docker container(s) under the
<PROJECT_ROOT>/runtimedirectory. - You are encouraged to review the
docker-compose.yamlfile throughout the lab session.
02. About ansible.cfg file¶
- What is
ansible.cfg?- The
ansible.cfgfile is an INI-like configuration file used to define various settings and parameters that influence how Ansible operates. - It allows users to customize Ansible’s behavior, such as specifying inventory locations, default module settings, connection options, and more.
- The
ansible.cfgfile can be placed in several locations, and Ansible will search for it in a specific order. - The configuration file is divided into sections, each containing various customizable parameters that control different aspects of Ansible’s functionality.
- Below we will create the
ansible.cfgfile, thessh.configfile and theinventoryfile.
- The
03. ansible.cfg locations:¶
- Reference: Official Ansible documentation: - Ansible Configuration Settings
- Ansible searches
ansible.cfgin a specific order. - The first file it finds will be used while ignoring the rest.
-
Ansible will search for the configuration file in the following order:
Search resource Description ANSIBLE_CONFIGenvironment variable if set ansible.cfgIn the current directory ~/.ansible.cfgUnder the home directory /etc/ansible/ansible.cfgOS common path -
In this exercise the environment variable
ANSIBLE_CONFIGis set in the docker container path/labs-scripts/.ansible.cfg
04. ansible.cfg structure:¶
-
The
ansible.cfgfile is divided into sections, each containing various customizable parameters. -
Main
ansible.cfgsettings:
| Setting | Description | Ansible Docs |
|---|---|---|
| [callback_plugins] | Specifies directories for callback plugins that customize output or trigger actions. | Docs |
| [connection] | Defines general connection settings that apply to all connection types. | Docs |
| [defaults] | Contains general settings for Ansible such as inventory location, verbosity, and log settings. | Docs |
| [diff] | Controls whether Ansible shows differences when applying configurations. | Docs |
| [galaxy] | Configures settings for Ansible Galaxy, a hub for sharing roles and collections. | Docs |
| [inventory] | Defines options related to inventory parsing and caching. | Docs |
| [logging] | Logging configuration, typically under [defaults] section using log_path. | Docs |
| [paramiko_connection] | Configures settings specific to the Paramiko SSH library. | Docs |
| [privilege_escalation] | Defines settings related to privilege escalation, such as sudo or become. | Docs |
| [ssh_connection] | Settings for SSH connections, (timeout, control settings etc). | Docs |
| [winrm] | Configures settings for Windows Remote Management (WinRM) connections. | Docs |
[callback_plugins]¶
- The
[callback_plugins]section specifies directories where Ansible looks for callback plugins, which can customize output or trigger actions based on playbook events.
[connection]¶
- The
[connection]section defines general connection settings that apply to all connection types.
[defaults]¶
- The
[defaults]section contains the general settings for Ansible (such as inventory location, verbosity and log settings). - It is the most commonly used section and is often the first place users look to customize their Ansible environment.
-
Here are some commonly used settings in the
[defaults]section:ask_pass- If set to true, Ansible will prompt for the SSH password.host_key_checking- If set to false, Ansible will not check SSH host keys.inventory- Specifies the path to the inventory file.log_path- Specifies the path to the log file.remote_user- Specifies the default remote user for SSH connections.timeout- Specifies the timeout for SSH connections in seconds.private_key_file- Specifies the path to the private key file for SSH authentication.become- If set to true, privilege escalation (e.g., sudo) will be used.become_method- Specifies the method to use for privilege escalation (e.g., sudo, su).become_user- Specifies the user to become when using privilege escalation.retry_files_enabled- If set to false, Ansible will not create retry files.gathering- Specifies how facts are gathered (e.g., smart, explicit, none).
[diff]¶
- Controls whether Ansible shows differences when applying configurations.
-
This can be useful for debugging and understanding changes.
always- Show differences even when the playbook is not run in check mode.context- The number of lines of context to show around changes.ignore- Do not show differences.diff- Show a unified diff of changes.unified- Show a unified diff of changes with context lines.
[galaxy]¶
- The
[galaxy]section configures settings for Ansible Galaxy, which is a hub for sharing and downloading Ansible roles and collections. - This section can be used to specify custom Galaxy servers, caching options, and other related settings.
-
Here is an example configuration for the
[galaxy]section:server_list- Specifies the list of Galaxy servers to use.cache_dir- Specifies the directory to cache downloaded roles and collections.role_file- Specifies the path to the file containing role definitions.collection_file- Specifies the path to the file containing collection definitions.requirements_file- Specifies the path to the file containing Galaxy requirements.role_file- Specifies the path to the file containing role definitions.
[inventory]¶
- Defines options related to inventory parsing and caching.
- Inventory is a critical component of Ansible, as it defines the hosts and groups of hosts that Ansible will manage.
- The inventory can be specified in various formats, including
INIfiles,YAMLfiles, and dynamic inventory scripts. - The inventory can also be cached to improve performance.
-
Here are some commonly used settings in the
[inventory]section:enable_plugins- Specifies the inventory plugins to use.cache- If set to true, inventory caching will be enabled.cache_plugin- Specifies the inventory cache plugin to use.cache_timeout- Specifies the timeout for inventory caching in seconds.inventory_ignore_extensions- Specifies file extensions to ignore when loading inventory files.inventory_loader- Specifies the inventory loader to use.strict- If set to true, Ansible will enforce strict inventory parsing.host_key_checking- If set to true, Ansible will check SSH host keys for inventory hosts.enable_inventory_cache- If set to true, inventory caching will be enabled.inventory_cache_timeout- Specifies the timeout for inventory caching in seconds.inventory_cache_connection- Specifies the connection string for the inventory cache plugin.
[logging]¶
- Ansible does not have a dedicated
[logging]section inansible.cfg. - Instead, logging is typically configured under the
[defaults]section using thelog_pathdirective. log_pathcontrols where Ansible logs its output.- If
log_pathis set, Ansible will write logs to the specified file, where as if it is not set, or left empty, logging will be disabled. - Here is an example of how to configure logging in the
[defaults]section:
[paramiko_connection]¶
- The
[paramiko_connection]section configures settings specific to the Paramiko SSH library, an alternative to OpenSSH for SSH connections. -
Here are some commonly used settings in the
[paramiko_connection]section:pty- If set to true, a pseudo-terminal will be allocated for the connection.look_for_keys- If set to true, Paramiko will look for SSH keysbanner_timeout- Specifies the timeout for receiving the SSH banner.keepalive- If set to true, keepalive messages will be sent to
[privilege_escalation]¶
- The
[privilege_escalation]section defines settings related to privilege escalation (such assudoorbecome). -
The
becomedirective is used to enable privilege escalation. -
Here are some commonly used settings in the
[privilege_escalation]section:become- If set to true, privilege escalation will be used.become_method- Specifies the method to use for privilege escalation (e.g., sudo, su).become_user- Specifies the user to become when using privilege escalation.become_ask_pass- If set to true, Ansible will prompt for the privilege escalation password.become_flags- Specifies any additional flags to pass to the privilege escalation command.become_exe- Specifies the path to the privilege escalation executable.become_pass- Specifies the password to use for privilege escalation.
[ssh_connection]¶
- Settings for SSH connections, (timeout, control settings etc).
- ControlMaster and ControlPersist options are used for SSH multiplexing, allowing multiple SSH sessions to share a single connection.
ssh_argscan be used to pass additional options to the SSH command.pipeliningcan be enabled to reduce the number of SSH connections.-
scp_if_sshspecifies whether to useSCPfor file transfers when using SSH.
[winrm]¶
- The
[winrm]section configures settings for Windows Remote Management (WinRM) connections, used for managing Windows hosts. -
Here are some commonly used settings in the
[winrm]section:transport- Specifies the transport method to use (e.g., basic, ntlm).cert_validation- Controls certificate validation (e.g., ignore, validate).read_timeout_sec- Specifies the read timeout for WinRM connections in seconds.operation_timeout_sec- Specifies the operation timeout for WinRM connections in seconds.max_retries- Specifies the maximum number of retries for WinRM connections.retry_delay- Specifies the delay between retries for WinRM connections.
05. Auto Generate ansible.cfg¶
- You can choose to execute
ansible-config init, which will generate a sample Ansible configuration file. -
As this is the main configuration file for our demo application, it is the content of
ansible.cfgwhich we will use in this lab.# File location: $RUNTIME_FOLDER/labs-scripts/ansible.cfg. # This is the default location of the inventory file, script, or directory that Ansible will use to determine what hosts it has available to talk to. # Defines that the inventory info is in a file named “inventory”. [defaults] inventory = inventory # Specifies remote hosts, so we do not need to config them in main SSH config. [ssh_connection] transport = ssh transfer_method = scp # The location of the SSH config file. # We will create this file in our next step. ssh_args = -F ssh.config \ -o ControlMaster=auto \ -o ControlPersist=60s \ -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/root/.ssh/known_hosts
06. Create the ssh.config file¶
- Ansible operates in Linux environments using
SSHprotocol, in order to run Ansible playbooks. - By default, Ansible uses the default SSH keys, unless provided with an SSH configuration file.
- Ansible ssh.config file allows you to define custom SSH settings for connecting to remote hosts.
- In this demo we will use our own
ssh.configconfiguration file.# File location: $RUNTIME_FOLDER/labs-scripts/ssh.config # Set up the desired hosts # keep in mind that we have set up the hosts in the docker-compose Host * # Disable host key checking # Avoid asking for the key-print authenticity StrictHostKeyChecking no UserKnownHostsFile /dev/null # Enable hashing known_host file HashKnownHosts yes # IdentityFile allows to specify private keys we wish to use for authentication # Authentication = the process of authentication # We will use the auto-generated SSH keys from our Docker container # List the desired servers # The hosts are defined in the docker-compose which we created in the setup lab Host linux-server-1 HostName linux-server-1 IdentityFile /root/.ssh/linux-server-1 User root Port 22 Host linux-server-2 HostName linux-server-2 IdentityFile /root/.ssh/linux-server-2 User root Port 22 Host linux-server-3 HostName linux-server-3 IdentityFile /root/.ssh/linux-server-3 User root Port 22
07. Create the inventory file¶
- See Ansible documentation: How to build your inventory.
- An Ansible inventory file is a
configuration filethat lists and categorizes the hosts Ansible will manage. - It provides a structured way to define
hostsandgroups, enabling efficient targeting and execution of tasks on specific hosts or groups of hosts. - The simplest inventory is a single file with a list of
hostsandgroups. - The inventory is written using the
INIformat. inventorycan be written in other formats as well, such asYAMLandDynamic Inventorywhich dynamically configure the inventory with scripts.- The default location for this file is
/etc/ansible/hosts. - If
/etc/ansible/hostsdoesn’t exists, ansible will look for user specific inventory file, to be placed at$HOME/.ansible/hosts - You can specify a different inventory file at the command line using the
-i <path>inventory option when executing Ansible commands or by exporting theANSIBLE_INVENTORYenvironment variable. - Using
-i <path>inventory option takes precedence over environment variable. - The inventory configuration we will use for the labs:
# File location: $RUNTIME_FOLDER/labs-scripts/inventory # List of servers which we want ansible to connect to # The names are defined in the docker-compose [servers] linux-server-1 ansible_ssh_common_args='-o UserKnownHostsFile=/root/.ssh/known_hosts' linux-server-2 ansible_ssh_common_args='-o UserKnownHostsFile=/root/.ssh/known_hosts' linux-server-3 ansible_ssh_common_args='-o UserKnownHostsFile=/root/.ssh/known_hosts' [all:vars] # Extra "global" variables for the inventory
This inventory file is written following these rules:
- Information is described by one node per line, such as
linux-server-xx. - A node line consists of an
identifier of the node (ex. linux-server-X)and ahost variable(s) (ex. ansible_host=xxxx), to be given to the node . - You can also specify an IP address or FQDN for the
linux-server-xxpart. - You can create a group of hosts with
[group_name]. In our inventory the group name is[servers]. -
You can use any group name except
[all]and[localhost](e.g.,[webservers]or[databases]can be used as group names for servers).[all]allis a special group that points to all nodes described in the inventory.- The
[all:vars]&group variablesare defined for the groupall.- When we use a group, we can use the whole group as “hosts” for ansible.
- A magic variable, represented by
ansible_xxxx, contains special values that control Ansible’s behavior and environment information that Ansible will automatically retrieve. - Details are explained in the variables section.
08. Prepare for execution¶
- Place the files under the shared folder or simply execute the script /Labs/000-setup/02-init-ansible.sh
- Verify that the controller can execute ansible /Labs/000-setup/01-init-servers.sh
Test Ansible configuration
- Now we are ready to start play with Ansible!
09. Check Ansible configuration¶
-
The first step is to test Ansible configuration
-
Sample output
ansible [core 2.17.9] config file = /labs-scripts/ansible.cfg configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3/dist-packages/ansible ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible python version = 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] (/usr/bin/python3) jinja version = 3.1.2 libyaml = True -
We are looking for the following line:
10. Basic ansible configuration¶
- Once all is ready, lets check if the controller can connect to the servers with the Ansible
pingcommand. -
pingis anAd-HocAnsible command that we will cover later on.# Ping the servers and check that they are "alive" docker exec ansible-controller sh -c "cd /labs-scripts && ansible all -m ping" ### Output * Executing: ansible all -m ping linux-server-2 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" } linux-server-1 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" } linux-server-3 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" }