Help me suffer for charity!

Wednesday, September 9th, 2009

I’m raising money for the Wounded Warrior Project and Athletes For A Cure (Prostate Cancer Research) by participating in something called Fight Gone Bad.

The short version is this:

  1. You donate
  2. I go and REALLY REALLY bust my butt
  3. I vomit (optional)
  4. We help out some deserving people and (for those of us with prostates) maybe even ourselves.

“But Josh, how do I do this?” You ask.
Good question! Just go to my easy-to-remember donation page:
http://j.mp/WatchJoshSweat
In 30 seconds you can enter the amount you’d like to donate and a credit card number. Very easy!

Update: Some people were curious about what the workout itself is.
Straight from the Crossfit FAQ:

In this workout you move from each of five stations after a minute. This is a five-minute round from which a one-minute break is allowed before repeating. The workout is a total of 3 rounds.

The stations are:
1. Wall-ball: 20 pound ball, 10 ft target. (Reps)
2. Sumo deadlift high-pull: 75 pounds (Reps)
3. Box Jump: 20″ box (Reps)
4. Push-press: 75 pounds (Reps)
5. Row: calories (Calories)
The clock does not reset or stop between exercises. On call of “rotate,” the athlete/s must move to next station immediately for good score. One point is given for each rep, except on the rower where each calorie is one point.

Puppet Module Patterns

Monday, July 13th, 2009

I’ve been playing a lot with Puppet recently, and have been really focusing on getting a core set of modules in place. I found myself using a few module patterns over and over, so I thought I’d write them down and keep an updated list.

/base and /site

Our puppet modules are stored in 2 directories: /base and /site. Here are the purposes:

/base

The best way to think of what goes in /base is:

I should be able to (and should!) post my /base tree to github or my blog, and it would be useful to other people.

Examples of things that might go into base are:

  • virtuozzo
  • nginx
  • lighttpd
  • perlbal
  • debrepo
  • rpmrepo
  • openvpn
  • mysql
  • memcached

Essentially, the environments that make daemons or applications useable.

/site

Site should be

This should not be in any way useful (or safe to share) outside my company

Good examples might be:

  • mywebapp
  • mystatshud
  • mymonitoringsystem

Module Design

Any functionality we want to do on a server can more or less be defined as:

I want to set up some applications and an environment in a certain way, so that it does what I want

Sample application: mywebapp

So, for example, if we wanted to build an mywebapp module, we’d need certain things to make that work.
Let’s assume that we need

  • lighttpd installed and configured in a certain way
  • apache installed and configured in a certain way
  • some perl libraries installed
  • some cron jobs set up

and so on.

The obvious way

The way I started out solving these sorts of problems turns out to not scale all that well.
As I started a module (to solve a specific problem) I would just start listing out the puppet resources it would need.

mywebapp/manifests/init.pp

package { "lighttpd": ensure => installed }
service { "lighttpd": ensure => running, enabled => true }
package { "lib-catalyst-rest-perl": ensure => installed }
package { "apache2": ensure => installed }
service { "apache2": ....

and so on.

This breaks down in several ways.

Things can only be defined once in puppet

First, puppet only lets us define a resource once. So if we decide we want a new tool that needs the package lib-catalyst-rest-perl installed, or needs to use apache to host some stats HUD,
we’d have a problem.

statshud/manifests/init.pp

...
package { "apache2": ensure => installed }
...

Puppet will freak.

Puppet::Parser::AST::Resource failed with error ArgumentError: Duplicate definition:
Package[apache2] is already defined in file statshub/manifests/init.pp at line 1;
cannot redefine at statshub/manifests/init.pp:2 on node mondrian

Things would get repeated a lot

As a practical example, I refer you to the our lighttpd config.

It has an SSL config file, in which we find this little gem:

ssl.cipher-list = "DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA EDH-RSA-DES-CBC3-SHA
    AES256-SHA AES128-SHA DES-CBC3-SHA DES-CBC3-MD5 RC4-SHA RC4-MD5"

Neat! This implements the current best practices for what ciphers we should accept.

So having this in a base/ module, which is used by everything that needs to spin up a lighttpd, means that all my stuff will be running in the safest way I know how to run it.

The alternative is not very pleasant: I’d need to copy and paste this block in every one of my modules that used lighttpd. I’d need to keep it updated in each one of those files if and when a cipher turns out to be insecure.

Similarly, I can consolidate a lot of intelligence like this:

  • making sure log rotation is correct
  • making sure compression cache files are cleaned
  • making sure monit is configured to restart it if it dies
  • making sure file permissions are set up right
  • ….

and, should we learn something New And Improved about any of these things, viola, all our useage of that module gets improved.

As an added benefit, this style of consolidation maps onto the way Puppet itself is going.
Much like Perl has the CPAN, Puppet Modules will be getting some new features that allow them to be centralized. Soon we will be able to get “the puppet mysql module” rather than “some guy’s cloned module from a cloned module on github”.

Module Patterns

Because of the above threats and virtues, we want to push as much functionality as we can into base modules.

Basic Design

Puppet Module Designs

So how this looks in practice in puppet-speak:

mywebapp/manifests/init.pp


// configure lighttpd module
include lighttpd

// configure apache module
include apache

// configure mysql module
include mysql

// set up crons
cron {
    command => "...."
}

Configuring other Classes

Ok, great, I’ve shipped all that intelligence to another module. But how do I make it work the way I want it to?

Well, we want to configure other classes. There are 3 basic methods to configure a class:

  • Create subclasses and only include one or some of them
  • Create ‘defines’ that we use from inside classes
  • Set variables before you include it

Technique #1: Create subclasses and only include one or some of them

I’ll keep this one simple:

A lot of the time there are several distinct modes you might want to use an app in. For example, there’s a big difference between

include mysql

and

include mysql::server

Technique #2: Create ‘defines’ that we use from inside classes

This technique is the most commonly used one. Many of the application and daemon classes we want to configure have lots of “parts” that can be enabled. Some examples:

  • monit config chunks
  • apache/lighttpd/nginx sites
  • subversion repos

These are best handled with defines. A good full-strength version of this is in our monit config:

define conf ( $source = '', $content = '' ) {
    if $source != '' {
        file { "/etc/monit.d/$name":
            notify => Service["monit"],
            source => $source,
            mode => 644,
            owner => root,
            group => root,
        }
    } else {
        file { "/etc/monit.d/$name":
            notify => Service["monit"],
            content => $content,
            mode => 644,
            owner => root,
            group => root,
        }
    }
}

Notable features:

 define conf ( $source = '', $content = '' ) 

This is useful because we can define a config file via either source or content.

I can call this from another module like:

include monit::common
monit::common::conf { "lighttpd-monit": source => "puppet:///lighttpd/lighthttpd-monitrc" }

or, if I wanted to template it:

include monit::common
monit::common::conf { "apache2": content => template("apache2/apache2-monitrc.erb") }

There’s no reason for us not to actually help people out and write common configs for them. This is easy with extra defines.

define simple_service ($pidname = $name) {
    file { "/etc/monit.d/$name":
        notify => Service["monit"],
        content => template("monit/simple_service.erb"),
        mode => 644,
        owner => root,
        group => root,
    }
}
include monit::common
monit::common::simple_service { "apache2": pidname => "apache2" }

Technique #3: Set variables before you include the class

A good example might be for the mywebapp, I only want apache2 to be listening to the lo loopback interface. This would be a dumb default behavior if someone just did

include apache2

I would probably want it listening on all the public interfaces, by default.

So I can specify configuration variables:

In

site/mywebapp/manifests/init.pp


// we only want to have apache2 listening on the loopback
$apache2_interface = "lo"

include apache2

Then, in

base/apache2/manifests/init.pp

// if someone set this variable before they included our class, use it
if($apache2_interface) {
    $interface = $apache2_interface
} else {
    // by default use '*' which means listen on all interfaces
    $interface = "*"
}

I like the idea of a consistent prefixing of configuration variables — for example, all config variables for module ‘foo’ would be ‘$foo_….’

Sometimes including a class doesn’t make sense unless we have some variable defined at all — there’s no reasonable default.
Let’s say we’re configuring our local syslog — the server we syslog to. Without defining that, it doesn’t make sense to include the module.

We get this pretty much for free, actually. If you specify in your documentation:

You must specify a value for $syslog_server before including this module

base/syslog-client/manifests/init.pp

    file { "/etc/syslog.conf":
        content => template(syslog-client/syslog.conf.erb),
    }

base/syslog-client/templates/syslog.conf.erb

#
# Remote Logging
#

destination d_remote {
        tcp("<%= syslog_server %>", port(514));
};

So if someone tries to

include syslog-client

without defining that variable, puppet will error for you.

Failed to parse template syslog.conf.erb: Could not find value for ’syslog_server’

Conclusions

I’ll keep this page updated as more useful patterns emerge.

Thinking about decomposing modules by /base and /site is a powerful model already, as it helps develop new variants on ideas in a really rapid way with little to no copy and paste.

I’ve found that my site modules are often in the 4-7 lines long range, and I automatically get a lot of my hard-earned “best ways to do things” along for the ride.

And since I’m not the only one making things around here, everyone else saves time (and avoids some n00b mistakes) by being able to develop things more quickly as well.

So much to say, so little time to say it!

Thursday, June 18th, 2009

I’ve been working on a lot of fun things both personally and for my company. However, I haven’t prioritized blogging about it. Maybe I should add a GTD recurring task to ‘blog about what’s on my plate.’

Things I’ve been focusing on:

Learning more about agile methods, especially as it pertains to to dealing with teams that have operational requirements as well.

Working more with my OpenSolaris NAS. Suprisingly, one of my most popular ever blog articles.

Playing lots of music: I’m playing bass and guitar in my cover band’s summer concert this weekend. (Can’t wait!)

Planning an epic road trip for the summer: 5 weeks up the West Coast, starting in July.

And, of course, loving my little 5 month old!

So, more blogs to come.