Skip to Content

Continuous Deployment with Brood

Posted on GitHub repository ign/brood

I just wrote my first post on the (relatively) new IGN Code blog introducing the deployment system I wrote in December, Brood. Here’s an excerpt that explains what Brood is:

Brood takes a different approach than most other deployment systems. It leverages Gearman to deploy to multiple servers in parallel. Deploys are triggered by a Gearman client, the Overlord. Most deployment tasks (actions) are executed by Gearman workers running on each server called Drones. In this respect, it is more similar to Chef than Fabric or Capistrano which both execute commands on servers directly with SSH.

Each action is encapsulated in a PHP class. What servers to deploy to and what actions to run on them are defined in an XML config file. There are no pre-determined deployment phases in Brood, nor do you specify on the command line which deploy tasks to be executed. Actions simply run one after the other as specified in the config file — the config file defines your entire deployment process. When you specify an action in the config file, you also specify which hosts or host groups the action should be run on. By default, the action will be run on all hosts in parallel, but you can specify a maximum concurrency for each host group. Brood ships with a few common tasks, such as a task to do a “git pull” and a task to send out e-mail notifications about a deploy. Different source control systems, different code distribution or notification methods, etc. can be supported by writing new actions.

Besides the design philosophy, the most interesting feature (and the one I’m most proud of) is the fine-grained control over parallelism. Consider this snippet from the example configuration file:

<!-- Groups of hosts, typically each group is behind
     a different load balancer -->
<!-- Each host runs a Gearman worker called a Drone -->
<hostgroup name="www">
    <host alias="www1">www1.example.com</host>
    <host alias="www2">www2.example.com</host>
    <host alias="www3">www3.example.com</host>
    <host alias="www4">www4.example.com</host>
</hostgroup>
<hostgroup name="static">
    <host alias="static1">static1.example.com</host>
    <host alias="static2">static2.example.com</host>
</hostgroup>
<action class="Brood\Action\Distribute\Git">
    <!-- Actions are run on hostgroups/hosts concurrently -->
    <hostgroup>www</hostgroup>
    <hostgroup>static</hostgroup>
    <parameters>
        <sudo>deploy</sudo>
        <directory>/var/www/exampleapp</directory>
    </parameters>
</action>
<action class="Brood\Action\Restart\Apache">
    <!-- Within a hostgroup, concurrency can be specified -->
    <hostgroup concurrency="2">www</hostgroup>
    <hostgroup concurrency="1">static</hostgroup>
</action>

With this configuration, all six servers will do a git pull simultaneously. Once that is done, Apache will be restarted on www1, www2, and static1 simultaneously. And once that is done, Apache will be restarted on www3, www4, and static2 simultaneously. Of course, you may not need to restart Apache unless you’re running APC with apc.stat=off, and you probably never need to restart static asset servers. But your deployment process probably includes a task or two that has to happen after git pull, should be done as quickly as possible, but shouldn’t be done on all servers at the same time. Brood makes this incredibly easy.