Juju is a service orchestration system. Juju works with a wide variety of providers, including your own machines. It attempts to abstract away the underlying specifics of a provider and allows you to focus and think about your service deployments and how they relate to each other. Juju does that using something called a charm, which we will talk about in this post.
Using a simple configuration file, you set up a provider. For this post, we will be using a local provider that doesn't require any special setup in the configuration file, but does depend on some local system packages being installed. In Part 2 of this two-part blog series, we will be using the EC2 provider, but for now, we will stick with the defaults. Both posts in this series assume you are using Ubuntu 14.04 LTS.
What is a charm?
A charm is a set of files that tell Juju how a service can be deployed and managed. Charms define properties that a service might have, for example, a MySQL charm knows it provides a SQL database and a WordPress charm knows it needs a SQL database. Since this information is encoded in the charm itself, Juju is able to fully manage this relation between the two charms. Let's take a look at just how this works.
First, you need to install Juju:
sudo add-apt-repository ppa:juju/stable sudo apt-get update && sudo apt-get install juju-core juju-local
Once you have Juju installed, you need to create the base configuration for Juju:
Now that you have done that, let’s switch to our local environment. The local environment is a convenient way to test out different deployments with Juju without needing to set up any of the actual third-party providers like Amazon, HP, or Microsoft. The local environment will use LXC containers for each of the service deployments.
juju switch local
First, we want to prepare our local environment to deploy services to it using charms. To do that, we do what is called bootstrapping. The juju bootstrap command will generate some configuration files and set up and start the Juju state machine. This is the machine that handles all of the orchestration commands for your Juju deployment:
Now that we have our Juju environment up and running, we can start issuing commands. First, let’s take a look at our state machine’s details. We can see this information using the status command:
I will be prompting you to use this command throughout this post. This command will help to let you know when services are deployed and ready.
At this point, you can begin deploying services using charms:
juju deploy wordpress
You can check on the status of your WordPress deployment using the previously mentioned juju statuscommand. Juju also logs details about the creation of machines and deployment of services to those machines. In the case of the local environment, those logs live at /var/log/juju-USERNAME-local. This can be a great place to find detailed information should you encounter any problems, and will provide you with a general overview of commands that have been run for a given command.
Continue by installing a database that we will later tell our WordPress installation to use:
juju deploy mysql
Once your deployments have completed, your juju status command will output something very similar to this.
juju status environment: local machines: "0": agent-state: started agent-version: 22.214.171.124 dns-name: localhost instance-id: localhost series: trusty state-server-member-status: has-vote "1": agent-state: started agent-version: 126.96.36.199 dns-name: 10.0.3.196 instance-id: wwitzel3-local-machine-1 series: precise hardware: arch=amd64 "2": agent-state: started agent-version: 188.8.131.52 dns-name: 10.0.3.79 instance-id: wwitzel3-local-machine-2 series: trusty hardware: arch=amd64 services: mysql: charm: cs:trusty/mysql-4 exposed: false relations: cluster: - mysql db: - wordpress units: mysql/0: agent-state: started agent-version: 184.108.40.206 machine: "2" public-address: 10.0.3.79 wordpress: charm: cs:precise/wordpress-25 exposed: true relations: db: - mysql loadbalancer: - wordpress units: wordpress/0: agent-state: started agent-version: 220.127.116.11 machine: "1" open-ports: - 80/tcp public-address: 10.0.3.196
The important detail to note from the status output is that the agent-state parameters for both MySQL and WordPress are reading started. This is generally the sign that the deployment was successful and all is well.
Now that we've deployed our instances of WordPress and MySQL, we need to inform WordPress about our MySQL instance so it can use it as its database. In Juju, these are called relations. Charms expose relation types that they provide or that they can use. In the case of our sample deployment, MySQL provides the db relation, and WordPress needs something that provides a db relation.
Do this with the following command:
juju add-relation mysql wordpress
The WordPress charm has what are called hooks. In the case of our add-relation command shown previously, the WordPress instance will run its relation changed hook, which performs the basic setup for WordPress, just like if you had gone through the steps of the install script yourself. Again, you will want to use the juju status command again to check on the status of the operation. You should notice that the WordPress instance status has gone from started back to installed. This is because it is now running the relationchanged hook on the installation. It will return back to the started status once this operation is complete.
Finally, we need to expose our WordPress installation so people can actually visit it. By default, most charms you deploy with Juju will not be exposed. This means they will not be accessible out of the local network they are being deployed to.
To expose the WordPress charm, we issue the following command:
juju expose wordpress
Now that we have exposed WordPress, we can visit our installation and continue the setup process. You can use juju status again to find the public address of your WordPress installation. Enter that IP address into your favorite browser and you should be greeted with the WordPress welcome page asking you to finish your installation.
Juju provides you with system logs for all of the machines under its control. For a local provider, you can view these logs in /var/log/juju-username-local/; for example, my username is wwitzel3, so my logs are at /var/log/juju-wwitzel3-local. In this folder, you will see individual log files for each machine as well as a combined all-machines.log file, which is an aggregation of all the machines’ log files.
Tailing the all-machines.log file is a good way to get an overview of the actions that Juju is performing after you run a command. It is also great for troubleshooting should you run in to any issues with your Juju deployment.
So there you have it, a basic overview of Juju and a simple WordPress deployment. In Part 2 of this two-part blog series, I will cover a production deployment use case using Juju and Amazon EC2 by setting up a typical Node.js application stack. This will include HAProxy, multiple load-balanced Node.js units, a MongoDB cluster, and an ELK stack (Elasticsearch, Logstash, Kibana) for capturing all of the logging.
About the author
Wayne Witzel III resides in Florida and is currently working for Slashdot Media as a Senior Software Engineer, building backend systems using Python, Pylons, MongoDB, and Solr. He can be reached at @wwitzel3.