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.
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 126.96.36.199 5432/tcp (config-changed) Live master (10.10) postgresql/1 waiting executing 1 188.8.131.52 agent initializing Machine State DNS Inst id Series AZ Message 0 started 184.108.40.206 machine-0 bionic 1 started 220.127.116.11 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