Charm architecture
Synapse is a drop in replacement for other chat servers like Mattermost and Slack. It integrates with PostgreSQL as its database.
The charm design leverages the sidecar pattern to allow multiple containers in each pod with Pebble running as the workload container’s entrypoint.
Pebble is a lightweight, API-driven process supervisor that is responsible for configuring processes to run in a container and controlling those processes throughout the workload lifecycle.
Pebble services
are configured through layers,
and the following containers represent each one a layer forming the effective
Pebble configuration, or plan
:
- An NGINX container, which can be used to efficiently serve static resources, as well as be the incoming point for all web traffic to the pod.
- The Synapse container itself, which has Synapse installed and configured.
As a result, if you run a kubectl get pods
on a namespace named for the Juju
model you’ve deployed the Synapse charm into, you’ll see something like the
following:
NAME READY STATUS RESTARTS AGE
synapse-0 3/3 Running 0 6h4m
This shows there are 3 containers - the two named above, as well as a container for the charm code itself.
All containers will have the command /charm/bin/pebble
. Pebble is responsible for service management, as explained above.
processes startup as explained above.
OCI images
We use Rockcraft to build OCI Images for Synapse and NGINX. The images are defined in NGINX rock and Synapse rock. They are published to Charmhub, the official repository of charms. This is done by publishing a resource to Charmhub as described in the Juju SDK How-to guides.
Containers
Configuration files for the containers can be found in the respective directories that define the rocks, see the section above.
NGINX
This container is the entry point for all web traffic to the pod (on port
8080
). Serves static files directly and forwards non-static requests to
the Synapse container (on port 8008
).
NGINX provides static content cache, reverse proxy, and load balancer among multiple application servers, as well as other features. It can be used in front of Synapse server to significantly reduce server and network load.
The workload that this container is running is defined in the NGINX rock.
Synapse
Synapse is a Python application run by the start.py
script.
Synapse listens to non-TLS port 8008
serving by default. NGINX can then
forward non-static traffic to it.
The workload that this container is running is defined in the Synapse rock.
If Synapse is integrated with PostgreSQL, Synapse Stats Exporter will be enabled.
Synapse Stats Exporter listens to non-TLS port 9877
and will be configured as a
target if the charm is integrated with Prometheus. It will provide two metrics: number of rooms and
number of users.
Integrations
See Integrations.
Charm code overview
The src/charm.py
is the default entry point for a charm and has the
SynapseOperatorCharm
Python class which inherits from the CharmBase
.
CharmBase is the base class from which all Charms are formed, defined by Ops (Python framework for developing charms).
See more information in Charm.
The __init__
method guarantees that the charm observes all events relevant to
its operation and handles them.
Take, for example, when a configuration is changed by using the CLI.
- User runs the command
juju config synapse server_name=myserver.myserver.com
- A
config-changed
event is emitted - Event handlers are defined in the charm’s framework observers. An example looks like the following:
self.framework.observe(self.on.config_changed, self._on_config_changed)
4. The method `_on_config_changed` will take the necessary actions.
The actions include waiting for all the relations to be ready and then configuring
the containers.