Presentation from Drupal Show and Tell event on 19th July 2013 where I talked about the work I had been doing on Cloud DevOps with Drupal. Examples include Puppet, Linode, MariaDB.
3. THE TWELVE-FACTOR APP
THE DEVOPS MANIFESTO?
Codebase
Dependencies
Config
Backing Services
Build, release, run
Process
Port binding
Concurrency
Disposability
Dev/prod parity
Logs
Admin processes
http://www.12factor.net/
4. “For practice DevOps I recommend first
follow cloud expert and devops expert on
Twitter. Next step is automate bulls shit out
of everything.”
@DEVOPS_BORAT http://bit.ly/ea42yy
5. MACHINE NAME, OR ROLE?
“I can, within about 10 minutes of
conversation, decide if someones existing
system design is flawed based on a very
simple observation...
do they spend lots of time mentioning
machines by name instead of role?”
Benjamin Knauss http://bit.ly/151fE0c
6. SERVERS = CATTLE, NOT PETS
SCALE UP
Give them a cute name
Each one is unique
When they get sick, nurse back to
health
SCALE OUT
Number them
When they get sick, shoot them
attr: Bill Baker (formerly Microsoft)
10. PUPPET BOOTSTRAP STACKSCRIPT
1. Set hostname and timezone
2. Configure static networking
3. Add Puppet server to /etc/hosts
4. Install Puppet client
5. Request a certificate from Puppet server
6. sign certificate?
7. Run Puppet
13. PUPPET MANIFESTS
Puppet programs are called manifests
Based on Resource declarations
Resource declation = desired state of a resource
Make decisions based on provided variables or Facts
14. EXAMPLE RESOURCE
file { 'testfile':
path => '/tmp/testfile',
ensure => present,
mode => 0640,
content => "I'm a test file.",
}
15. PUPPET TYPES
Files & Directories
Users & Groups
Packages
Services
Crontabs
Mount points
Nagios
Databases
SSH Keys
Software repos
/etc/hosts
Exec
etc... and more from modules...
19. EXAMPLE: MODULES/MARIADB/CONFIG.PP
class mariadb::config (
$root_password = 'UNSET',
...
) inherits mariadb::params {
...
# manage root password if it is set
if $root_password != 'UNSET' {
...
exec { 'set_mysql_rootpw':
command => "mysqladmin -u root ${old_pw} password '${root_passwo
rd}'",
...
require => File['/etc/mysql/conf.d'],
}
}
...
file { '/etc/mysql/my.cnf':
content => template('mariadb/my.cnf.erb'),
mode => '0644',
}
}
20. EXAMPLE: MODULES/MARIADB/DB.PP
define mariadb::db (
$user,
$password,
$charset = 'utf8',
$host = 'localhost',
...
) {
...
# create database if it does not exist
exec { "mariadb-create-db-${title}":
...
command => "/usr/bin/mysql -uroot -p${root_password}
-e 'CREATE DATABASE IF NOT EXISTS ${title};'
",
require => Class['mariadb::server'],
}
...
exec { "mariadb-grant-${title}-${user}":
...
command => "/usr/bin/mysql -uroot -p${root_password}
-e "GRANT ALL PRIVILEGES ON ${title}.* TO '
${user}'@'${host}' IDENTIFIED BY '${password}';"",
require => Class['mariadb::server'],
...
}
}
21. EXAMPLE NODE
node "db01.example.com" {
include core
class { 'mariadb::server':
bind_address => '192.168.195.56',
config_hash => {
'root_password' => '...',
},
}
mariadb::db { 'example_database':
user => 'example',
password => 'password',
host => '192.168.%',
}
}
22. SUMMARY
Develop configuration as code
Use Puppet modules, and commit to Git repo
Use same configuration on dev as prod (Vagrant uses
Puppet)
Automatically generate node configurations and provision
Servers no longer have names, they have a role and number