Ansible
@slueg


Advances
- do once, run everywhere
- same state everywhere
- review changes
Ansible is...
idempotent
Denoting an element of a set which is unchanged in value when multiplied or otherwise operated on by itself.
defines the state,
NOT the operation
no need to care about the previous state
(well... theoretically)
Ansible consists of...
Playbooks
Roles
Tasks
Modules
Playbooks
Roles
Tasks
Modules
Programs
Class
Functions
Operations
~
Playbook
- define which hosts to run on
- define which roles, tasks other playbooks to run
Playbook - example
- hosts: cambuildr-servers
roles:
- basic-server-setup
- setup-cambuildr
- setup-filebeat
- setup-watchmanRole
- includes one or more tasks
- independent of the host systems
- can have:
- dependencies (other roles)
- default variables
- templates
- etc.
Role - example
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
foo.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependenciesTasks
- uses one module
- can be called for multiple items
- ifs possible
Task - example 1
- name: create cambuildr app and varys subfolders
file:
path: "{{ item }}"
state: directory
owner: "{{ cambuildr_user }}"
group: "{{ cambuildr_group }}"
with_items:
- "{{ cambuildr_app_dir }}/storage"
- "{{ cambuildr_app_dir }}/releases"
- "{{ cambuildr_app_dir }}/filesystem/private"
- "{{ cambuildr_app_dir }}/filesystem/public"
- "{{ cambuildr_varys_dir }}/releases"
- "{{ cambuildr_generic_theme_dir }}/releases"Task - example 2
- name: Enable apache2 module <headers>
apache2_module:
state: present
name: headers
notify:
- restart apache2and of...
Handlers
- only called if the state is changed
- only called once at the end
- called in the order they are written
- used to restart services, etc.
Handlers - example
- name: Disable apache2 docs configuration for Apache 2.4 on Ubuntu 14.04
command: a2disconf apache2-doc
args:
removes: /etc/apache2/conf-enabled/apache2-doc.conf
when: ansible_distribution_major_version == "14"
notify:
- restart apache2- name: restart apache2
service:
name: apache2
state: restartedtask:
handler:
called at the end?
I need them NOW!
flush to the rescue
- name: flush to the rescue
meta: flush_handlersnot to forget the...
Templates
- define templates that can use variables
- useful for configuration files
- and generally all files that are touched by ansible
Templates - example
- name: set sshd_config file
template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
backup: yes
owner: root
group: root
mode: 0644
validate: '/usr/sbin/sshd -T -f %s'
notify:
- restart sshdtask:
Templates - example
###############################################################################
#
# {{ ansible_managed }}
#
#==============================================================================
# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
{% if ansible_distribution_major_version == "14" %}
HostKey /etc/ssh/ssh_host_ed25519_key
{% endif %}
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes
# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
{% if ansible_distribution_major_version == "12" %}
ServerKeyBits 768
{% else %}
ServerKeyBits 1024
{% endif %}sshd_config.j2:
hosts & variables
hosts file
- define servers with ip, hostname, etc.
- order them in groups (prod, staging, db, etc.)
variables
- server & group variables
- default variables for roles
- define variables in task
- use ansible facts
- and many more type of vars ...
variable precedence
(the last listed variables winning prioritization)
- role defaults [1]
- inventory vars [2]
- inventory group_vars
- inventory host_vars
- playbook group_vars
- playbook host_vars
- host facts
- play vars
- play vars_prompt
- play vars_files
- registered vars
- set_facts
- role and include vars
- block vars (only for tasks in block)
- task vars (only for the task)
- extra vars (always win precedence)
host/group vars
- you can define variables for each host or group
- defined in inventory
- this variables override defaults and vars in roles
host vars
---
cambuildr_base_dir: XXX
cambuildr_user: XXX
cambuildr_group: XXX
db_username: XXX
db_password: XXX
mail_server_active: XXX
watchman_active: true
watchman_db_password: XXX
inventories/hosteurope-server/host-vars/myHostName:
facts
- Ansible gathers facts everytime it runs and provides them for you
- see all facts for a host:
ansible -m setup myHostNameuse variables
- name: set bash prompt
lineinfile:
dest: ~/.bashrc
line: 'export PS1="\[\e[1;37;41m\] {{ inventory_hostname }} (\u) \[\e[0m\]:\[\e[0;34m\]\w\[\e[0m\] ⚡️ "'
state: presentuse a fact:
use variables - complex
---
# Stores the packages depending on the ubuntu version (12 or 14) with their state (absent or present)
basic_apt_packages_for_ubuntu:
"14":
- name: curl
state: present
- name: php5-curl
state: present
- name: php5-json
state: present
- name: php5-gd
state: present
- name: php5-readline
state: present
- name: php5-mysqlnd
state: present
"12":
- name: curl
state: present
- name: php5-curl
state: present
- name: php5-json
state: present
- name: php5-gd
state: present
- name: php5-mysql
state: present
define default:
use variables - complex
- name: install basic packages
apt:
name: "{{ item.name }}"
state: "{{ item.state }}"
with_items: "{{ basic_apt_packages_for_ubuntu[ansible_distribution_major_version] }}"
use defined variable, fact and loop:
top secret variables
- how to store ssh-private-keys?
- answer: ansible vault
Ansible Vault
- Encrypts variables using a master password
- master password must be specified when running playbook
- http://docs.ansible.com/ansible/playbooks_vault.html
Ansible Vault
- specify ansible vault password in vault_password_file
- tell ansible about the password file in ansible.cfg
need help?
so... how to start?
Installation
⚡️ ~ $ brew install ansiblesetup:
⚡️ ~ $ ansible --version
ansible 2.2.0.0
config file =
configured module search path = Default w/o overridesvalidate and check version:
run
⚡️ ~ $ ansible -m setup myHostName
⚡️ ~ $ ansible -m ping allrun a single module (facts and ping):
⚡️ ~ $ ansible-playbook my-playbook.ymlrun a playbook:
further reading
Ansible
By Christoph Schleifer
Ansible
- 823