Configuration Management

Development Principles

using Ansible examples

Created by Will Thames / @willthames

About this presentation

This presentation is available on Github Pages at:
http://willthames.github.io/devops-bris-ansible/

All code samples are included in the same repo, under examples

To save you having to remember that, I've published the info at http://willthames.github.io

About me

I build the future!

  • 18 months with Suncorp
  • 8 years before that at Betfair in the UK

† see Devops, what's missing, what's next

About Ansible

  • Been around 18 months (first commit 23/02/2012)
  • Daemon-less orchestration and config management tool - runs over ssh and uses existing privileges
  • Requires python (rather than ruby)
  • Recently raised US$6m in funding for their ansibleworks business, which offers enterprise features
  • Doesn't need root! (except to do things that need root)

About Ansible

  • Assumes homogeneity (little abstraction of resources like package installation etc.). This is realistic within corporations, but reduces reuse
  • Task driven rather than convergence driven - much less declarative than chef, let alone puppet

And vagrant...

  • Vagrant is a tool to programatically manage virtual machines
  • The demos in this presentation rely upon Vagrant.
  • Vagrant supports Ansible as a provisioning method
Vagrant.configure(2) do |config|

  config.vm.define :shop do |shop|
    shop.vm.box = "centos64-64"
    shop.vm.network :private_network, ip: "192.168.0.2"
    shop.vm.network :forwarded_port, guest: 22, host: 2202
  end

  config.vm.define :acct do |acct|
    acct.vm.box = "centos64-64"
    acct.vm.network :private_network, ip: "192.168.0.3"
    acct.vm.network :forwarded_port, guest: 22, host: 2203
  end

  config.vm.provision :ansible do |ansible|
    ansible.playbook = "provisioning/playbook.yml"
    ansible.inventory_file = "provisioning/ansible_hosts"
    ansible.sudo = true
  end
end

          
---
- hosts: vagrant

  tasks:
  - name: add dummy host in /etc/hosts
    action: lineinfile state=present regexp=repo.dev.example \
                line='192.168.0.1      repo.dev.example'

  - name: ensure /usr/local is writable by admin group
    action: file state=directory group=admin mode=775 \
                dest=/usr/local

Getting started with Ansible

Install from OS package (yum, apt-get etc) or

git clone http://github.com/ansible/ansible
pip install paramiko PyYAML jinja2
mkdir ~/.ansible
source ansible/hacking/env-setup -q

Setup Ansible config

cat > ~/.ansible/config << EOT
[defaults]
hostfile = ~/.ansible/hosts
library = ~/src/ansible/library
EOT

Talk to a target host

  • ssh-keygen (use a strong passphrase)
  • ssh-add (so you don't have to type your passphrase every connection)
  • ssh-copy-id $target (or OS equivalent)
ansible -m command -a date web
127.0.0.2 | success | rc=0 >>
Sun Aug 25 14:41:08 EST 2013

This presentation is about Ansible

The principles are applicable to:

Chef, Puppet, Salt, Cfengine

etc...

Example environment

We'll use this environment for discussion purposes

The naive approaches

  • Snowflake servers!
  • ssh in a for loop running a bash script on each server
  • version controlled per-server configuration

Configuration management

to the rescue?

DEMO!!!

What can we improve?

  • All that copy and paste! Refactoring...
  • Modular playbooks
  • Hierarchical configuration
  • Repeatability
  • Security

Modularity

Most configuration management frameworks have a way to have playbooks that include other playbooks.

Ansible recently introduced Role Dependencies, so that playbooks can include roles which can include other roles

This means that e.g. installing java or logstash can be separated out to roles

Hierarchical configuration

Configuration is typically multi-dimensional:

  • environment specific
  • application specific

Also, there are typically groupings of targets - e.g. dev environments and prod-like environments

Hierarchical configuration

Here there are likely elements common to the dev environment such as mail gateways, log shipping destinations, log level.

There are also likely elements common to application type, such as files to log ship, JVM versions etc.

Repeatability

There are two key elements to repeatability:

  • invariance: The system should not change between runs of the same playbook, no matter how long apart
  • idempotency: Running the same playbook twice should have no additional effects

This means that playbooks that install the latest version of an artifact, or checkout HEAD from version control are not repeatable.

Checks should be made when adding things - e.g. lines to a config file to ensure that it doesn't happen again on a second run

Version control is not just for

application code

It's probably obvious that you should commit your playbooks to source control.

But you also need to manage versions. So that you can run playbook v1.2 against dev, v1.1 against test and v1.0 against prod as improvements flow through the pipeline.

There are many ways to achieve this, but cheap branching (typically DVCS) is an easy way - whether that's a dev branch or just pointing dev at the 1.2 branch.

Security

What you don't want is your production database passwords, or Amazon private keys, or any other sensitive data written in plain text in source control.

Typically a solution is for the target nodes to have decryption keys and then the configuration management software decrypting it as it writes the config file

ansible-vault is still a work in progress.

Software development practices

Testing

Unlike chef-cucumber and rspec-puppet, there are no common frameworks yet available. Using vagrant to test your changes in a throwaway VM will work in some cases.

Static Analysis

Again, puppet has puppet-lint, chef has food-critic.

Announcing ansible-lint!!

I've created an extensible lint for ansible at
http://github.com/willthames/ansible-lint

$ bin/ansible-lint examples/example.yml
[ANSIBLE0001] Old style (${var}) brackets
examples/example.yml:10
    action: command echo ${oldskool}

[ANSIBLE0004] Checkouts must contain explicit version
examples/example.yml:22
    action: git a=b c=d

...

What about the devops?

  • Developers can work with ops on playbooks that work in dev environments through to production - shared ownership
  • Operations can provide playbooks that setup and configure monitoring, log shipping - all devs have to do is set the right variables
  • Depending on environment (e.g. devs typically won't have root privileges, ops won't know how best to deploy a particular application) collaboration will be essential - talk to each other!

What about the devops...

Dev and Ops relaxed and happy

Conclusions

Room for improvement

  • Testing framework
  • Sensitive data management
  • Community playbooks - or even the abstractions to allow reuse

Conclusions

Where Ansible excels

  • Trivial to get going
  • Great for orchestration (even if you use chef or puppet, it's nice to have something to tell servers to update themselves!)
  • Improvements to core are happening rapidly - more modules, more modularity

Useful links

Questions?

Photo credits: Peta Thames