Ansible

Warning

Use at your own risk!!! Commands, procedures etc. described in this page worked for me. That does not mean they will automatically work for you.

Table of contents (sitemap)

Full table of contents

Ansible is a kick ass open-source automation engine that automates a lot of your everyday admin tasks. Its built using python, ssh, sudo and a number of other techniques. So these need to work correctly!

Since Ansible is built on the before mentioned techniques bootstrapping it to a system is a chicken and egg thing. Basically you need to provide a use with sudo rights to get it working.

Ansible expresses configurations, deployment, and orchestration in Playbooks. Playbooks are yaml files with a scenario specific instructions.

Ansible provides a number of internal variables and Facts used in Playbooks. Facts can be locally extended to provide needed information to the Playbooks.

Playbooks can be combined into roles. These roles easily created downloaded from Ansible Galaxy. Roles are referenced in Playbooks.

Hosts are defined in an inventory and the playbooks specify the host groups where they apply to.

The ansible config can specify the location of the inventory.

documentation

Most of the needed documentation can be found on the command line:

  • ansible-doc -l: lists all the modules available to you
  • ansible-doc <module>: extensive documentation on your module

Overall documentation can be found on Ansible Docs.

inventory

The inventory can be:

  • a file
  • a directory
  • an executable

The inventory location is mentioned in the ansible.cfg file with the inventory keyword:

[defaults]
inventory      = /etc/ansible/hosts

format of an inventory file

The inventory:

  • file is an ini style file with group names as section headers.
  • directory is a directory with a collection of such
  • executable outputs a json type output

The inventory accepts regular expressions, ranges are mentioned as [0:9] not as [0-9] and IP address format does not accept normal like 10.0.0.0/24.

Example #1:

[group1]
server1 ansible_connection=local
server2

[group2]
server3
server4
192.168.[0:1].[128:250]

[group3:children]
group1
group2

Warning

In the inventory directory the files and executables are sourced in order. This means if a groups children aren’t mentioned yet the run will fail.

reference

commands

Execute a uname -r on serverx:

ansible serverx -m command -a 'uname -r'

Execute a uname -r on serverx short:

ansible serverx -a 'uname -r'

List hosts in inventory:

ansible serverx --list-hosts

ansible all --list-hosts

ansible '*' --list-hosts

List all hosts in inventory but not the stinky group:

ansible 'all:!stinky' --list-hostS

Check the format of a playbook:

ansible-playbook --syntax-check someplay.yml

reference

Note

var files vs include_vars

environment

  • ANSIBLE_KEEP_REMOTE_FILES=1, do not remove the temporary files
  • ANSIBLE_CONFIG=<filename>, alternative path in ansible.cfg

playbooks

  • start with three dashes
  • add name where you can for clarity
  • a playbook can contain multiple plays

reference

variables

Tip

avoid using variables in inventory

Example in a playbooks:

- hosts: all
  vars:
    foo: bar

Example in a playbooks for external file:

- hosts: all
  vars_files:
    - vars/common.yml

Example in inventory:

[lala]
server1

[lala:vars]
user=joe
  • the directories group_vars and host_vars in the same directory as the inventory file or directory are implicitly sourced.
  • bracket notation is preffered above dot notation to avoid confusion to methods or attributes.
animal:
  pike:
    class: fish
    legs: no
  wolf:
    class: canine
    legs: yes

animal.pike.class --> 'fish'

better: animal['pike']['class']

facts

Example:

---
- name:
  gather_facts: no
...

Don’t disable unless you have performance issues.

# ansible 10.0.0.90 -m setup -a 'filter=ansible_fqdn'
10.0.0.90 | SUCCESS => {
    "ansible_facts": {
        "ansible_fqdn": "heimdall.doubtfull.snd"
    },
    "changed": false
}
# cat /etc/ansible/facts.d/system.fact
[system_responsiblity]
gateway = true
username@hermod/centos 11:24:51 [~/ansible]
# ansible 10.0.0.170 -m setup -a 'filter=ansible_local'
10.0.0.170 | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "system": {
                "system_responsiblity": {
                    "gateway": "true"
                }
            }
        }
    },
    "changed": false
}
student@loki dev-vars-facts]$ ansible webserver -m setup -a 'filter=ansible_user*'
servera.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "ansible_user_dir": "/root",
        "ansible_user_gecos": "root",
        "ansible_user_gid": 0,
        "ansible_user_id": "root",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 0,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64"
    },
    "changed": false
}

roles

Example layout:

example
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

modules

get_url:

- name: download foo.conf
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    mode: 0440

stat:

# Obtain the stats of /etc/foo.conf, and check that the file still belongs
# to 'root'. Fail otherwise.
- stat: path=/etc/foo.conf
  register: st
- fail: msg="Whoops! file ownership has changed"
  when: st.stat.pw_name != 'root'
  • stat
  • lineinfile
  • replace
  • command

TODO

Indices and tables