Ansible: Basic Usage
Note
This page contains {{ jinja2_style_variable_syntax }}
in example commands or configs. Replace them with the appropriate values when using the code or values in question.
Basic Usage
Set up an inventory file
At its most basic, an inventory file contains a list of hostnames, with one per line. If no inventory file is specified, Ansible defaults to /etc/ansible/hosts
You can also create host groups by listing them under a group name specified within square brackets.
You can also set per-host or per-group variables that can be referenced in Jinja2 templates (see below). Some variables, like ansible_user
, are used to change ansible's default behavior. In the following example, Ansible will attempt to connect to servers listed under [groupa]
as ansible_setup_user
, while it will attempt to connect to servers listed under [groupb]
as administator
[groupa]
host1.a.example.com color=red location=philadelphia
host2.a.example.com color=green location=burlington
[groupb]
host1.b.example.com color=blue location=toronto
[groupa:vars]
ansible_user=ansible_setup_user
[groupb:vars]
ansible_user=administrator
Run a command on all hosts in inventory
ansible all -a {{ COMMAND }} -i {{ INVENTORY_FILE }}
Run a module on all hosts in inventory
ansible all -m {{ MODULE }} -i {{ INVENTORY_FILE }}
Group Headers
You can group hosts with Group Headers, and specifically target them by Header:
In inventory.txt:
[grouped-hosts]
grouped-host-0
grouped-host-1
ansible grouped-hosts -m {{ MODULE }} -i {{ INVENTORY_FILE }}
Playbooks
Playbooks are YAML files that define a more complex processes than running individual commands or modules.Since this is just a syntax and filetype-detection plugin there is nothing to configure, once a file has been identified as a Jinja file it will be highlighted appropriately. Any file with the extension .jinja will be recognised as a Jinja file.
Here is an example playbook, which ensures that Apache is up-to-date and running on a RHEL/CentOS system (copied from middlewareinventory.com)
---
- name: Playbook
hosts: webservers
become: yes
become_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: ensure apache is running
service:
name: httpd
state: started
Running an Ansible Playbook
ansible-playbook -i {{ INVENTORY_FILE }} {{ PLAYBOOK_FILE }}
Templating
Ansible playbooks can use Jinja2 templates to dynamically generate configuration files they reference, or even parts of themselves.
For instance, I have a simple playbook I use to determine how a given Linux host's distro is identified by Ansible, helping me figure out how to modify behavior for different distros. It has the following contents
---
- name: Get Server Distribution
hosts: all
gather_facts: true
tasks:
- name: Ansible fact OS
debug:
msg: "Distro: {{ ansible_distribution }} (like {{ ansible_distribution_file_variety }}); Distro Family: {{ ansible_os_family }}"
See the official docs for details.
Conditionals
Conditional execution of a task can help create a more portable playbook. For example, I have a playbook called guest-init.playbook.yml
that I use when setting up new Linux VMs. The following is an excerpt of that file that illustrates the usage of conditionals
- name: Update apt cache on Debian-like systems
ansible.builtin.apt:
update_cache: true
when: ansible_facts['os_family'] == "Debian"
- name: Enable the Extra Packages for Enterprise Linux repository on RHEL-like systems
ansible.builtin.dnf:
name: epel-release
state: latest
when: ansible_facts['os_family'] == "RedHat" and ansible_facts['distribution'] != "Fedora"
- name: Upgrade installed software (sensible distros)
ansible.builtin.package:
name: '*'
state: latest
when: ansible_facts['os_family'] != "Archlinux"
- name: Upgrade installed software btw
community.general.pacman:
update_cache: yes
upgrade: yes
when: ansible_facts['os_family'] == 'Archlinux'
With the conditionals, I have managed to do the following:
* On Debian, Ubuntu, and related systems, update the apt cache.
* On RedHat-like systems, other than Fedora, enable EPEL
* On non-Arch systems, update installed packages
* On Arch systems, update installed packages. This is done separately because ansible.builtin.package
does not work with Arch's pacman
package manager.
Galaxy
Quoting the Galaxy Documentation homepage (and actually using block quotes as intended for once):
About Galaxy
Galaxy is a hub for finding and sharing Ansible content.
Use Galaxy to jump-start your automation project with great content from the Ansible community. Galaxy provides pre-packaged units of work known to Ansible as Roles, and new in Galaxy 3.2, Collections.
Installing Roles
Default path (requires root)
ansible-galaxy install {{ role_id }}
Alternate path (does not require root)
ansible-galaxy install --roles-path {{ install_path }} {{ role_id }}