# Ansible
##### Arnaud Morin
## Ansible is Powerful
* orchestration
* deployment
* configuration
## Why using such tool?
* Manage a fleet of nodes
* Pet versus Cattle
* Automate deployment of software
* Continuous integration and delivery
* Reproductibility
* Configuration holding
* Make sure that the system is always in a good state
* Laziness
## Vocabulary
* Host inventory
* Tasks
* Modules
* Playbooks
* Roles
* Idempotent
## Main config file
* /etc/ansible/hosts
* /etc/ansible/ansible.cfg
## From simple host inventory...
```bash
$ cat /etc/ansible/hosts
neutron # we can use names
glance
192.168.1.81 # but also ip addresses
```
## ... to complex dynamic inventories
* pulling inventory dynamically from cloud (such as OpenStack)
* more info https://docs.ansible.com/ansible/2.5/user_guide/intro_dynamic_inventory.html#explicit-use-of-inventory-script
# Ansible command line tools
## Main commands
* ansible
* ansible-config
* ansible-console
* ansible-doc
* ansible-galaxy
* ansible-inventory
* ansible-playbook
* ansible-pull
* ansible-vault
## First ad hoc command
```bash
$ ansible all -m ping
192.168.1.81 | SUCCESS => {
"changed": false,
"ping": "pong"
}
glance | SUCCESS => {
"changed": false,
"ping": "pong"
}
neutron | SUCCESS => {
"changed": false,
"ping": "pong"
}
```
## You can also execute command only on one node ...
```bash
$ ansible 192.168.1.81 -m ping
192.168.1.81 | SUCCESS => {
"changed": false,
"ping": "pong"
}
```
## ... or execute shell command on all nodes
```bash
$ ansible all -m shell -a "/bin/echo hello"
192.168.1.81 | CHANGED | rc=0 >>
hello
neutron | CHANGED | rc=0 >>
hello
glance | CHANGED | rc=0 >>
hello
```
## ansible-console
run interactive ah hoc commands against a chosen inventory
```bash
$ ansible-console all
Welcome to the ansible console.
Type help or ? to list commands.
root@all (3)[f:5]$ uname -r
neutron | CHANGED | rc=0 >>
4.4.0-138-generic
glance | CHANGED | rc=0 >>
4.4.0-138-generic
192.168.1.81 | CHANGED | rc=0 >>
4.4.0-138-generic
root@all (3)[f:5]$
```
## ansible-galaxy
Search/download role from ansible galaxy (like a store)
```bash
$ ansible-galaxy search asterisk
...
```
```bash
$ ansible-galaxy install dgnest.asterisk
- downloading role 'asterisk', owned by dgnest
- downloading role from https://github.com/dgnest/ansible-role-asterisk/archive/0.0.5.tar.gz
- extracting dgnest.asterisk to /root/.ansible/roles/dgnest.asterisk
- dgnest.asterisk (0.0.5) was installed successfully
```
## ansible-inventory
used to display or dump the configured inventory as Ansible sees it
```bash
$ ansible-inventory --yaml --list
all:
children:
ungrouped:
hosts:
192.168.1.81: {}
glance: {}
neutron: {}
```
## ansible-playbook
the tool to run Ansible playbooks, which are a configuration and multinode deployment system
```bash
$ ansible-playbook play.yml --list-tasks
playbook: play.yml
play #1 (all): all TAGS: []
tasks:
install cowsay and steam locomotive TAGS: []
```
## ansible-pull
pulls playbooks from a VCS repo and executes them for the local host
## ansible-vault
encryption/decryption utility for Ansible data files
## Playbooks
* YAML files
* playbooks are composed of one or more **plays**
* plays are composed of **roles** and **tasks**
* roles are composed of **tasks**
* tasks are based on **modules** to perform specific actions on nodes
## Playbooks
* Applied to a group af node
* Allow orchestration between nodes
## Example
```yaml
---
- hosts: localhost # Apply only to localhost
tasks:
- name: install cowsay and sl # Use apt module
apt:
name: ['cowsay', 'sl'] # Ensure that those packages
state: latest # are installed
```
## ansible-playbook play.yml

## Ansible roles
Roles are ways of automatically do tasks that are related (such as installing and configuring a software)
They are also nice for:
* sharing with other (or use others roles - see ansible-galaxy)
* reuse (you can use same roles in multiples plays)
## Example
```bash
$ cat /etc/ansible/playbooks/play.yml
---
- hosts: localhost
roles:
- useless
```
```bash
$ cat /etc/ansible/roles/useless/tasks/main.yml
---
- name: install cowsay and steam locomotive
apt:
name: ['cowsay', 'sl']
state: latest
```
## Definition
Variables can be defined in
* inventory
* playbooks
* roles
* on CLI
* retrieved from facts
## Defining a variable
General yaml syntax
```yaml
foo:
field1: one
field2: two
```
Accessing it
```yaml
foo.field1
# or
foo['field1']
```
## Example in a playbook
In a playbook
```yaml
- hosts: webservers
vars:
http_port: 80
# or from external file
vars_files:
- /vars/external_vars.yml
```
From CLI
```bash
ansible-playbook bla.yml --extra-vars "foo=bar truc=bidule"
```
## Using variables with Jinja2
Ansible is using Jinja2 as templating system.
Example:
```yaml
Foo value is {{ foo }}
```
## Facts: special variables
Ansible is collectings some facts when connecting to the nodes.
Those facts are then available as variables, like any other.
Example:
```yaml
My hostname is {{ ansible_facts['nodename'] }}
```
## Facts: special variables
See all gathered facts:
```bash
ansible hostname -m setup
```
## Registering variables
You can register variables from result of a task.
Example
```yaml
- hosts: web_servers
tasks:
- shell: /usr/bin/foo
register: foo_result
ignore_errors: True
- shell: /usr/bin/bar
when: foo_result.rc == 5
```
# Conditionals, loops and blocks
## The when statement
Use very often to execute tasks only if required
Example
```yaml
tasks:
- name: "shut down Debian flavored systems"
command: /sbin/shutdown -t now
when: ansible_facts['os_family'] == "Debian"
```
## Loops
Sometime, you want to execute the same task multiple times with differents values
Example
```yaml
tasks:
- name: add several users
user:
name: "{{ item }}"
state: present
groups: "wheel"
loop:
- testuser1
- testuser2
```
## Blocks
Blocks allow for logical grouping of tasks and in play error handling (try/catch)
Example
```yaml
tasks:
- name: Handle the error
block:
- debug:
msg: 'I execute normally'
- name: i force a failure
command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- debug:
msg: 'I caught an error, can do stuff here to fix it, :-)'
```
# More info
https://docs.ansible.com/ansible/latest/