Archive for the ‘juju’ Category
After experimenting with juju and puppet the other week, I wanted to see if it was possible to create a generic juju charm for deploying any Django apps using Apache+mod_wsgi together with puppet manifests wherever possible. The resulting apache-django-wsgi charm is ready to demo (thanks to lots of support from the #juju team), but still needs a few more configuration options. The charm currently:
- Enables the user to specify a branch of a Python package containing the Django app/project for deploy. This python package will be `python setup.py install`’d on the instance, but it also
- Enables you to configure extra debian packages to be installed first so that your requirements can be installed in a more reliable/trusted manner, along with the standard required packages (apache2, libapache2-mod-wsgi etc.). Here’s the example charm config used for apps.ubuntu.com,
- Creates a django.wsgi and httpd.conf ready to serve your app, automatically collecting all the static content of your installed Django apps to be served separately from the same Apache virtual host,
- When it receives a database relation change, it creates some local settings, overriding the database settings of your branch, sync’s and migrates the database (a noop if it’s the second unit) and restarts apache (See the database_settings.pp manifest for more details).
Here’s a quick demo which puts up a postgresql unit and two app servers with these commands:
$ juju deploy --repository ~/charms local:postgresql $ juju deploy --config ubuntu-app-dir.yaml --repository ~/apache-django-wsgi/ local:apache-django-wsgi $ juju add-relation postgresql:db apache-django-wsgi $ juju add-unit apache-django-wsgi
Things that I think need to be improved or I’m uncertain about:
- `gem install puppet-module` is included in the install hook (a 3rd way of installing something on the system :/). I wanted to use the vcsrepo puppet module to define bzr resource types and puppet-module-tool seems to be the way to install 3rd-party puppet modules. Using this resource-type enables a simple initial_state.pp manifest. Of course, it’d be great to have ‘necessary’ tools like that in the archive instead.
- The initial_state.pp manifest pulls the django app package to /home/ubuntu/django-app-branch and then pip installs it on the system. Requiring the app to be a valid python package seemed sensible (in terms of ensuring it is correctly installed with its requirements satisfied) while still allowing the user to go one step further if they like and provide a debian package instead of a python package in a branch (which I assume we would do ultimately for production deploys?)
- Currently it’s just a very simple apache setup. I think ideally the static file serving should be done by a separate unit in the charm (ie. an instance running a stripped down apache2 or lighttpd). Also, I would have liked to have used an ‘official’ or ‘blessed’ puppet apache module to benefit from someone else’s experience, but I couldn’t see one that stood out as such.
- Currently the charm assumes that your project contains the configuration info (ie. a settings.py, urls.py etc.), of which the database settings can be simply overridden for deploy. There should be an additional option to specify a configuration branch (and it shouldn’t assume that you’re using django-configglue), as well as other options like django_debug, static_url etc.
- The charm should also export an interface (?) that can be used by a load balancer charm.
I’ve been playing with juju for a few months now in different contexts and I’ve really enjoyed the ease with which it allows me to think about services rather than resources.
More recently I’ve started thinking about best-practices for deploying services using juju, while still using puppet to setup individual units. As a simple experiment, I wrote a juju charm to deploy an irssi service  to dig around. Here’s what I’ve found so far . The first is kind of obvious, but worth mentioning:
Install hooks can be trivial:
#!/bin/bash sudo apt-get -y install puppet juju-log "Initialising machine state." puppet apply $PWD/hooks/initial_state.pp
Normally the corresponding manifest (see initial_state.pp) would be a little more complicated, but in this example it’s hardly worth mentioning.
Juju config changes can utilise Puppet’s Facter infrastructure:
This enables juju config options to be passed through to puppet, so that config-changed hooks can be equally simple:
#!/bin/bash juju-log "Getting config options" username=`config-get username` public_key=`config-get public_key` juju-log "Configuring irssi for user" # We specify custom facts so that they're accessible in the manifest. FACTER_username=$username FACTER_public_key=$public_key puppet apply $PWD/hooks/configured_state.pp
In this example, it is the configured state manifest that is more interesting (see configured_state.pp). It adds the user to the system, sets up byobu with an irssi window ready to go, and adds the given public ssh key enabling the user to login.
The same would go for other juju hooks (db-relation-changed etc.), which is quite neat – getting the best of both worlds: the charm user can still think in terms of deploying services, while the charm author can use puppets declarative syntax to define the machine states.
Next up: I hope to experiment with an optional puppet master for a real project (something simple like the Ubuntu App directory), so that
- a project can be deployed without the (probably private) puppet-master to create a close-to-production environment, while
- configuring a puppet-master in the juju config would enable production deploys (or deploys of exact replicas of production to a separate environment for testing).
If you’re interested in seeing the simple irssi charm, the following 2min video demos:
# Deploy an irssi service $ juju deploy --repository=/home/ubuntu/mycharms local:oneiric/irssi # Configure it so a user can login $ juju set irssi username=michael public_key=AAAA... # Login to find irssi already up and running in a byobu window $ ssh email@example.com
and the code is on Launchpad.
 Yes, irssi is not particularly useful as a juju service (as I don’t want multiple units, or relating it to other services etc.), but it suited my purposes for a simple experiment that also automates something I can use for working in the cloud.
 I’m not a puppet or juju expert, so if you’ve got any comments or improvements, don’t hesitate.