Deploying Services
The fundamental point of Juju is that you can use it to deploy serivces through the use of charms (the magic bits of code that make things just work). These charms can be fetched from the charm store, stored in a local repository, or if you are feeling clever, written by you. Just as there are different series of Ubuntu ('precise', 'raring', etc), so there needs to be different series of charms to take into account any subtle changes in the underlying OS. For the most part you can forget about this, as Juju will always try to apply the most relevant charm, so deploying can be straightforward and easy.
Deploying from the Charm Store
In most cases, you will want to deploy charms by fetching them directly from the charm store. This ensures that you get the relevant, up to date version of the charm and "everything just works". To deploy a charm like this you can just specify:
juju deploy mysql
Running this will do exactly what you expect - fetch the latest juju charm for the series you are running and then use the bootstrap environment to initiate a new instance and deploy MySQL
Juju usefully supports a system of namespaces that means you can actually deploy charms from a variety of sources. The default source is the charm store. The above command is the same as running:
juju deploy cs:precise/mysql
which follows the format:
<repository>:<series><service>
Deploying from a local repository
There are many cases when you may wish to deploy charms from a local filesytem source rather than the charm store:
- When testing charms you have written.
- When you have modified store charms for some reason.
- When you don't have direct internet access.
... and probably a lot more times which you can imagine yourselves.
Juju can be pointed at a local directory to source
charms from using the --repository=<path/to/files>
switch like this:
juju deploy --repository=/usr/share/charms/ local:precise/vsftpd
You can also make use of standard filesystem shortcuts, so the following examples are also valid:
juju deploy --repository=. haproxy juju deploy --repository=~/charms/ wordpress
Note: Specifying a
local repository makes juju look there
first, but if the relevant charm is
not found in that repository, it will fall back to
fetching it from the charm store. If you wish to check
where a charm was installed from, it is listed in the
juju status
output.
Changing the defaults
As we have seen, we can specify repositories to
install from on the commandline. In fact, this only
introduces another potential source and changes the
searching order. To permanently change the defaults
(e.g. if you would prefer to always deploy from a local
service first), you can enter a list of repositories in
your environments.yaml
file:
repositories: - http://charms.ubuntu.com/collection/ubuntu - http://charms.ubuntu.com/collection/openstack - http://charms.ubuntu.com/people/miked - /var/lib/charms
A note about caching...
After juju resolves a charm and its dependencies, it bundles them and deploys them to a machine provider charm cache/repository (e.g. ~/.juju/charmcache). This allows the same charm to be deployed to multiple machines repeatably and with minimal network transfers.
Deploying to specific machines
Juju has native support for specifying which machine a charm should be deployed to. This is useful for a few reasons. The most obvious reason is to save money when deploying to a public cloud. Instead of having one machine per unit we can consolidate services.
In this example we use the
--constraints
flag to fire up a bootstrap
node with 4G of RAM so we can deploy other services to
it by using the --to
command:
juju bootstrap --constraints="mem=4G" juju deploy --to 0 mysql juju deploy --to 0 rabbitmq-server
As you can see from the example we've deployed mysql and rabbitmq-server "to" node 0.
Note that you need to know the identifier of the
machine that you are going to deploy --to
– in all
deployments, machine 0 is always the bootstrap node so
the above example works nicely. Doing a juju status
will show you a list of all the machines
and their machine numbers for you to decide what to
deploy to.
The add-unit
command also supports the --to
option, so its now possible to specifically target
machines when expanding service capacity:
juju deploy --constraints="mem=4G" openstack-dashboard juju add-unit --to 1 rabbitmq-server
I should now have a second machine running both the openstack-dashboard service and a second unit of the rabbitmq-server service:
juju status
Which results in the following
machines: "0": agent-state: started agent-version: 1.11.4 dns-name: 10.5.0.44 instance-id: 99a06a9b-a9f9-4c4a-bce3-3b87fbc869ee series: precise hardware: arch=amd64 cpu-cores=2 mem=4096M "1": agent-state: started agent-version: 1.11.4 dns-name: 10.5.0.45 instance-id: d1c6788a-d120-44c3-8c55-03aece997fd7 series: precise hardware: arch=amd64 cpu-cores=2 mem=4096M services: mysql: charm: cs:precise/mysql-26 exposed: false relations: cluster: - mysql units: mysql/0: agent-state: started agent-version: 1.11.4 machine: "0" public-address: 10.5.0.44 openstack-dashboard: charm: cs:precise/openstack-dashboard-9 exposed: false relations: cluster: - openstack-dashboard units: openstack-dashboard/0: agent-state: started agent-version: 1.11.4 machine: "1" public-address: 10.5.0.45 rabbitmq-server: charm: cs:precise/rabbitmq-server-12 exposed: false relations: cluster: - rabbitmq-server units: rabbitmq-server/0: agent-state: started agent-version: 1.11.4 machine: "0" public-address: 10.5.0.44 rabbitmq-server/1: agent-state: started agent-version: 1.11.4 machine: "1" public-address: 10.5.0.45
These two features make it much easier to deploy complex services such as OpenStack which use a large number of charms on a limited number of physical servers.
Considerations
Charms are running without any separation, so its entirely possible for Charms to stamp all over each others configuration files and try to bind to the same network ports. We are working to containerize everything so that this does not happen and every service is in its own container, but this work is not yet complete.
While the "add-unit" command supports the --to
option, you can elect not use --to
when doing an
"add-unit" to scale out the service on it's own
node.
juju add-unit rabbitmq-server
This will allow you to save money when you need it by using --to, but also horizontally scale out on dedicated machines when you need to.