Ansible
Ansible is an agentless automation system written in Python. It can be used for automating machine deployments, configuration management, or orchestrating continuous delivery.
The automation jobs are written in YAML as a series of interactions with the target hosts performed via SSH by default. Ansible requires no databases nor central runtime servers.
Installation
USE flags
USE flags for app-admin/ansible Model-driven deployment, config management, and command execution framework
Emerge
Install app-admin/ansible:
root #
emerge --ask app-admin/ansible
Additional software
- app-admin/ansible-lint - Tool for linting Ansible playbooks and roles
- app-admin/ansible-modules-hashivault - Ansible module integrating HashiCorp Vault
Configuration
Environment variables
- ANSIBLE_CONFIG
Files
- ~/ansible.cfg or ~/.ansible.cfg - Local (per user) configuration file.
- /etc/ansible.cfg - Global (system wide) configuration file.
Ansible configuration file location is resolved in the following order: ANSIBLE_CONFIG variable, ansible.cfg file in the current directory, ~/.ansible.cfg file, lastly /etc/ansible/ansible.cfg.
Since Ansible 2.12 (core), a configuration file can be generated by Ansible. To generate an example config file (a "disabled" one with all default settings, commented out):
user $
ansible-config init --disabled > .ansible.cfg
Also, to generate a more complete file by including existing plugins:
user $
ansible-config init --disabled -t all > .ansible.cfg
For previous versions, please visit Ansible GitHub page, select a branch (release), navigate to examples folder, click the ansible.cfg file, click the 'raw' button and download a copy of ansible.cfg. For example, for Ansible 2.9 please visit https://github.com/ansible/ansible/blob/stable-2.9/examples/ansible.cfg.
To show the current Ansible configuration, use:
user $
ansible-config view
[defaults]
# Basic default values:
inventory = $HOME/ansible/hosts
# Uncomment this to disable SSH key host checks
#host_key_checking = False
# Default user to use for playbooks if user is not specified
# (/usr/bin/ansible will use current user as default)
#remote_user = root
# If set, configures the path to the Vault password file as an alternative to
# specifying --vault-password-file on the command line.
ask_vault_pass = True
ansible_vault_password_file = $HOME/ansible/vault.yml
Inventory
Ansible inventory holds aliases for all managed hosts organized in groups. The default inventory file name is hosts. It is expected to reside in the ~/ansible directory.
With ansible_user and ansible_port it is possible to override the target host's default connection port (22/TCP by default) and remote user. The ansible_host variable specifies the host/IP when it differs from the inventory alias.
The first two lines explicitly set the Ansible Python interpreter for all hosts in the inventory. Ansible attempts to detect the Python interpreter [1] but setting it explicitly makes the process safer.
Example inventory describing two host groups ("servers" and "workstations") configured to use the /usr/bin/python3.7 Python interpreter:
[all:vars]
ansible_python_interpreter=/usr/bin/python3
[servers]
myserver01
myserver02 ansible_user=larry
myserver03 ansible_host=192.0.2.10
[workstations]
evapc ansible_user=larry ansible_port=9000
joepc ansible_user=larry
mypc ansible_user=larry ansible_connection=local
Authentication
By default, Ansible assumes SSH keys (leveraging ssh-agent or similar) being used to connect to the managed hosts.
It is also possible to use username and password, although this method requires encryption prior storing the credentials. Ansible provides the ansible-vault tool enabling manipulation with encrypted data.
Create an Ansible vault file for the credentials. Invoking the ansible-vault asks for a passphrase. This passphrase is used to encrypt and decrypt content of the ~/ansible/vault.yml file:
user $
ansible-vault create ~/ansible/vault.yml
The vault file contains the credentials used to authenticate to the managed hosts:
---
username: larry
password: gentoo linux rocks and I am a cow
Content of the encrypted ~/ansible/vault.yml file:
user $
less ~/ansible/vault.yml
$ANSIBLE_VAULT;1.1;AES256 36616661333864373230383539623831626231643737323662366437316233396631666530303664 3137373065663035393937393764646666613437363333350a316163653066656362636339653561 66643133313266323764386337623365353463626263343963366330333265613938346638616166 6466656332386436350a353734333265303063346139356662656532383462653534666437663539 64356335356538623339323864613136346231356130376262636237663036363738663264663864 36316531643563643633643739663464396138643732356564653531353030383539303366373565 36383963636532666665623138613834333764646534373133356665366130666338386337393736 32363139633432343039
Gentoo-specific roles
The Gentoo Ansible project, though now marked as "OBSOLETE", contains over 40 Ansible roles created specifically for Gentoo.
Using Portage via Ansible
It is possible to run portage on an Ansible managed host using the portage module in Ansible's community.general collection.
Usage
Check if Ansible can manage remote machine with given user:
user $
ansible evapc -u larry -m ping
Get info from remote machine, what can be used later in Ansible playbooks:
user $
ansible evapc -u larry -m setup
Run emerge --sync on evapc under larry via sudo:
user $
ansible evapc -s -u larry -m command -a "emerge --sync"
Option | Description |
---|---|
-u
|
Specifies the user, if absent Ansible will search in your inventory file for default user associated to the given host, if not any it will use the default specified in the /etc/ansible/ansible.cfg file, if there is no such an entry it will use the current username. |
-m
|
Specifies the module to be invoked. |
-a
|
Specifies the arguments to passed to the module. |
The ansible-doc command can be used to read module documentation. For example, to list available modules:
user $
ansible-doc -l
To print out info about the ping module:
user $
ansible-doc ping
Ad-hoc commands
Although Ansible provides means for composing and running complex configurations using Ansible playbooks, there is always a possibility to execute an one-off task.
For example, restarting all hosts in a host group named "workstations" can be performed as simply as:
user $
ansible workstations -a '/sbin/reboot'
The previous example used the default Ansible module called "command". There is also module providing shell capabilities named "shell". It can be invoked as:
user $
ansible workstations -m shell -a 'date >> /tmp/stamp.log'
Troubleshooting
Alternatives
- Puppet — a configuration management system written in Ruby.
- Rex — a configuration automation framework written in Perl known for its shallow learning curve and ease of extensibility
- Sparrow an automation framework written in Raku.
- dsh — a shell that allows parallel execution of remote commands across large numbers of servers
- Chef
- Salt
External resources
- Set of Ansible tasks to configure Gentoo-based workstations (not tested before posting link).
- Porting guides