devops for humans - ansible for drupal deployment victory!
DESCRIPTION
Everyone knows it's a Good Idea™ to use a configuration management system (e.g. Puppet, Chef) to manage your Drupal infrastructure. But many people (myself included) have run into a wall of #wtfmoments when trying to learn the vagaries of traditional CM systems and their vendor-specific syntaxes. In 2012, Ansible was released, enabling normal human beings to manage their servers with an easy, but powerful, CM system that uses YAML (just like Drupal 8!) to define configuration and Jinja2 (very much like Twig!) for templates. Not only that, but Ansible is also an incredibly simple and very flexible Drupal deployment and continuous delivery tool. Learn how you can use Ansible to manage your infrastructure—including local development environments—and stop letting servers and deployments get in the way of development.TRANSCRIPT
DEVOPS FOR HUMANSF O R D R U P A L D E P L O Y M E N T V I C T O R Y !
DevOps Track - Thursday, June 5, 2014
2014
Me
• geerlingguy / Jeff Geerling • Senior Application Developer, Mercy • Owner, Midwestern Mac, LLC
Ansible for DevOps
• For sale on LeanPub
• 50% complete
This presentation
1. Drupal deployments are hard
2. Ansible is simple and powerful
3. Ansible is great for Drupal deployments (and a lot more)
In the Beginning…
• Local Dev: MAMP/WAMP/XAMPP
• Deployments: git pull && drush updb
• Plus 15 other manual deployment steps…
• New servers: manual provisioning
http://devopsreactions.tumblr.com/
http://devopsreactions.tumblr.com/
_______________________________________ / I once had to go to a sysadmin with a \ \ bottle of whiskey to get a deploy. / -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||-‐-‐-‐-‐w | || ||
@itababy at AnsibleFest NYC, 2014
Managed servers: 1
Managed servers: 1
circa
(Dries)
Managed servers: 50+
UAT
Test
Prod
Managed servers: 50+
UAT
Test
Prod
Dev
Managed servers: 50+
UAT
Test
Prod
circa Dev
The Simsons™ and © Fox and its related companies. All rights reserved.
DevOps
• Solving Modern Problems:
• multi-server infrastructure (beyond LAMP)
• cloud provisioning, auto-scaling
• testable infrastructure
_______________________________________ / It should take less time to rebuild a \ \ server than to log in and fix it. / -‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||-‐-‐-‐-‐w | || ||
http://www.slideshare.net/ItamarHassin/monitordriven-development-using-ansible-34920480
Puppet Chef Salt Ansible
Initial release 2005 2009 2011 2012
Configuration Language DSL Ruby/DSL YAML YAML
Template Language ERB ERB Jinja2 Jinja2
Agentless ✓
Simple ad-hoc task execution ✓ ✓
GitHub ★s* 2,239 2,729 3,531 6,202
*As of 2014/06/02. Just a reference point. Stars don’t mean much in the grand scheme of things ;-)
Current solutions
Puppet Chef Salt Ansible
Initial release 2005 2009 2011 2012
Configuration Language DSL Ruby/DSL YAML YAML
Template Language ERB ERB Jinja2 Jinja2
Agentless ✓
Simple ad-hoc task execution ✓ ✓
GitHub ★s* 2,239 2,729 3,531 6,202
Just like Drupal 8!
Just like Twig!
*As of 2014/06/02. Just a reference point. Stars don’t mean much in the grand scheme of things ;-)
Current solutions
Puppet Chef Salt Ansible
Initial release 2005 2009 2011 2012
Configuration Language DSL Ruby/DSL YAML YAML
Template Language ERB ERB Jinja2 Jinja2
Agentless ✓
Simple ad-hoc task execution ✓ ✓
GitHub ★s* 2,239 2,729 3,531 6,202
Just like Drupal 8!
Just like Twig!
*As of 2014/06/02. Just a reference point. Stars don’t mean much in the grand scheme of things ;-)
#HugOps
Current solutions
Who uses ?
(and me: Server Check.in, Hosted Apache Solr, Midwestern Mac, LLC)
First Steps with
Inventory
Inventory
[lamp] example.com ![lamp:vars] ansible_ssh_user=johndoe ansible_ssh_port=2222
(save in /etc/ansible/hosts)
Inventory
[lamp] example.com ![lamp:vars] ansible_ssh_user=johndoe ansible_ssh_port=2222
(save in /etc/ansible/hosts)
Group name
Inventory
[lamp] example.com ![lamp:vars] ansible_ssh_user=johndoe ansible_ssh_port=2222
(save in /etc/ansible/hosts)
Group nameHosts in group (just one, for now)
Inventory
[lamp] example.com ![lamp:vars] ansible_ssh_user=johndoe ansible_ssh_port=2222
(save in /etc/ansible/hosts)
Group nameHosts in group (just one, for now)
Variables(for all hosts in group)
Playbook Task
Playbook Task
-‐ name: Ensure Apache is installed. apt: pkg=apache2 state=latest
Playbook Task
-‐ name: Ensure Apache is installed. apt: pkg=apache2 state=latest
Documentation
Playbook Task
-‐ name: Ensure Apache is installed. apt: pkg=apache2 state=latest
Documentation
Module
Playbook Task
-‐ name: Ensure Apache is installed. apt: pkg=apache2 state=latest
Documentation
ArgumentsModule
Playbook-‐-‐-‐ -‐ name: Ensure Apache/PHP is installed. apt: "pkg={{ item }} state=latest" with_items: -‐ apache2 -‐ php5-‐common -‐ libapache2-‐mod-‐php5 -‐ php5-‐cli !-‐ name: Ensure Apache is started. service: name=apache2 state=started
(save as web.yml)
Playbook
-‐-‐-‐ -‐ hosts: lamp sudo: yes ! tasks: -‐ apt: update_cache=yes ! -‐ include: web.yml
(save as playbook.yml)
Playbook
-‐-‐-‐ -‐ hosts: lamp sudo: yes ! tasks: -‐ apt: update_cache=yes ! -‐ include: web.yml
(save as playbook.yml)
Name of group/host defined in inventory
Playbook
-‐-‐-‐ -‐ hosts: lamp sudo: yes ! tasks: -‐ apt: update_cache=yes ! -‐ include: web.yml
(save as playbook.yml)
Name of group/host defined in inventory
Include the playbook we created earlier
ansible-‐playbook run
ansible-‐playbook run
Ansible ♥ Vagrant
Ansible ♥ Vagrant
• First-class provisioner
• Inside Vagrantfile:
config.vm.provision "ansible" do |ansible| ansible.playbook = "playbook.yml" ansible.inventory_path = "inventory-‐vagrant" end
Deploy Drupal 8 with
-‐-‐-‐ -‐ hosts: d8 sudo: yes ! pre_tasks: -‐ apt: update_cache=yes -‐ apt_repository: > repo='ppa:ondrej/php5-‐oldstable' ! roles: -‐ geerlingguy.apache -‐ geerlingguy.mysql -‐ geerlingguy.php -‐ geerlingguy.php-‐mysql -‐ geerlingguy.postfix -‐ geerlingguy.drupal
-‐-‐-‐ -‐ ! -‐ -‐ repo='ppa:ondrej/php5-‐oldstable'! -‐ -‐ -‐ -‐ -‐ -‐
(this actually works)
00:03:14 later…
Demo
Ansible Roles• Encapsulation for configuration/tasks
Ansible Roles• Encapsulation for configuration/tasks
Ansible Role
files/
tasks/
handlers/
vars/ meta/
templates/
Drupal Deployment Role
deploy/ roles/ site-deploy/ playbook.yml
Drupal Deployment Role
deploy/ roles/ site-deploy/ playbook.yml
Custom role!'site-deploy'
tasks
-‐-‐-‐ -‐ name: Run drush commands to update site. command: > drush -‐y {{ item }} chdir={{ drupal_core_path }} with_items: -‐ "cset system.site name '{{ site_name }}'" -‐ "rap 'anonymous' 'search content'" notify: restart webserver
site-deploy/tasks/main.yml
vars
-‐-‐-‐ site_name: "Ansible Deployment" drupal_core_path: /var/www/drupal-‐8.x-‐dev
site-deploy/vars/main.yml
handlers
-‐-‐-‐ -‐ name: restart webserver service: > name=apache2 state=restarted sudo: yes
site-deploy/handlers/main.yml
deploy/ roles/ site-deploy/ playbook.yml
tasks/main.yml vars/main.yml handlers/main.yml
Drupal Deployment Role
deploy/ roles/ site-deploy/ playbook.yml
Drupal Deployment Role
playbook
-‐-‐-‐ -‐ hosts: d8 roles: -‐ site-‐deploy
playbook.yml
Demo
Notifications
-‐ name: Send IRC message. irc: > channel='#drupalcon' server='chat.freenode.net' nick='ansible-‐ninja' msg={{ irc_message }} delegate_to: 127.0.0.1
(also inside playbook.yml)
-‐-‐-‐ -‐ hosts: d8 sudo: yes ! pre_tasks: -‐ apt: update_cache=yes -‐ apt_repository: > repo='ppa:ondrej/php5-‐oldstable' ! roles: -‐ geerlingguy.apache -‐ geerlingguy.mysql -‐ geerlingguy.php -‐ geerlingguy.php-‐mysql -‐ geerlingguy.postfix -‐ geerlingguy.drupal -‐ site-‐deploy
-‐-‐-‐ -‐ hosts: d8 sudo: yes ! pre_tasks: -‐ apt: update_cache=yes -‐ apt_repository: > repo='ppa:ondrej/php5-‐oldstable' ! roles: -‐ geerlingguy.apache -‐ geerlingguy.mysql -‐ geerlingguy.php -‐ geerlingguy.php-‐mysql -‐ geerlingguy.postfix -‐ geerlingguy.drupal -‐ site-‐deploy
Add to provisioningplaybook.yml
reverse-proxy.yml
webserver.yml
database.yml
search.yml
cache.yml
reverse-proxy.yml
webserver.yml
database.yml
search.yml
cache.yml
infrastructure-playbook.yml
-‐-‐-‐ -‐ hosts: all roles: -‐ security -‐ monitoring -‐ fileshare !-‐ hosts: webservers roles: -‐ nginx -‐ php -‐ drupal !-‐ hosts: database roles: -‐ postgres
for Drupal Deployment Victory!
for Drupal Deployment Victory!
• Easy to get started
for Drupal Deployment Victory!
• Easy to get started
• OH: “it works on my machine”
• sysadmin burnout
for Drupal Deployment Victory!
• Easy to get started
• OH: “it works on my machine”
• sysadmin burnout
• You’ll actually enjoy it!
for Drupal Deployment Victory!
• Easy to get started
• OH: “it works on my machine”
• sysadmin burnout
• You’ll actually enjoy it!
• …but BEWARE THE GOLDEN HAMMER!
Things I wanted to cover, but didn’t have time
• Ansible ♥’s:
• Packer
• Docker
• [AWS|DO|Linode|Rackspace|etc.]
Things I wanted to cover, but didn’t have time
• Ansible ♥’s:
• Packer
• Docker
• [AWS|DO|Linode|Rackspace|etc.]
• Delegation, notifications, ad-hoc commands, async commands, rolling updates, prompts, Ansible Vault, wait_for, forks, dynamic inventory, and oh-so-much-more…
Things I wanted to cover, but didn’t have time
Resources
• Docs
• Freenode: #ansible
• Google Group
• Ansible for DevOps
• Ansible Weekly (newsletter)
• Download Ansible
• Automate!
• Buy my book :)
Things you will do now:
WHAT DID YOU THINK?E VA LUAT E T H I S S E S S I O N :
A U S T I N 2 0 1 4 . D R U PA L . O R G / S C H E D U L E
Thank you!
2014