Merge ~cjwatson/launchpad:doc-charm-database-roles into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 95521a784a0f0ee394b114f89f3c6dea3a24f48c
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:doc-charm-database-roles
Merge into: launchpad:master
Diff against target: 105 lines (+97/-0)
1 file modified
doc/explanation/charms.rst (+97/-0)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+443202@code.launchpad.net

Commit message

Document database role management for charms

Description of the change

When setting up charmed instances of the librarian recently, I had to invent some approaches to handling database roles. I expect much the same approaches to be used for a number of other charms, so I wanted to at least write down what I did so that other people don't need to reinvent it if they find themselves doing the same thing.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Thanks for the documentation! I added some comments where I'd need some additional information to be able to do similar things.

I understand that we need to do these manual steps due to the way Juju (currently) works.

I would believe that our requirements are not too special. Is the Juju team aware of this situation? Were there discussions or is there an open bug report?

review: Approve
Revision history for this message
Colin Watson (cjwatson) wrote (last edit ):

This isn't a matter for the Juju team (in much the same way that one wouldn't normally escalate bugs in a C program to the compiler team). It's also not an issue if you're using the `postgresql` charm by way of normal Juju relations; in that case the user is created automatically. It's arguably a limitation in the very simple proxy charm that we use to pass around PostgreSQL credentials in order that we don't have to have applications deployed in the same Juju model as PostgreSQL itself; we may eventually be able to use cross-model relations instead, but I'm not enthusiastic about introducing that extra complexity when we already have enough on our plate just with dealing with the migration to Juju.

For qastaging and staging, this is a transitional measure; at some point over the next few months I expect to migrate their databases into the same Juju model as the application code, at which point we can use normal relations for those environments instead.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/doc/explanation/charms.rst b/doc/explanation/charms.rst
2index 6fe52d3..28cb3ba 100644
3--- a/doc/explanation/charms.rst
4+++ b/doc/explanation/charms.rst
5@@ -111,3 +111,100 @@ Managing secrets like this is more cumbersome than updating Mojo specs, so
6 try to keep it to a minimum. In some cases there may be automation
7 available to help, such as the `autocert charm
8 <https://charmhub.io/autocert>`_.
9+
10+Database roles
11+==============
12+
13+PostgreSQL considers "users" and "roles" to be very nearly synonymous. In
14+this section, "user" means specifically a role that has login credentials.
15+
16+Launchpad uses lots of different database roles. We used to deal with this
17+by having each user on each machine that runs Launchpad code have a
18+``.pgpass`` file with credentials for the particular set of users that it
19+needs, and then it would log in as those users directly. However, this
20+approach doesn't work very well with Juju: the ``postgresql`` charm allows
21+related charms to request access to a single user (per interface), and they
22+can optionally request that that user be made a member of some other roles;
23+SQL sessions can then use ``SET ROLE`` to switch to a different role.
24+
25+In our production, staging, and qastaging environments, we use a proxy charm
26+to provide charms with database credentials rather than relating them to
27+``postgresql`` directly (partly for historical reasons, and partly to avoid
28+complications when the database is deployed in a different region from some
29+of our applications). As a result, we need to do some manual user
30+management in these environments. On staging and qastaging, developers can
31+do most of this themselves when adding new charms to those existing
32+deployment environments.
33+
34+Taking the librarian as an example: ``charm/launchpad-librarian/layer.yaml``
35+lists the ``binaryfile-expire``, ``librarian``, ``librarianfeedswift``, and
36+``librariangc`` roles as being required (this corresponds to the database
37+users used by the services and jobs installed by that particular charm). To
38+create the corresponding user, we first generate a password (e.g. using
39+``pwgen 30 1``), then log into the management environment (``ssh -t
40+launchpad-bastion-ps5.internal sudo -iu stg-launchpad``), set up environment
41+variables for qastaging (``. .mojorc.qastaging``), run ``juju ssh
42+launchpad-admin/leader``, and run ``db-admin``. In the resulting PostgreSQL
43+session, replacing ``<secret>`` with the generated password:
44+
45+.. code-block:: psql
46+
47+ CREATE ROLE "juju_launchpad-librarian"
48+ WITH LOGIN PASSWORD '<secret>'
49+ IN ROLE "binaryfile-expire", "librarian", "librarianfeedswift", "librariangc";
50+
51+The user name here should be ``juju_`` plus the name of the charm, since
52+that matches what the ``postgresql`` charm would create.
53+
54+Having done that, we need to install the new credentials. On
55+``stg-launchpad@launchpad-bastion-ps5.internal``, find the
56+``db_connections`` option under the ``external-services`` application, and
57+add an entry to
58+``~/.local/share/mojo/LOCAL/mojo-lp/lp/qastaging/deploy-secrets`` that looks
59+like this, again replacing ``<secret>`` with the generated password:
60+
61+.. code-block:: yaml
62+
63+ launchpad_qastaging_librarian:
64+ master: "postgresql://juju_launchpad-librarian:<secret>@pamola.internal:6432/launchpad_qastaging?connect_timeout=10"
65+ standbys: []
66+
67+In the connection string URL, the database host, port, and name (in this
68+case, ``pamola.internal``, ``6432``, and ``launchpad_qastaging``
69+respectively) should match those of other entries in ``db_connections``.
70+
71+The configuration for the ``pgbouncer`` connection pooler must also be
72+updated to match, which currently requires help from IS. On
73+``pamola.internal``, IS should take the relevant username/password pair from
74+the ``deploy-secrets`` file above and add it to
75+``/etc/pgbouncer/userlist.txt``.
76+
77+Staging works similarly with the obvious substitutions of ``staging`` for
78+``qastaging``. The qastaging and staging environments currently share a
79+``pgbouncer``; as a result, while the user still has to be created on both
80+database clusters, the passwords for a given user on qastaging and staging
81+must be identical.
82+
83+Production works similarly, except that IS needs to generate the user on the
84+production database, add it to the production ``pgbouncer`` by editing
85+``userlist.txt`` in ``prod-launchpad-db@is-bastion-ps5.internal`` and
86+pushing it out using Mojo, and update the secrets file found in
87+``~/.local/share/mojo/LOCAL/mojo-lp/lp/production/deploy-secrets`` on
88+``prod-launchpad@is-bastion-ps5.internal``. Developers should request this
89+via RT, using this document to construct instructions for IS on what to do.
90+
91+Finally, the corresponding application in `launchpad-mojo-specs
92+<https://git.launchpad.net/launchpad-mojo-specs>`_ needs to be configured
93+with the appropriate database name (``launchpad_qastaging_librarian`` in the
94+example above). This normally looks something like this, where
95+``librarian_database_name`` is an option whose value is set depending on the
96+stage name:
97+
98+.. code-block:: yaml
99+
100+ launchpad-librarian:
101+ ...
102+ options: {{ base_options() }}
103+ databases: |
104+ db:
105+ name: "{{ librarian_database_name }}"

Subscribers

People subscribed via source and target branches

to status/vote changes: