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.
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.
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.
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.
👩🏾 💻 local
⬇️ SSH
🖥️ Server
👨🏿 💻 local
⬇️ SSH ⬇️ SSH ⬇️ SSH
🖥️ 🖥️ 🖥️ Servers
👩🏼 💻 local
⬇️ GIT
🖥️ Gitlab & Gitlab-CI
⬇️ SSH ⬇️ SSH ⬇️ SSH
🖥️ 🖥️ 🖥️ Servers
⚠ YAML all-the-things ⚠
file, copy, apt, …)hosts file group_vars/ variables host_vars/ variables 
(e.g. file, copy, apt, …)
file module
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
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
At the time of writing taken from https://docs.ansible.com/ansible/latest/modules/
file, copy, apt, …)hosts file group_vars/ variables host_vars/ variables (A packaged set of tasks)
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
roles/
├── ...
├── common
├── docker
├── ...
├── local_setup
├── ...
├── nginx
├── ...
└── slack_bot
20 directories, 0 files
roles/nginx/
├── defaults/
├── vars/
├── handlers/
├── tasks/
├── files/
└── templates/
6 directories, 0 files
 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
 roles/nginx/handlers/all.yml file 
- name: nginx reload
  service:
    name: nginx
    state: reloaded
 roles/nginx/defaults/main.yml file 
nginx_user: www-data
nginx_vhosts: {}
# ...
 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 }};
  }
}
file, copy, apt, …)hosts file group_vars/ variables host_vars/ variables (A list of servers and associated vars)
ansible> find . -name hosts
./inventories/production/hosts
./inventories/integration/hosts
./inventories/infra/hosts
inventories/production/
├── group_vars/
├── host_vars/
└── hosts
2 directories, 1 file
hosts file
[nginx]
web[1:2].prod.example.org
[app]
sa[6:9].prod.example.org
 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
 group_vars/nginx/vault.yml file 
$ANSIBLE_VAULT;1.1;AES256
33326630376138613334303363306434623065383236366162616132383566386662636663666563
6133333065326439306366313532633561663266353665350a393932366364623236313330653734
34383239373434653835633131366636343736633766316532613230336132326138636165346461
3365656562336633360a636235343166366537383861643136336435343865383233376262613139
37626163316532636266636662373335343764626562376437653535303562633164313836376565
35613861346538303837653438383535663563643138313333333962383962326632323838386431
65646633646435396630623462626665326262393538613939396265333435366431633031323535
33353232656437356663
👨🏻 💻 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...
file, copy, apt, …)hosts file group_vars/ variables host_vars/ variables (Applying a set of roles to an inventory)
> 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
> ansible-playbook \
  --inventory production \
  --limit web1.prod.example.org \
  --tag nginx \
  setup.yml
file, copy, apt, …)hosts file group_vars/ variables host_vars/ variables Forgot which binary to use?
> 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
Questions?
— Thanks!