Provisioning Cloud Nodes with Pallet

I recently needed to move a server from dedicated hosting to a cloud server. The existing server had been configured over time by several people, with little documentation. I want to make sure that this time everything was documented, and what better way than doing that than using an automated configuration tool.

Looking around at the configuration tools, I couldn't find one I really liked, so I started Pallet. I'll explain why I didn't use an existing tool below, but first I wanted to show how to manage nodes in Pallet.

  ;; Pull in the pallet namespaces
  (require 'pallet.repl)
  (pallet.repl/use-pallet)

  ;; Define a default node
  (defnode mynode [])

  ;; Define the cloud account to use
  (def service
    (compute-service "provider" "user" "password"
                      :log4j :ssh))

  ;; Create 2 nodes
  (converge {mynode 2} service)

This example would create two nodes (cloud vm instances) with the tag "mynode" in your cloud account, as specified in the service. This would give you the smallest size, ubuntu image on most clouds. Of course, to do anything serious, you would want to specify the image you would like, and you would probably like some configuration of the nodes. So carrying on the above example:

  ;; Pull in the needed crates
  (use 'pallet.crate.automated-admin-user)
  (use 'pallet.crate.java)

  ;; Define a new node that will use the Java JDK
  (defnode javanode
    [:ubuntu :X86_64 :smallest
     :os-description-matches "[^J]+9.10[^32]+"]
    :bootstrap [(automated-admin-user)]
    :configure [(java :openjdk :jdk)])

  ;; Create a new node, and remove the previous ones
  (converge {javanode 1 mynode 0} service)

This would stop the two nodes that were created before, and create a new one, with the specified ubuntu version. On first boot, it would create a user account with your current username, authorize your id_rsa key on that account, and give it sudo permissions. Every time converge is run, it also ensures that the openjdk JDK is installed.

The configuration to be applied is specified as a call to a crate - automated-admin-user and java in the example above. Crates are just clojure functions that specify some configuration or other action on the nodes (they're equivalent to Chef's recipes, which Pallet can also execute using chef-solo). Pallet can be extended with your own crates, and crates can specify general actions, not just configuration. lift is a companion to converge, and can be used to apply crates to existing nodes (including local VM's). The hypothetical example below would execute my-backup-crate on all the "mynode" nodes.

  (defnode mynode [] :backup [(my-backup-crate)])
  (lift mynode service :backup)

This was just a quick overview of Pallet, to give you an idea of what it is. One big area of Pallet not demonstrated here is its command line tool. But that is a topic for another post.

Why Write another Tool?

Now you've seen some examples, I'll try and explain the features that make Pallet distinct from other configuration tools out there.

No Dependencies

The machines being managed require no special dependencies to be installed. As long as they have bash and ssh running, they can be used with pallet. For me this was important - it means that you can use pretty much any image out there, which is great for ad-hoc testing and development.

No Server

Pallet has no central server to set up and maintain - it simply runs on demand. You can run it from anywhere, even over a remote REPL connection.

Everything in Version Control

In pallet, all your configuration is handled in SCM controlled files - there is no database involved. This means that your configuration can always be kept in step with the development of your crates, and the versions of the external crates that you use.

Jar File Distribution of Crates

Custom crates can be distributed as jar files, and so can be published in maven repositories, and be consumed in a version controlled manner. Hopefully this will promote shared crates.

Provisioning, Configuration and Administration

Pallet aims quite wide. You can use it for starting an stopping nodes, for configuring nodes, deploying projects and also for running administration tasks. To be honest, this wasn't an initial design goal, but has come out of the wash that way.

Interested?

Hopefully this has whetted your appetite, and you'll give pallet a try. You can get support via the Google Group, or #pallet on freenode irc.