Ansible

Speaker: Apua

Date: 2014.12.25

Location: CLBC

Activity: Taipei.py

automation engine

  • cloud provisioning
  • configuration management
  • application deployment
  • intra-service orchestration
  • etc.

philosophy

  • low learning curve
    for adminstrators, developers,
    and IT managers
  • secure
  • highly reliable
  • agentless
  • goal-oriented but scripted
  • batteries included

about author

Name: Michael DeHaan
Projects:
  - Cobbler:
      a Linux provisioning server
  - FUNC:
      role: co-author
      name: Fedora Unified Network Controller
      desc: >
            a framework for remote 
            administration of Linux

Ad-hoc

command

# ansible $inventory -m $module -a $arguments
ansible all -m uri -a 'url=http://8.8.8.8'

module

# ansible-doc $module
ansible-doc uri
ansible-doc --list

features

# command (default)
ansible myhosts -m shell -a 'echo $TERM'
# gathering features
ansible myhosts -m setup
# change user and sudo
ansible myhosts -a "/usr/bin/foo" -u username --sudo
# file transfer
ansible myhosts atlanta -m copy -a \
  "src=/etc/hosts dest=/tmp/hosts"

parallel and async.

# polling
ansible hosts -a "$prog" -f 10 -B 3600 -P 10

# check by asyc_status
ansible hosts -a "$prog" -f 10 -B 3600 &
ansible hosts -m sync_status -a "jid=123456789"

Inventory

INI format

[myhosts]
10.30.1.[2:253]
nuclear.apua.idv.tw  ansible_ssh_port=32768
blog.apua.idv.tw     http_port=8000
production           ansible_ssh_host=10.30.1.1

group hosts

[test_servers]
10.30.1.[2:253]

[apua_domain]
nuclear.apua.idv.tw
blog.apua.idv.tw

[own:children]
test_servers
apua_domain

group vars

[myhosts]
blog.apua.idv.tw
nuclear[01:10].apua.idv.tw

[myhosts:vars]
ntp_server=time.stdtime.gov.tw

vars files

/etc/ansible/group_vars/own/ntp_settings
/etc/ansible/group_vars/test_servers/db_settings
/etc/ansible/host_vars/production

dynamic inventory

# ``./ec2.py`` would print out JSON format
ansible -i ec2.py -u ubuntu us-east-1d -m ping

patterns

# :  := or
# :& := in
# :! := not in
webservers:dbservers:&staging:!phoenix

Playbook

YAML format

---
- hosts: 10.30.1.68
  vars:
    http_port: 80
    max_clients: 200
  tasks:
  - name: debug var
    debug: vars=http_port

output

PLAY [10.30.1.68] *************************************************************

GATHERING FACTS ***************************************************************
<10.30.1.68> REMOTE_MODULE setup
ok: [10.30.1.68]

TASK: [debug var] *************************************************************
ok: [10.30.1.68] => {
    "msg": "Hello world!"
}

PLAY RECAP ********************************************************************
10.30.1.68                 : ok=2    changed=0    unreachable=0    failed=0

variable and condition

tasks:
    - command: echo {{ item }}
      with_items: [ 0, 2, 4, 6, 8, 10 ]
      when: item > 5

handler

tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache

roles

ansible-galaxy init apua_role -p ./roles

roles
└──apua_role/
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    └── vars
        └── main.yml

Check mode

lifecycle

  1. embeded test
  2. deploy stage
  3. integration test against stage
  4. production

prompt

---
- hosts: all
  vars_prompt:
    - name: "release_version"
      prompt: "Product release version"
      default: "1.0"

rolling update

  • `serial:n`
    run n hosts every time
  • `delegate_to: host`
    delegate task to specify host
  • `connection`
    use specify connection
  • `tag`
    specify the step

check mode

  • `--check`
    dry run
  • `--diff`
    report diff if changed
  • `--limit`
    select server
  • `--start-at`
    select started task
  • `--step`
    execute interactively

error handling

  • `ignore_errors`
  • `when`
  • `failed_when`
  • `changed_when`

Odds and Ends

SSH connection

  • paramiko
  • pipelining and accelerated mode

poll mode

Usage: ansible-pull [options] [playbook.yml]

config

  1. ANSIBLE_CONFIG (an environment variable)
  2. ansible.cfg (in the current directory)
  3. .ansible.cfg (in the home directory)
  4. /etc/ansible/ansible.cfg

lookup

- hosts: all
  vars:
      contents:
          "{{ lookup('file', '/etc/foo.txt') }}"

Windows support

  • controller installation only support Unix-like now
  • so does Salt

encryption

ansible-vault create xxx.yml
ansible-vault edit xxx.yml
ansible-playbook xxx.yml --ask-vault-pass
ansible-playbook xxx.yml --vault-password-file ~/.print_pass.py

Ansible Tower

Comparison

language

CFEngine: DSL
Puppet: DSL, Ruby
Chef: DSL
Salt: YAML, Jinja2, DSL
​Ansible: YAML, Jinja2 (-), any lang (+)

history

CFEngine: 1993
Bcfg2:    2005
Puppet:   2005
Chef:     2009
Salt:     2011
Ansible:  2012
Made with Slides.com