WordPress & Kubernetes: Getting Started

WordPress & Kubernetes: Separating Key WordPress Components for Kubernetes

This is the second blog post in our WordPress & Kubernetes series. In this post you will learn about the key WordPress components, and why they need separating in different Kubernetes pods for redundancy, high availability and scalability.

Here’s the series overview:

  • Getting Started with Kubernetes
  • Separating Key WordPress Components for Kubernetes (you are here)
  • Creating a MySQL Database Service in Kubernetes
  • Configuring a Redis Service for Persistent Object Caching
  • Moving the WordPress Media Library to a MinIO Storage Service
  • Making Changes and Deploying Code in Kubernetes
  • Scaling Your WordPress Application In and Out, Auto-Scaling
  • Backups and Disaster Recovery for WordPress on Kubernetes

Separating Key WordPress Components for Kubernetes

Now that you’re familiar with some of the Kubernetes terminology, let’s explore how the various WordPress components fit into a Kubernetes cluster, to provide a good balance between complexity, scalability and performance.

The modern WordPress application consists of the following components:

  • A PHP application (including plugins and themes)
  • A MySQL database
  • A persistent object cache backend, such as Redis or Memcached
  • A media storage backend for user uploads (local filesystem, S3-like storage and others)

The object cache backend is optional, though it is encouraged for highly dynamic WordPress applications.

Same vs. Separate Kubernetes Pods

If you’re looking for simplicity, you could deploy all these WordPress components on a single Kubernetes pod. This will work just fine and will also be fairly quick, since all services will be hosted on the same physical server.

However this approach has some drawbacks:

  • You lose the ability to scale your application in and out
  • Your site will be offline if the underlying host is unreachable or dead
  • You may lose all or some of your WordPress data if the underlying disks are corrupted

For high availability and scalability, you’ll need to separate all your components into different pods, as well as find a way to run at least two copies of each, giving you options for failover and disaster recovery, as well as scale in and out based on demand and capacity.

We’ll cover the exact set up and configuration of each service in the next few posts in this series, but here is a quick outline.

PHP

The PHP application alone is quite straightforward to separate out to its own pods in Kubernetes. However, with WordPress in particular, there are a few key considerations for a successful deployment.

Many parts of WordPress assume they’re running on a single host, so they’ll attempt to do things, such as create files and directories when new plugins are installed, create files when media is uploaded, update its own files when newer versions are available.

On a multi-host deployment such as ours, this will inevitable result in a split-brain situation, where one host (pod) will have one copy of the application files, while another host may have a different copy. To solve this challenge we’ll need to introduce a read-only filesystem, and a deployment flow, to make sure PHP application code is consistent across all running WordPress pods.

MySQL/MariaDB

Separating a MySQL or a MariaDB database into its own Kubernetes pod is usually not a problem, however given our need for scalability and high availability, we’ll need more than one database service.

Luckily, both MySQL and MariaDB have ways to run database clusters with replication and failover, with disaster recovery options for any catastrophic events.

It’s also worth nothing that WordPress is designed to speak to only one database server. Luckily, there are projects such as HyperDB which allow WordPress to work with multiple database servers, shard its data, split reads and writes, detect replication lag and a lot more.

We’ll explore some of these WordPress plugins and database configuration options in the next blog post in this series.

Redis/Memcached

From all the WordPress components we’ve identified, this is the one that doesn’t really require high availability. That is because the data stored in the WordPress object cache is already available in its MySQL database, and is duplicated in Redis/Memcached only for quicker access.

In the event of the object cache server failure, WordPress will happily fetch the data from MySQL instead. However, this will most certainly degrade overall performance, so for high-traffic WordPress applications, we do recommend a highly available and scalable object cache cluster as well.

Both Redis and Memcached have the ability to run in cluster mode (as multiple Kubernetes pods), with read replicas, data sharding and more. There are a few WordPress plugins available to implement these protocols for the WordPress object cache. We’ll explore some of them and their optimal configuration in one of the next posts in this series.

Media/uploads

As mentioned earlier, a default WordPress installation will attempt to write media uploads to its local filesystem. Given our read-only filesystem as explained above, we’ll need to find a different solution for user uploads as well.

Unlike PHP files (core, themes and plugins) we can’t really have users jump through hoops (or a deployment workflow) to get their cat pictures into their WordPress Media Library, but there are a couple of other options available, such as network filesystems, or object storage.

Whatever storage solution we choose, should also be deployed in an N+1 manner. We’ll explore the benefits and drawbacks of each in a future post.

Next

In the next blog post we’ll dive deep into creating a MySQL or MariaDB database cluster in Kubernetes, and ways for WordPress to effectively communicate with this cluster. We’ll talk about replication, sharding, failover and more.