Need help with motherbrain?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

RiotGamesMinions
123 Stars 21 Forks Other 2.5K Commits 12 Opened issues

Description

An orchestrator for Chef

Services available

!
?

Need anything else?

Contributors list

motherbrain

Build Status

motherbrain is an orchestration framework for Chef. In the same way that you would use Chef's Knife command to create a single node, you can use motherbrain to create and control an entire application environment.

Other Documentation

Requirements

  • Ruby 2.0.0+
  • Chef Server 10 or 11, or Hosted Chef

Installation

Install motherbrain via RubyGems:

gem install motherbrain

We don't recommend including motherbrain in your Gemfile.

Before using motherbrain, you'll need to create a configuration file with

mb
configure
:
Enter a Chef API URL:
Enter a Chef API Client:
Enter the path to the client's Chef API Key:
Enter a SSH user:
Enter a SSH password:
Config written to: '~/.mb/config.json'

You can verify that motherbrain is installed correctly and pointing to a Chef server by running

mb plugin list --remote
:
$ mb plugin list --remote

** listing installed and remote plugins...

Getting Started

motherbrain comes with an

init
command to help you get started quickly. Let's pretend we have an app called MyFace, our hot new social network. We'll be using the myface cookbook for this tutorial:
$ git clone https://github.com/reset/myface-cookbook
$ cd myface
myface$

We'll generate a new plugin for the cookbook we're developing:

myface$ mb plugin init
      create  bootstrap.json
      create  motherbrain.rb

motherbrain plugin created.

Take a look at motherbrain.rb and bootstrap.json, and then bootstrap with:

mb myface bootstrap bootstrap.json

To see all available commands, run:

mb myface help

myface$

That command created a plugin for us, as well as told us about some commands we can run. Plugins live within cookbooks in a file named

motherbrain.rb
. Notice that each command starts with the name of our plugin. Once we're done developing our plugin and we upload it to our Chef server, we can run plugins from any cookbook on our Chef server.

Lets take a look at all of the commands we can run on a plugin:

myface$ mb myface
using myface (1.1.8)

Tasks: mb myface app [COMMAND] # Myface application mb myface bootstrap MANIFEST # Bootstrap a manifest of node groups mb myface help [COMMAND] # Describe subcommands or one specific subcommand mb myface nodes # List all nodes grouped by Component and Group mb myface provision MANIFEST # Create a cluster of nodes and add them to a Chef environment mb myface upgrade # Upgrade an environment to the specified versions

There are a few things plugins can do:

  • Bootstrap existing nodes and configure an environment
  • Provision nodes from a compute provider, such as Amazon EC2, Vagrant, or Eucalyptus
  • List all nodes in an environment, and what they're used for
  • Configure/upgrade an environment with cookbook versions, environment attributes, and then run Chef on all affected nodes
  • Run plugin commands, which abstract setting environment attributes and running Chef on the nodes

Notice that there's one task in the help output called

app
which doesn't map to any of those bulletpoints. Let's take a look at the plugin our
init
command created:
stack_order do
  bootstrap 'app::default'
end

component 'app' do description "Myface application" versioned

group 'default' do recipe 'myface::default' end end

A plugin consists of a few things:

  • stack_order
    declares the order to bootstrap component groups
  • component
    creates a namespace for different parts of your application
    • description
      provides a friendly summary of the component
    • versioned
      denotes that this component is versioned with an environment attribute
    • group
      declares a group of nodes
    • recipe
      defines how we identify nodes in this group

This plugin is enough to get our app running on a single node. Let's try it out. Edit

bootstrap.json
and fill in a hostname to bootstrap:
{
  "nodes": [
    {
      "groups": ["app::default"],
        "hosts": ["box1"]
    }
  ]
}

And then we'll bootstrap our plugin to that node:

myface-cookbook$ knife environment create motherbrain_tutorial
myface-cookbook$ mb myface bootstrap bootstrap.json -e motherbrain_tutorial

using myface (0.4.1)

[bootstrap] searching for environment [bootstrap] Locking chef_environment:motherbrain_tutorial [bootstrap] performing bootstrap on group(s): ["app::default"] [bootstrap] Unlocking chef_environment:motherbrain_tutorial [bootstrap] Success

That's it! But that's not much different from using

knife bootstrap
, and it took a lot more work.
myface-cookbook$ ls recipes/
database.rb     default.rb      webserver.rb
myface-cookbook$ cat recipes/default.rb
include_recipe "myface::webserver"
include_recipe "myface::database"

We're currently using the

default
recipe in our plugin, which ends up adding both the
webserver
and
database
recipes to our node's runlist. Let's change the automatically-generated plugin to better fit the architecture for our application:
stack_order do
  bootstrap 'app::db'
  bootstrap 'app::web'
end

component 'app' do description "Myface application" versioned

group 'web' do recipe 'myface::webserver' end

group 'db' do recipe 'myface::database' end end

Note that we're bootstrapping the nodes in order, and since our web server depends on a database, we'll want to bootstrap the database first.

And then change our bootstrap manifest to bootstrap 2 nodes instead of 1:

{
  "nodes": [
    {
      "groups": ["app::web"],
      "hosts": ["box1"]
    },
    {
      "groups": ["app::db"],
      "hosts": ["box2"]
    }
  ]
}

And then run the bootstrap again:

myface-cookbook$ mb myface bootstrap bootstrap.json -e motherbrain_tutorial

using myface (0.4.1)

[bootstrap] searching for environment [bootstrap] Locking chef_environment:motherbrain_tutorial [bootstrap] performing bootstrap on group(s): ["app::db"] [bootstrap] performing bootstrap on group(s): ["app::web"] [bootstrap] Unlocking chef_environment:motherbrain_tutorial [bootstrap] Success

That's it! We now have our application deployed to 2 nodes.

Service Commands

If your cookbook is written using the "service orchestration" pattern, motherbrain can make your plugin even simpler.

component "app" do
  description "Myface Application"
  versioned

service "app" do service_group "app" service_recipe "myface::service" service_attribute "myface.app.state" end

group "app" do recipe "myface::app" end end

To start the service, you would run

mb myface service app.app start
. This would set the
myface.app.state
attribute to 'start' and then do a partial chef run on all nodes that have
myface::app
in their default runlist, using an override runlist of
myface::app_service
. The same command could be used to stop, restart, or change to any other state that your service recipe supports.

For each service resource in your cookbook, you should use a single attribute to define the desired state (stopped, started, restarted). The default that motherbrain will look for is

component_name.service_name.state
(although you can use anything you like).

This resource should also be in a dedicated recipe that only works with your services.

Swagger

When running as a server, MB mounts various enpoinds using the Grape library. For convenience, the tool Swagger has also been integrated into MB's REST API.

First, clone the Swagger UI project.

Next, start your MB server. The only requirement here is a properly defined configuration file:

bundle exec bin/mbsrv

Next, open up

dist/index.html
in your clone of swagger-ui. In the top menu bar, paste in your MB server's address (and port) plus
swagger_doc.json
and click Explore.

For a local server, running on the default port, the URL would look like "http://localhost:26100/swagger_doc.json".

That's all! You should now be able to explore the REST API of MB using Swagger.

Authors

If you'd like to contribute, please see our contribution guidelines first.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.