|
| 1 | +# Charm architecture |
| 2 | + |
| 3 | +The wordpress-k8s charm aims to provide core functionalities of WordPress with horizontally |
| 4 | +scalable architecture, leveraging its flexible capabilities enhanced by plugins. Operational |
| 5 | +capabilities are enhanced through integration with the |
| 6 | +Canonical Observability Stack ([COS](https://charmhub.io/topics/canonical-observability-stack/)) |
| 7 | +charms. |
| 8 | + |
| 9 | + |
| 10 | +## Containers |
| 11 | + |
| 12 | +The core component of wordpress-k8s charm consists of a wordpress-k8s main workload container with an Apache Prometheus exporter. The services inside the container are driven by |
| 13 | +Pebble, a lightweight API-driven process supervisor that controls the lifecycle of a service. |
| 14 | +Learn more about Pebble and its layer configurations [in the Pebble documentation](https://github.com/canonical/pebble). |
| 15 | + |
| 16 | +```mermaid |
| 17 | +C4Context |
| 18 | +title Component diagram for Wordpress Charm |
| 19 | +
|
| 20 | +Container_Boundary(wordpress, "WordPress") { |
| 21 | + Component(pebble, "Pebble", "", "Starts the WordPress server and app") |
| 22 | + Component(apache-server, "Apache server", "", "Serves the WordPress application") |
| 23 | + Component(charm, "WordPress App", "", "WordPress application") |
| 24 | +
|
| 25 | + Rel(pebble, apache-server, "") |
| 26 | + Rel(apache-server, charm, "") |
| 27 | +} |
| 28 | +``` |
| 29 | + |
| 30 | +### WordPress |
| 31 | + |
| 32 | +This container runs the main workload of the charm. The OCI image is custom built and includes |
| 33 | +the [WordPress CLI](https://make.wordpress.org/cli/handbook/), Apache server and default WordPress plugins and themes. By |
| 34 | +default, Apache server accepts all the web traffic on port 80 and redirects the requests to |
| 35 | +WordPress PHP index file, handled by the default `x-httpd-php` handler. The configuration of the |
| 36 | +Apache server redirects can be found in |
| 37 | +[`wordpress_rock/files/etc/apache2`](https://github.com/canonical/wordpress-k8s-operator/blob/main/wordpress_rock/files/etc/apache2) |
| 38 | +folder. |
| 39 | + |
| 40 | +WordPress, by default, stores uploaded content files locally at `/wp-content/uploads` directory. |
| 41 | +To make the content accessible across WordPress replication servers, a swift-proxy is added to |
| 42 | +enable content storage on OpenStack Swift through the use of |
| 43 | +[`wp_plugin_openstack-objectstorage_config` configuration parameter](https://charmhub.io/wordpress-k8s/configurations#wp_plugin_openstack-objectstorage_config). Swift proxy settings can be found |
| 44 | +in [`docker-php-swift-proxy.conf`](https://github.com/canonical/wordpress-k8s-operator/blob/main/wordpress_rock/files/etc/apache2/conf-available/docker-php-swift-proxy.conf) |
| 45 | +in the repository. The settings are dynamically modified during runtime when the |
| 46 | +`wp_plugin_openstack-objectstorage_config` parameter is configured. |
| 47 | + |
| 48 | +In order to enable monitoring of Apache server status, redirection to WordPress PHP for route |
| 49 | +`/server-status` is overridden in |
| 50 | +[`apache2.conf`](https://github.com/canonical/wordpress-k8s-operator/blob/main/wordpress_rock/files/etc/apache2/apache2.conf). |
| 51 | +`/server-status` endpoint is accessed by `apache-exporter` service to convert and re-expose with |
| 52 | +open metrics compliant format for integration with `prometheus_scrape` interface. |
| 53 | + |
| 54 | +When a logging relation is joined, a promtail application is started via Pebble which starts |
| 55 | +pushing Apache server logs to Loki. The configurations for Apache have been set up to stream logs |
| 56 | +to both `access.log`, `error.log` files and container logs in |
| 57 | +[`000-default.conf`](https://github.com/canonical/wordpress-k8s-operator/blob/main/wordpress_rock/files/etc/apache2/sites-available/000-default.conf). |
| 58 | +These files are essential for promtail to read and push latest logs to Loki periodically. |
| 59 | + |
| 60 | +### charm |
| 61 | + |
| 62 | +This container is the main point of contact with the Juju controller. It communicates with Juju to |
| 63 | +run necessary charm code defined by the main `src/charm.py`. The source code is copied to the |
| 64 | +`/var/lib/juju/agents/unit-UNIT_NAME/charm` directory. |
| 65 | + |
| 66 | +## OCI image |
| 67 | + |
| 68 | +The wordpress-image is custom built to include a default set of plugins and themes. The list of |
| 69 | +plugins and themes can be found at the reference section of the |
| 70 | +[documentation](https://charmhub.io/wordpress-k8s/docs/reference-plugins). Since WordPress is |
| 71 | +an application running on PHP, required libraries and dependencies are installed during the build |
| 72 | +process. |
| 73 | + |
| 74 | +WordPress application installation is done at runtime during database connection setup. This can |
| 75 | +happen during database relation changed, database relation joined or database config changed |
| 76 | +events. |
| 77 | +To facilitate the WordPress installation process, |
| 78 | +[WordPress CLI](https://make.wordpress.org/cli/handbook/guides/installing/) is embedded in the OCI |
| 79 | +image during the build step. The latest CLI PHP archive file from source is used. |
| 80 | + |
| 81 | +Currently, WordPress version 6.4.3 is used alongside Ubuntu 20.04 base image. The Ubuntu base image |
| 82 | +hasn't yet been upgraded to 22.04 due to an unsupported PHP version 8 for |
| 83 | +`wordpress-launchpad-integration` plugin (which currently supports PHP version 7). All other plugins and themes use |
| 84 | +the latest stable version by default, downloaded from the source. |
| 85 | + |
| 86 | +## Integrations |
| 87 | + |
| 88 | +### Peer relations |
| 89 | + |
| 90 | +When deploying multiple replications of the wordpress-k8s charm, peer relations are set up to |
| 91 | +ensure synchronization of data among replications. Namely, secrets and admin credentials are shared |
| 92 | +among peers. See more about the secrets in the `rotate-wordpress-secrets` action of the |
| 93 | +[reference documentation](https://charmhub.io/wordpress-k8s/docs/reference-actions). |
| 94 | + |
| 95 | +### database |
| 96 | + |
| 97 | +The database relation is the standard database relation in accordance with the latest data platform |
| 98 | +library. It is a required relation for wordpress-k8s charm to become active. It provides a |
| 99 | +connection with `mysql_client` interface, meaning that any charms supporting MySQL client can |
| 100 | +connect to the wordpress-k8s charm. It should be noted that the connection port on the database |
| 101 | +side must be on 3306. |
| 102 | + |
| 103 | +### ingress |
| 104 | + |
| 105 | +Ingress interface provides external http/https access to the WordPress application along with other |
| 106 | +additional capabilities depending on the ingress charm. The wordpress-k8s charm's ingress relation |
| 107 | +is best enhanced with the [nginx-ingress-integrator](https://charmhub.io/nginx-ingress-integrator) |
| 108 | +charm, providing additional capabilities such as ModSecurity enabled |
| 109 | +Web Application Firewall ([WAF](https://docs.nginx.com/nginx-waf/)) through the wordpress-k8s charm |
| 110 | +configuration parameter [`use_nginx_ingress_modsec`](https://charmhub.io/wordpress-k8s/configurations#use_nginx_ingress_modsec). The ingress relation interface is subject to |
| 111 | +renaming due to additional ingress interface definition supported by the Traefik charm. |
| 112 | + |
| 113 | +### metrics-endpoint |
| 114 | + |
| 115 | +This interface is a part of the COS integration to enhance metrics observability. The wordpress-k8s |
| 116 | +charm satisfies the `prometheus_scrape` interface as a provider by exposing Open Metrics compliant |
| 117 | +`/metrics` endpoint. Requires [prometheus-k8s](https://charmhub.io/prometheus-k8s) charm. Learn |
| 118 | +more about COS [here](https://charmhub.io/topics/canonical-observability-stack). |
| 119 | + |
| 120 | +### logging |
| 121 | + |
| 122 | +Logging relation is a part of the COS integration to enhance logging observability. The |
| 123 | +wordpress-k8s charm satisfies the `loki_push_api` by integrating promtail that pushes Apache logs to |
| 124 | +Loki. Requires the [loki-k8s](https://charmhub.io/loki-k8s) charm. Learn more about COS |
| 125 | +[here](https://charmhub.io/topics/canonical-observability-stack). |
| 126 | + |
| 127 | +### grafana-dashboard |
| 128 | + |
| 129 | +Grafana-dashboard is a part of the COS integration to enhance observability. This relation provides |
| 130 | +a pre-made dashboard used for monitoring Apache server hosting WordPress. The wordpress-k8s charm |
| 131 | +satisfies the `grafana_dashboard` interface by providing the pre-made dashboard template to the |
| 132 | +Grafana relation data bag under the "dashboards" key. Requires Prometheus datasource to be already |
| 133 | +integrated with Grafana. |
| 134 | + |
| 135 | + |
| 136 | +## Juju events |
| 137 | + |
| 138 | +Juju events allow progression of the charm in its lifecycle and encapsulates part of the execution |
| 139 | +context of a charm. Below is the list of observed events for wordpress-k8s charm with how the charm |
| 140 | +reacts to the event. For more information about the charm’s lifecycle in general, refer to the |
| 141 | +charm’s life [documentation](https://juju.is/docs/sdk/a-charms-life#heading--the-graph). |
| 142 | + |
| 143 | +### start |
| 144 | + |
| 145 | +This event marks the charm’s state as started. The charm’s running state must be persisted by the |
| 146 | +charm in its own state. See the documentation on the |
| 147 | +[start event](https://juju.is/docs/sdk/start-event). |
| 148 | + |
| 149 | +### uploads_storage_attached |
| 150 | + |
| 151 | +This event marks the charm’s storage availability. The name of the event derived from the name of |
| 152 | +the storage noted in the `metadata.yaml` configuration under "storage" key. |
| 153 | +`containers.wordpress.mounts.storage` and `storage.uploads` section. The storage filesystem maps to |
| 154 | +`/var/www/html/wp-content/uploads` directory of the WordPress application, which is used to store |
| 155 | +uploaded content from the WordPress user. |
| 156 | + |
| 157 | +### leader_elected |
| 158 | + |
| 159 | +This event is fired when Juju elects a leader unit among the replica peers. The wordpress-k8s charm |
| 160 | +then responds by setting up secrets and sharing them with peers through peer relation databag if |
| 161 | +not already set. |
| 162 | + |
| 163 | +### config-changed |
| 164 | + |
| 165 | +The wordPress-k8s charm reacts to any configuration change and runs reconciliation between the current |
| 166 | +state and the desired state. See the list of |
| 167 | +[configurations](https://charmhub.io/wordpress-k8s/configure). |
| 168 | + |
| 169 | +### wordpress_pebble_ready |
| 170 | + |
| 171 | +When this event is fired, wordpress-k8s charm installs, configures and starts Apache server for |
| 172 | +WordPress through Pebble if the storage is available. Configurations that are set dynamically |
| 173 | +include database connection and secrets used by the WordPress application. Dynamic configurations |
| 174 | +are modified in `wp-config.php` file and the changes are pushed through Pebble. |
| 175 | + |
| 176 | +### apache_prometheus_exporter_pebble_ready |
| 177 | + |
| 178 | +This event signals that the `apache_prometheus_exporter` container is ready in the pod. Apache |
| 179 | +Prometheus exporter service is then started through Pebble. |
| 180 | + |
| 181 | +### wordpress-replica_relation_changed |
| 182 | + |
| 183 | +When any of the relation is changed, wordpress-k8s charm must run reconciliation between the |
| 184 | +current state and the desired state with new relation data to synchronize the replication |
| 185 | +instances. The reconciliation process is divided into 3 distinct steps: core, theme and plugin |
| 186 | +reconciliation. Core reconciliation sets up the necessary WordPress application configuration: |
| 187 | +secrets and database connection. Theme and Plugin respectively reconcile between currently |
| 188 | +installed themes and plugins with the incoming list of themes and plugins. |
| 189 | + |
| 190 | +### upgrade-charm |
| 191 | + |
| 192 | +The `upgrade-charm` event is fired on the upgrade charm command `juju refresh wordpress-k8s`. The command sets up |
| 193 | +secrets in peer-relation databag for upgraded deployment of WordPress if it was not already set. |
| 194 | + |
| 195 | +## Charm code overview |
| 196 | + |
| 197 | +The `src/charm.py` is the default entry point for a charm and has the WordpressCharm Python class which inherits from CharmBase. |
| 198 | + |
| 199 | +CharmBase is the base class from which all Charms are formed, defined by [Ops](https://juju.is/docs/sdk/ops) (Python framework for developing charms). |
| 200 | + |
| 201 | +> See more in the Juju docs: [Charm](https://canonical-juju.readthedocs-hosted.com/en/3.6/user/reference/charm/). |
| 202 | +
|
| 203 | +The `__init__` method guarantees that the charm observes all events relevant to its operation and handles them. |
| 204 | + |
0 commit comments