Post on 03-Aug-2015
TITLE
6 Ways Ansible Can Improve Your Workflow
Owen Zanzal@AgentO3April 2015
TITLE
Questions?@VividCortex
2
TITLE
Ansible at VividCortex
3
• 1.5 years• Simple• Powerful• Versatile• Easy to learn
TITLE
How we use Ansible
4
• Configuration Management• Provisioning• Deployment• Builds• Monitoring• Debugging
TITLE
0 to Ansible
5
TITLE6
• Inventory• Playbook• Hosts• Vars• Tasks• Roles• Tags
Ansible Terminology
TITLE7
[server_group]server1server2 server3
Inventory
TITLE8
[server_group]server1server2 server3
Inventory
TITLE9
- hosts: server_group tags: [‘say-hello’] vars:
say: Hello tasks:
- name: Say hello shell: echo {{say}} roles:
- say-hello
Playbook
TITLE10
- hosts: server_group tags: [‘say-hello’] vars:
say: Hello tasks:
- name: Say hello shell: echo {{say}} roles:
- say-hello
Hosts
TITLE11
- hosts: server_group tags: [‘say-hello’] vars:
say: Hello tasks:
- name: Say hello shell: echo {{say}} roles:
- say-hello
Vars
TITLE12
- hosts: server_group tags: [‘say-hello’] vars:
say: Hello tasks:
- name: Say hello shell: echo {{say}} roles:
- say-hello
Tasks
TITLE13
- hosts: server_group tags: [‘say-hello’] vars:
say: Hello tasks:
- name: Say hello shell: echo {{say}} roles:
- say-hello
Roles
TITLE14
- hosts: server_group tags: [‘say-hello’] vars:
say: Hello tasks:
- name: Say hello shell: echo {{say}} roles:
- say-hello
Tags
TITLE15
ansible-playbook -i inventory \playbooks.yml \-t say-hello \-e ‘say=bye’
CLI
TITLE16
ansible-playbook -i inventory \playbooks.yml \-t say-hello \-e ‘say=bye’
CLI
TITLE17
ansible-playbook -i inventory \playbooks.yml \-t say-hello \-e ‘say=bye’
CLI
TITLE18
ansible-playbook -i inventory \playbooks.yml \-t say-hello \-e ‘say=bye’
CLI
TITLE19
ansible-playbook -i inventory \playbooks.yml \-t say-hello \-e ‘say=bye’
CLI
TITLE
#1 Configuration Management
20
TITLE21
• Chef
• Puppet
• Salt Stack
Similar To
TITLE22
• Install packages
• Manage application state
• Configure files
Common Tasks
TITLE23
- hosts: webservers … tasks:
- name: Install apache on Ubuntu apt: name=apache2 state=present when: ansible_distribution == “Ubuntu”
- name: Install apache on CentOs yum: name=httpd state=present when: ansible_distribution == “CentOs”
Install Packages
TITLE24
- hosts: webservers … tasks:
- name: Install apache on Ubuntu apt: name=apache2 state=present when: ansible_distribution == “Ubuntu”
- name: Install apache on CentOs yum: name=httpd state=present when: ansible_distribution == “CentOs”
Install Packages
TITLE25
- hosts: webservers … tasks:
- name: Install apache on Ubuntu apt: name=apache2 state=present when: ansible_distribution == “Ubuntu”
- name: Install apache on CentOs yum: name=httpd state=present when: ansible_distribution == “CentOs”
Install Packages
TITLE26
- hosts: webservers … tasks:
- name: Install apache on Ubuntu apt: name=apache2 state=present when: ansible_distribution == “Ubuntu”
- name: Install apache on CentOs yum: name=httpd state=present when: ansible_distribution == “CentOs”
Install Packages
TITLE27
- hosts: webservers … tasks:
- name: Install apache on Ubuntu apt: name=apache2 state=present when: ansible_distribution == “Ubuntu”
- name: Install apache on CentOs yum: name=httpd state=present when: ansible_distribution == “CentOs”
Install Packages
TITLE28
...
- name: Start apache on Ubuntu
service: name=apache2 state=started
enabled=yes
when: ansible_distribution == “Ubuntu”
- name: start apache on CentOs
yum: name=httpd state=started enabled=yes
when: ansible_distribution == “CentOs”
Application State
TITLE29
...
- name: Start apache on Ubuntu
service: name=apache2 state=started
enabled=yes
when: ansible_distribution == “Ubuntu”
- name: start apache on CentOs
yum: name=httpd state=started enabled=yes
when: ansible_distribution == “CentOs”
Application State
TITLE30
...
- name: Start apache on Ubuntu
service: name=apache2 state=started
enabled=yes
when: ansible_distribution == “Ubuntu”
- name: start apache on CentOs
yum: name=httpd state=started enabled=yes
when: ansible_distribution == “CentOs”
Application State
TITLE31
... - name: Copy php.ini to webservers copy: src=files/php.ini dest=/etc/php.ini- name: Copy vhost to webservers
template: > src=vhost.conf.j2dest=/etc/httpd/conf.d/vhost.conf
Configure Files
TITLE
#2 Provisioning
32
TITLE33
• Terraform
• Cloud Formation
Similar To
TITLE34
• Bring up a new instance
• Gather facts
• Wait for it to boot
Tasks
TITLE35
topology: - name: db count: 1 user: root type: c3.large keypair: keyname group: sg-8565309 image: "{{datacenter_images.centos}}" subnet: subnet-1776c...
Create instance
TITLE36
hosts: localhost...- name: Create ec2 boxes ec2: count_tag: Name: "{{env_key}}-{{item.name}}" exact_count: "{{item.count}}" key_name: "{{item.keypair}}" group_id: "{{item.group}}" instance_type: "{{item.type}}"
Create instance
TITLE37
hosts: localhost...- name: Create ec2 boxes ec2: count_tag: Name: "{{env_key}}-{{item.name}}" exact_count: "{{item.count}}" key_name: "{{item.keypair}}" group_id: "{{item.group}}" instance_type: "{{item.type}}"
Create instance
TITLE38
... image: "{{item.image}}" vpc_subnet_id: "{{item.subnet}}" wait: yes region: "{{item.region}}" instance_tags: Name: "{{env_key}}-{{item.name}}" volumes: "{{item.volumes}}" register: ec2 with_items: topology
Create instance
TITLE39
... image: "{{item.image}}" vpc_subnet_id: "{{item.subnet}}" wait: yes region: "{{item.region}}" instance_tags: Name: "{{env_key}}-{{item.name}}" volumes: "{{item.volumes}}" register: ec2 with_items: topology
Gather facts
TITLE40
... - name: Add new instance to host group add_host: > hostname={{env}}-{{server_name}} ansible_ssh_host={{ item.private_ip }} groupname=launched ansible_ssh_user={{ server_config.user }} when: ec2.changed with_items: ec2.instances
Gather facts
TITLE41
... - name: Add new instance to host group add_host: > hostname={{env}}-{{server_name}} ansible_ssh_host={{ item.private_ip }} groupname=launched ansible_ssh_user={{ server_config.user }} when: ec2.changed with_items: ec2.instances
Gather facts
TITLE42
... - name: Wait for SSH to come up wait_for: host={{item.private_ip}} port=22 delay=2 timeout=320 state=started when: ec2.changed with_items: ec2.instances
Wait
TITLE
#3 Deployment
43
TITLE44
• Capistrano
Similar To
TITLE45
• Move files to target
• Create release and link to current
• Restart
Tasks
TITLE46
...- name: Unarchive artifacts to dest sudo_user: "app-runner" unarchive: > src=downloads/services.zip dest=/tmp/services
Move files to target
TITLE47
...- name: Create a release sudo_user: "app-runner" release: > src=/tmp/services/archive/artifacts name=consumers keep=5
Create release and link to current
TITLE48
...- name: restart runit service service: name=consumers state=restarted
Restart
TITLE
#4 Builds
49
TITLE50
• Make
• TravisCI
Similar To
TITLE51
• Resolve dependencies
• Build artifacts
• Archive
Tasks
TITLE52
- hosts: 127.0.0.1 connection: local vars: env: "{{lookup('env','ENV')}}"
theme_path: ./themes/cortex bin_grunt_path: ./node_modules/grunt-cli/bin artifacts: - _site
Resolve Dependencies
TITLE53
.... tasks: - file: > path={{current_path}}/artifacts state=directory recurse=yes - name: Install npm deps command: npm install chdir={{theme_path}}
Resolve Dependencies
TITLE54
....- name: Build assets command: "{{bin_grunt_path}}/grunt
chdir={{theme_path}}" - name: Build site command: ~/hugo_0.13/hugo --config="prod_config.yaml" when: env == "prod" - name: Build site command: ~/hugo_0.13/hugo --config="stage_config.yaml" when: env != "prod"
Build
TITLE55
....- name: Build assets command: "{{bin_grunt_path}}/grunt
chdir={{theme_path}}" - name: Build site command: ~/hugo_0.13/hugo --config="prod_config.yaml" when: env == "prod" - name: Build site command: ~/hugo_0.13/hugo --config="stage_config.yaml" when: env != "prod"
Build
TITLE56
...vars:... artifacts: - _site... - command: cp -rf {{item}} {{current_path}}/artifacts with_items: artifacts
Archive
TITLE57
...vars:... artifacts: - _site... - command: cp -rf {{item}} {{current_path}}/artifacts with_items: artifacts
Archive
TITLE
#5 Monitoring
58
TITLE59
• Nagios
Similar To
TITLE60
• SSH into target
• Run assertion
• Notify
Tasks
TITLE61
- hosts: all tasks: - name: Check df command: echo {{(item.size_available * 100 ) // item.size_total}} with_items: ansible_mounts register: df_results
SSH into target
TITLE62
- hosts: all tasks: - name: Check df command: echo {{(item.size_available * 100 ) // item.size_total}} with_items: ansible_mounts register: df_results
SSH into target
TITLE63
- hosts: all tasks: - name: Check df command: echo {{(item.size_available * 100 ) // item.size_total}} with_items: ansible_mounts register: df_results
SSH into target
TITLE64
... - hipchat: > token={{secret_token}} room=notifications msg="Disk space alert -- {{ ansible_fqdn }} disk {{ item.item.mount }} = {{item.stdout}}% free" when: item.stdout | int < 10 with_items: df_results.results
Run Assertion
TITLE65
... - hipchat: > token={{secret_token}} room=notifications msg="Disk space alert -- {{ ansible_fqdn }} disk {{ item.item.mount }} = {{item.stdout}}% free" when: item.stdout | int < 10 with_items: df_results.results
Notify
TITLE
#6 Debugging
66
TITLE67
• Fabric
Similar To
TITLE68
• SSH into target
• Inspect file ( log, config, etc… )
• Dump contents
Tasks
TITLE69
ansible-playbook \-i dev ops.yml \-t runit-log \-e “h=api-servers q=api-hosts”
CLI
TITLE70
- hosts: "{{h}}" tags: ["runit-log"] vars: docs: "Get runit logs" q: "*" p: /home/ansible/service/{{q}}/log/main/current n: 20
SSH into target
TITLE71
... tasks: - shell: tail -n {{n}} {{p}} register: r - debug: var=r.stdout_lines
Inspect file
TITLE72
... tasks: - shell: tail -n {{n}} {{p}} register: r - debug: var=r.stdout_lines
Dump contents
TITLE73
ok: [dev-api0] => { "r.stdout_lines": [ "==> /home/ansible/service/api-hosts-read/log/main/current <==", "2015/04/28 16:12:56 b17fefd0ad793b7a 0.008614 200 10.10.11.207 via 10.10.13.156:42480 GET /hosts/12/agents", "2015/04/28 16:13:06 091e3dcb1a15d931 0.015990 200 10.10.13.156 via 10.10.13.156:42671 GET /hosts/2/agents", "2015/04/28 16:13:12 67dcee980bf3e6cc 0.003114 200 10.10.13.120 via 10.10.13.156:42801 GET /hosts/22/credentials?type=mysql",
Dump contents
TITLE
Bonus!!!
74
TITLE75
• Codify Knowledge
• Accessibility
• Discovery
ChatOps
TITLE76
ansible-playbook \-i dev ops.yml \-t runit-log \-e “h=api-servers q=api-hosts*”
CLI
TITLE77
/ops runit-log use=dev h=api-servers q=api-hosts*
or
/ops use dev
/ops runit-log h=api-servers q=api-hosts*
ChatOps Version
TITLE78
ChatOps in Action
TITLE
Thanks for watching!!!
79