Relations are Juju’s secret weapon. They’re the key to enabling “always optimal configuration”. Applications can automatically negotiate their configuration, by making use of information provided by their environment.
This tutorial is 1 of a series that I hope to write illustrating what relations are and how they behave.
Note:
We’ll assume for now that you have a Juju controller available. If that’s not the case, then use juju bootstrap
to create one, or juju login jaas
to make use of the hosted JAAS controllers.
A relation enables application units to share information. Let’s ignore how Juju enables that sharing at this stage. Instead, we’ll work through some examples of why this feature is useful.
Scenario: automatically re-configure an application when it is scaled out into multiple units
When an application’s scale increases, configuration often needs to be updated. Suddenly, the pre-existing unit(s) need to be notified of their new peer.
Deploying a high-availability PostgreSQL cluster on Ubuntu is a very popular tutorial topic. Most tutorials include a dive deep into configuration files. With Juju, that’s not necessary. Relations enable applications to re-configure themselves.
To start, let’s create a stand-alone PostgreSQL server. Execute these commands from the command-line:
juju add-model postgres-demo
juju deploy postgresql
Juju will proceed to deploy PostgreSQL onto /etc/postgresql
within an Ubuntu Server instance. After everything is installed, Juju will write the configuration settings files. One of the most important files is pg_hba.conf. The letters HBA in the file name stand for “host-based authentication”. Accordingly, pg_hba.conf controls access to the database server.
To demonstrate what Juju is able to do, we’ll take a local copy of the file before and after adding a second unit.
The following snippet uses juju exec to execute a command on the postgresql/0
unit. In this case, we’re executing cat. We then redirect the output of the cat
command to a new file on our local machine.
juju exec --unit postgresql/0 \
-- sudo cat /etc/postgresql/10/main/pg_hba.conf \
> /tmp/hba_old.conf
And, to create a high-availability cluster, all we need to do is add a unit:
juju add-unit postgresql
Juju will take the time to ensure that the new unit is on machine that’s provisioned on a different availability zone.
If we monitor the juju status
output, “(config changed)
” will appear in the postgresql/0
unit’s line. The asterisk after postgresql/0 indicates that it is the leader unit.
Model Controller Cloud/Region Version SLA Timestamp
postgres-demo az azure/centralus 2.8-beta1.1 unsupported 10:05:45+13:00
App Version Status Scale Charm Store Rev OS Notes
postgresql 10.10 waiting 2 postgresql jujucharms 199 ubuntu
Unit Workload Agent Machine Public address Ports Message
postgresql/0* active executing 0 13.86.127.19 5432/tcp (config-changed) Live master (10.10)
postgresql/1 waiting executing 1 52.185.67.131 agent initializing
Machine State DNS Inst id Series AZ Message
0 started 13.86.127.19 machine-0 bionic
1 started 52.185.67.131 machine-1 bionic
Once everything has settled down, we’ll be able to evaluate the changes that Juju has made. Let’s copy the new configuration file to a new location.
juju exec --unit postgresql/0 \
-- sudo cat /etc/postgresql/10/main/pg_hba.conf \
> /tmp/hba_new.conf
Let’s observe the difference between the two files. diff
is a great command for this:
diff /tmp/hba_old.conf /tmp/hba_new.conf
Produces (on my model):
104a105,106
> host replication _juju_repl "192.168.0.5/32" md5 # replication:1 (postgresql/1)
> host postgres _juju_repl "192.168.0.5/32" md5 # replication:1 (postgresql/1)
Adding the second unit has caused Juju to insert 2 lines to be added. The _juju_repl
user has been given access to the replication and postgres databases. Is this magic? No! The charm has written the code that makes these changes.
Relations are a mechanism for informing charms that the situation has changed. The charm code is then able to update its application to fit. They’re a surprisingly powerful abstraction that can enable you, as someone writing charms, to keep everything up-to-date.
To clean up, execute the juju destroy-model
command:
juju destroy-model -y postgres-demo