Ansible 101

Intro

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

https://docs.ansible.com/ansible/latest/index.html

Intro

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

https://docs.ansible.com/ansible/latest/index.html

Intro

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

https://docs.ansible.com/ansible/latest/index.html

Intro

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

https://docs.ansible.com/ansible/latest/index.html

“Push model”

👩🏾 💻 local

⬇️ SSH

🖥️ Server

“Push model”

👨🏿 💻 local

⬇️ SSH ⬇️ SSH ⬇️ SSH

🖥️ 🖥️ 🖥️ Servers

“Push model” via CI

👩🏼 💻 local

⬇️ GIT

🖥️ Gitlab & Gitlab-CI

⬇️ SSH ⬇️ SSH ⬇️ SSH

🖥️ 🖥️ 🖥️ Servers

DISCLAIMER

YAML all-the-things ⚠

all_the_things.jpg

Vocabulary

Vocabulary

  • modules provided by Ansible (e.g. file, copy, apt, …)
  • 📝 Tasks (calling an Ansible module)
  • 📦 Roles defined by community or us (A packaged set of tasks)
  • 🖥️ Inventories defined by us (A list of servers and associated vars)
    • hosts file
    • group_vars/ variables
    • host_vars/ variables
  • 📦➡️🖥️ Playbook (Applying a set of roles to an inventory)

Modules

(e.g. file, copy, apt, …)

file module

file_module_doc.png

file module

Parameter Choices/Defaults Comments
path
required
  path to the file being managed. Aliases: dest, name
state Choices:
absent
directory
file ←
hard
link
touch
If directory, all intermediate subdirectories will be created if they do not exist. Since Ansible 1.7 they will be created with the supplied permissions. If file, the file will NOT be created if it does not exist; see the touch value or the copy or template module if you want that behavior. If link, the symbolic link will be created or changed. Use hard for hardlinks. If absent, directories will be recursively deleted, and files or symlinks will be unlinked. Note that absent will not cause file to fail if the path does not exist as the state did not change. If touch (new in 1.4), an empty file will be created if the path does not exist, while an existing file or directory will receive updated file access and modification times (similar to the way `touch` works from the command line).
force
bool
Choices:
no ←
yes
group  
mode  
owner  

file module

- name: Create nginx needed directories
  file:
    path: /etc/nginx/conf.d
    state: directory

Run file module

👨🏻 💻 Run a single module with

> ansible -m file --args "state=touch path=/tmp/coucou" localhost
localhost | SUCCESS => {
    "changed": true,
    "dest": "/tmp/coucou",
    "failed": false,
    "gid": 27,
    "group": "sudo",
    "mode": "0644",
    "owner": "paul",
    "size": 0,
    "state": "file",
    "uid": 1000
}

> ls -l /tmp/coucou
-rw-r--r-- 1 paul sudo 0 Aug 27 14:48 /tmp/coucou

apt module

- name: Install nginx.
  apt:
    update_cache: yes
    cache_valid_time: 86400
    name: nginx
    state: present

1850 modules available!

At the time of writing taken from https://docs.ansible.com/ansible/latest/modules/

Vocabulary

  • modules provided by Ansible (e.g. file, copy, apt, …)
  • 📝 Tasks (calling an Ansible module)
  • 📦 Roles defined by community or us (A packaged set of tasks)
  • 🖥️ Inventories defined by us (A list of servers and associated vars)
    • hosts file
    • group_vars/ variables
    • host_vars/ variables
  • 📦➡️🖥️ Playbook (Applying a set of roles to an inventory)

Roles

(A packaged set of tasks)

Community defined

vendor/
├── docker-gc
├── docker-ubuntu
├── geerlingguy.varnish
├── gitlab-runner
└── rbenv

5 directories, 0 files

👩🏼 💻 Installed with

> ansible-galaxy install --roles-path vendor/ -r requirements.yml

Defined by us

roles/
├── ...
├── common
├── docker
├── ...
├── local_setup
├── ...
├── nginx
├── ...
└── slack_bot

20 directories, 0 files

Role directory hierarchy

roles/nginx/
├── defaults/
├── vars/
├── handlers/
├── tasks/
├── files/
└── templates/

6 directories, 0 files

Role nginx tasks

roles/nginx/tasks/nginx-app.yml file

- name: remove previous conf files
  file:
    path: "{{ item }}"
    state: absent
  with_fileglob:
    - /etc/nginx/sites-enabled/www.*.conf

- name: Upload main CT nginx configuration
  template:
    src: www.conf.j2
    dest: "/etc/nginx/sites-enabled/www.{{ item.key }}.conf"
    with_dict: "{{ nginx_vhosts }}"
  notify: nginx reload

Role nginx handlers

roles/nginx/handlers/all.yml file

- name: nginx reload
  service:
    name: nginx
    state: reloaded

Role nginx defaults

roles/nginx/defaults/main.yml file

nginx_user: www-data
nginx_vhosts: {}
# ...

Role nginx templates

roles/nginx/templates/www.conf.j2 file

{% set server = item.value %}
{% set vhost = item.key %}

server {
  server_name {{ server.server_name }};
  listen {{ server.port | default(80) }};

  access_log /var/log/nginx/www-{{ vhost }}.log;
  error_log /var/log/nginx/www-{{ vhost }}-error.log;

  location / {
    proxy_pass  http://{{ server.proxy_destination }};
  }
}

Vocabulary

  • modules provided by Ansible (e.g. file, copy, apt, …)
  • 📝 Tasks (calling an Ansible module)
  • 📦 Roles defined by community or us (A packaged set of tasks)
  • 🖥️ Inventories defined by us (A list of servers and associated vars)
    • hosts file
    • group_vars/ variables
    • host_vars/ variables
  • 📦➡️🖥️ Playbook (Applying a set of roles to an inventory)

Inventories

(A list of servers and associated vars)

Our inventories

ansible> find . -name hosts
./inventories/production/hosts
./inventories/integration/hosts
./inventories/infra/hosts

Inventory example

inventories/production/
├── group_vars/
├── host_vars/
└── hosts

2 directories, 1 file

Inventory example

hosts file

[nginx]
web[1:2].prod.example.org

[app]
sa[6:9].prod.example.org

Inventory variables

group_vars/nginx/vars.yml file

nginx_vhosts:
  www.example.org:
    port: 8080
    server_name: "www.example.org example.org"
    proxy_destination: "localhost:5000"

host_vars/web1.prod.example.org/vars.yml file

private_ip: 172.16.10.1

Inventory (secret) variables

group_vars/nginx/vault.yml file

$ANSIBLE_VAULT;1.1;AES256
33326630376138613334303363306434623065383236366162616132383566386662636663666563
6133333065326439306366313532633561663266353665350a393932366364623236313330653734
34383239373434653835633131366636343736633766316532613230336132326138636165346461
3365656562336633360a636235343166366537383861643136336435343865383233376262613139
37626163316532636266636662373335343764626562376437653535303562633164313836376565
35613861346538303837653438383535663563643138313333333962383962326632323838386431
65646633646435396630623462626665326262393538613939396265333435366431633031323535
33353232656437356663

Inventory (secret) variables

👨🏻 💻 Edit vaulted variable file with

> ansible-vault edit production/group_vars/nginx/vault.yml
Vault password: *********

group_vars/nginx/vault.yml file (decrypted)

nginx_secret: MySuperSecretValue
ssl_cert: |
   -----BEGIN CERTIFICATE-----
   JLlkjjj2qjj...

Vocabulary

  • modules provided by Ansible (e.g. file, copy, apt, …)
  • 📝 Tasks (calling an Ansible module)
  • 📦 Roles defined by community or us (A packaged set of tasks)
  • 🖥️ Inventories defined by us (A list of servers and associated vars)
    • hosts file
    • group_vars/ variables
    • host_vars/ variables
  • 📦➡️🖥️ Playbook (Applying a set of roles to an inventory)

Playbooks

(Applying a set of roles to an inventory)

Our playbooks

> git ls-files *.yml
# Deploy Software
clever_deploy.yml

# Configure local system
local.yml
# Configure remote systems
app.yml
webservers.yml

# Orchestrate
restart.yml
upgrade.yml

setup.yml

# Ability to include other playbook
- include: notify_begin.yml
  when: app_name is defined

- hosts: all
  serial: [ "34%", "34%", "100%" ]
  roles:
    - role: common
    # ...
    - role: nginx
      when: "nginx_setup | default(false)"
      tags: ['nginx']
    # ...
    - role: redis
      when: "'redis' in group_names"
      tags: ['redis']
    - role: ruby
      deploy_step: 'prepare'
      when: rbenv is defined
      tags: [ 'ruby' ]
    # ...

- include: notify_end.yml
  when: app_name is defined

Running a playbook

> ansible-playbook \
  --inventory production \
  --limit web1.prod.example.org \
  --tag nginx \
  setup.yml

Vocabulary

  • modules provided by Ansible (e.g. file, copy, apt, …)
  • 📝 Tasks (calling an Ansible module)
  • 📦 Roles defined by community or us (A packaged set of tasks)
  • 🖥️ Inventories defined by us (A list of servers and associated vars)
    • hosts file
    • group_vars/ variables
    • host_vars/ variables
  • 📦➡️🖥️ Playbook (Applying a set of roles to an inventory)

Help!

Forgot which binary to use?

Ansible makefile helper

> make
app-specific-env       make app-specific-env app_name=<app> output_dir=/tmp env=integration limit=dev
console                make console # Run an ansible console
debug                  make debug host=myhost # Debug a host's variable
deploy                 make deploy app_name=<app> env=integration limit=dev # Launch an app deploy
dry-run                make dry-run [playbook=setup] [env=integration] [tag=<ansible-tag>] [limit=<ansible-host-limit>] [args=<ansiblearguments>] # Run a playbook in dry run mode
facts                  make facts group=all # Gather facts from your hosts
install                make install # Install roles dependencies
inventory-report       make inventory-report #
lint                   make lint playbook=setup # Check syntax of a playbook
list                   make list # List hosts inventory
run                    make run [playbook=setup] [env=integration] [tag=<ansible-tag>] [limit=<ansible-host-limit>] [args=<ansiblearguments>] # Run a playbook
vault                  make vault file=/tmp/vault.yml # Edit or create a vaulted file

💻 paulrbr/ansible-makefile

Thanks

Questions?

Thanks!