Drupal Devministration

Preview:

DESCRIPTION

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.

Citation preview

DEVMINISTRATIONDRUPAL SHOW AND TELL, LONDON, 18TH JULY 2013

/ Darren Mothersele @mothersele

DELIVERING SaaSSoftware errosionAutomated provisioningScalabilityAvailability

THE TWELVE-FACTOR APPTHE DEVOPS MANIFESTO?

CodebaseDependenciesConfigBacking ServicesBuild, release, runProcess

Port bindingConcurrencyDisposabilityDev/prod parityLogsAdmin processes

http://www.12factor.net/

“For practice DevOps I recommend firstfollow cloud expert and devops expert on

Twitter. Next step is automate bulls shit outof everything.”

@DEVOPS_BORAT http://bit.ly/ea42yy

MACHINE NAME, OR ROLE?“I can, within about 10 minutes of

conversation, decide if someones existingsystem 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

SERVERS = CATTLE, NOT PETSSCALE UP

Give them a cute nameEach one is uniqueWhen they get sick, nurse back tohealth

SCALE OUTNumber themWhen they get sick, shoot them

attr: Bill Baker (formerly Microsoft)

DEVMINISTRATION“Stop administering your infrastructure,

and start developing it!”

1. Provision server via API call2. Boot server and let it configure itself

PROVISION SERVERlinode.create()linode.ip.addprivate()linode.disk.createfromstackscript()linode.boot()

STACKSCRIPTS?Bare distro by defaultStackScript runs on first bootUDF - User defined fields

PUPPET BOOTSTRAP STACKSCRIPT1. Set hostname and timezone2. Configure static networking3. Add Puppet server to /etc/hosts4. Install Puppet client5. Request a certificate from Puppet server6. sign certificate?7. Run Puppet

PUPPET

PUPPET NETWORKING

Being a Puppet Master http://slidesha.re/n1DG8o

PUPPET MANIFESTSPuppet programs are called manifestsBased on Resource declarationsResource declation = desired state of a resourceMake decisions based on provided variables or Facts

EXAMPLE RESOURCEfile { 'testfile': path => '/tmp/testfile', ensure => present, mode => 0640, content => "I'm a test file.",}

PUPPET TYPESFiles & DirectoriesUsers & GroupsPackagesServicesCrontabsMount points

NagiosDatabasesSSH KeysSoftware repos/etc/hostsExec

etc... and more from modules...

BASIC PUPPET: PACKAGE, FILE, SERVICE package { 'ntp': ensure => installed, }

file { '/etc/ntp.conf': ensure => file, source => '/root/example/ntp.conf', owner => 'root', group => 'root', mode => '0444', require => Package['ntp'], notify => Service['ntp'], }

service { 'ntp': ensure => 'running', enable => 'true', }

PUPPET MODULESManifestsFilesTemplatesLibraries

EXAMPLE: MODULES/MARIADB/INIT.PPclass mariadb {

apt::source { 'mariadb' : location => "http://mirror.stshosting.co.uk/mariadb/repo/5.5/ubuntu", repos => 'main', key => '1BB943DB', key_server => 'keyserver.ubuntu.com', include_src => true, }

package { 'mariadb-server': ensure => installed, require => Apt::Source['mariadb'], }}

EXAMPLE: MODULES/MARIADB/CONFIG.PPclass 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_password}'", ... require => File['/etc/mysql/conf.d'], } } ... file { '/etc/mysql/my.cnf': content => template('mariadb/my.cnf.erb'), mode => '0644', }}

EXAMPLE: MODULES/MARIADB/DB.PPdefine 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'], ... }}

EXAMPLE NODEnode "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.%', }}

SUMMARYDevelop configuration as codeUse Puppet modules, and commit to Git repoUse same configuration on dev as prod (Vagrant usesPuppet)Automatically generate node configurations and provisionServers no longer have names, they have a role and number