A brief introduction

Christian Claus
- Software developer at Micromata
- Current love: Spring-Boot, Ansible, Elastic-Stack, golang
- Github: github.com/chclaus
- Web: chclaus.de
Agenda
- Introduction
- Theory and demo
- Best practices
- Useful notes
- Wrap up
Introduction
Use cases
- Provisioning
- Provisioning
- Config management
- App deployment
- Continuous Delivery
- Security & Compliance
- Orchestration
see ansible.com
What it's all about
- Agentless: ssh and python
- Single point of truth
- Declarative yaml
- Templating
- Idempotency
- Encryption capabilities
- Open Source
A very brief history
- 2012: Developed by Michael DeHaan (func & Cobbler)
- 2015: Acquired by Red Hat Inc.
- September 2017: Ansible Tower was opensourced as AWX
- Today: Ansible Engine was introduced as enterprise product
More keyfacts
- 1,300+ modules
- 25,000+ Github stars
- 250+ Meetups worldwide
- 2,900+ Community contributors
Theory and demo
Describe your Infrastructure
web1, web2
db1
Describe your Infrastructure
mail.example.com
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
inventory.ini
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
dbservers:
hosts:
db1.example.com:
inventory.yml
Directory layout
.
├── ansible.cfg # global settings
├── group_vars/ # variables shared for whole group
│ ├── all.yml
│ ├── dbservers.yml
│ └── webservers.yml
├── host_vars/ # variables for specific hosts
│ ├── db1.example.com.yml
│ ├── mail.example.com.yml
│ ├── web1.example.com.yml
│ └── web2.example.com.yml
├── roles/ # shared behaviors
├── ...
├── inventory.yml # infrastructure definition
├── dbservers.yml # dbservers playbook
└── webservers.yml # webservers playbook
Ad-hoc commands
- Execute single task on specific hosts
- or even on groups
Modules
Playbooks
- An ordered set of tasks
- Declarative state definitions
- Not used for programming - just yaml!
- Self documented
Playbooks in a nutshell
---
- name: Provision webservers
hosts: webservers
gather_facts: yes
serial: 1
tasks:
- name: Ensure nginx is installed
apt:
name: nginx
state: present
update_cache: yes
- name: Ensure nginx is started and enabled to start at boot
service:
name: nginx
state: started
enabled: yes
Variables
hostname: foo.example.com
api:
base_path: /api
user: bar
password: secret
- name: Call status endpoint
get_url:
url: "https://{{ hostname }}{{ api.base_path }}/status"
dest: /var/app.status
url_username: "{{ api.username }}"
url_password: "{{ api.password }}"
https://foo.example.com/api/status
Example: Database setup
- Postgresql
- Unix-User app1, app2, ...
- Unix-User shall have one or multiple authorized ssh-keys
- Each Unix-User is also a Postgres-User
- Each Unix-User has a database with the same name
Jinja2 Templates
# {{ ansible_managed }}
# ======================== Elasticsearch Configuration =========================
cluster.name: {{ elasticsearch.cluster.name }}
node.name: {{ ansible_hostname }}
path.data: {{ elasticsearch.path.data }}
path.logs: {{ elasticsearch.path.logs }}
network.host: ["127.0.0.1", "{{ internal_network_address }}"]
http.port: {{ elasticsearch.http.port }}
discovery.zen.ping.unicast.hosts: [ "{{ groups['elasticsearch'] | map('extract', hostvars, ['internal_network_address']) | join('", "') }}"]
# Ansible managed
# ======================== Elasticsearch Configuration =========================
cluster.name: es-dev-cluster
node.name: es-dev1
path.data: /home/es/data
path.logs: /home/es/logs
network.host: ["127.0.0.1", "10.0.0.1"]
http.port: 9200
discovery.zen.ping.unicast.hosts: ["10.0.0.1", "10.0.0.2", "10.0.0.3"]
Handlers
...
tasks:
- name: Update nginx config
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
Reusable playbooks
- Import other files (include vs. import)
- Use roles for complete encapsulated functionality
- Share functionality between playbooks
- DRY-principle
- Reduces playbook complexity
Variable encryption
- Encrypt single fields
- Encrypt / Decrypt whole files
- RFC2104 style HMAC encryption
Ansible galaxy
Best practices
Setup
- Use one control node
- Add your files to VCS
- Let the directory structure fit your needs
(multiple stages, inventories, etc.)
Conventions
- Use meaningful variable names
- Use pure yaml
- Name your tasks!
- Seperate playbooks for:
- provisioning
- configuration
- deployment
- Add verbosity parameter for debug output
Complexity kills
- Keep playbooks simple
- Better to repeat than to increase abstraction level
- Don't code, think declarative
- Solve your use case, not the world's
Test your services
- Check if a service is up and running
- Check if a service responds correctly
- name: Wait until server is started
wait_for:
port: "{{ server.port }}"
delay: 10
sleep: 5
timeout: 60
- name: Check for valid response
uri:
url: http://localhost/api/status
return_content: yes
register: result
until: '"status: up" in result.content'
retries: 10
delay: 1
Useful notes
- Ansible docs - GREAT!
- Ansible best practices
- Common ansible.cfg params on Github
- Official youtube channel
- Control node via Ansible-Tower
- awesome list coming soon ;)
Wrap up
- Powerful tool for (Dev-)Ops
- Easy to learn and understand
- Self-documented and transparent
- Traceable config and system changes
Thanks :)
deck
By chclaus
deck
- 2,036