Secure WordPress On Kubernetes With A Managed Cloud Database, TLS, Let's Encrypt And Rolling Upgrades

Introduction

If you're interested in deploying WordPress on a Kubernetes cluster, the easiest way is with Bitnami's WordPress Helm chart, which is also part of the official Helm chart repository. But getting WordPress up and running on Kubernetes is only the beginning.

Typically, if you're deploying WordPress on Kubernetes, you're planning to use it for one (or more) production-grade Web sites or Web applications. Post-deployment tweaks might include:

This guide walks you through the above tasks to help you gain enhanced security and benefits for your production deployment of WordPress on Kubernetes.

Assumptions and prerequisites

This guide makes the following assumptions:

Depending on the tasks you wish to perform, there may be additional requirements and dependencies. Refer to the sections below for task-specific assumptions and prerequisites.

Use a managed cloud database

Tip

The steps below use Amazon RDS as an example and assume that you have an account with Amazon Web Services (AWS). If you prefer to use a different cloud database service, the steps below can be easily adapted to any other database service.

By default, the Bitnami WordPress Helm chart packages MariaDB to enable quick bootstrapping and deployment of WordPress. However, for production environments, it's common to instead rely on a managed cloud database service such as Amazon Relational Database Service(RDS) or Microsoft Azure CosmosDB. These managed database services offer high performance, scalability, automated backups, geographic redundancy and cost-efficient operations among their benefits.

Bitnami's WordPress Helm chart comes with built-in support for external databases, making it easy to provision a new WordPress deployment on Kubernetes and connect it to a managed database service. The steps below explain how to achieve this, using Amazon RDS as an example.

  • Begin by logging in to the Amazon RDS console and creating a new Amazon RDS instance for your WordPress deployment. When creating the RDS instance:
    • Ensure that you configure the security group to allow inbound traffic from your Kubernetes cluster's IP addresses;
    • Specify and note the database administrator username and password;
    • Specify and note a database name (this database will hold your WordPress configuration and content);
RDS credentials
  • Once the Amazon RDS instance has been created, note its endpoint details.
RDS endpoint
  • Deploy a new release of WordPress using Bitnami's Helm chart as shown below. Replace the DATABASE-ENDPOINT, DATABASE-USERNAME, DATABASE-PASSWORD and DATABASE-NAME placeholders with the Amazon RDS endpoint, database administrator username, corresponding password and WordPress database name respectively.
helm install stable/wordpress \
  --set mariadb.enabled=false \
  --set externalDatabase.host=DATABASE-ENDPOINT \
  --set externalDatabase.user=DATABASE-USERNAME \
  --set externalDatabase.password=DATABASE-PASSWORD \
  --set externalDatabase.database=DATABASE-NAME \
  --set externalDatabase.port=3306
Tip

To adapt the previous command for a different cloud database service, simply replace the placeholders shown with the endpoint, credentials and database names provided by that service.

  • Wait for the deployment to complete. Once complete, log in to your Amazon RDS database instance and confirm that you see WordPress-related content and configuration in the specified database.
RDS database contents

Secure traffic with TLS and Let's Encrypt SSL certificates

Tip

The steps below assume that you have a public domain name and the ability to configure an A record for that domain name.

The Bitnami WordPress Helm chart comes with built-in support for Ingress routes and certificate management through cert-manager. This makes it easy to configure TLS support using certificates from a variety of certificate providers, including Let's Encrypt.

The steps below explain how to use Ingress routes and cert-manager to configure TLS for your Bitnami WordPress deployment using a free Let's Encrypt certificate:

Tip

As an alternative to installing the NGINX Ingress controller and cert-manager, you can install the Bitnami Kubernetes Production Runtime (BKPR) which bundles these and other services that make it easy to run production workloads in Kubernetes

  • Begin by installing the NGINX Ingress controller with Helm:
helm install --name ingress stable/nginx-ingress
  • Obtain the LoadBalancer IP address using the command below. Note this IP address as you will use it to configure DNS in a later step.
kubectl get svc ingress-nginx-ingress-controller -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
Tip

It may take some time for the load balancer IP address to be assigned, so you may need to wait a few minutes before the command above returns any output.

  • Browse to the IP address and confirm that you see a "default backend - 404" response. This indicates that the NGINX Ingress controller is working.
  • Configure the DNS for your domain name by adding an A record pointing to the public IP address obtained in the previous steps.
  • Add the cert-manager repository, create a namespace and create CRDs:
helm repo add jetstack https://charts.jetstack.io
kubectl create namespace cert-manager
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml
Tip

When executing these commands on Google Kubernetes Engine (GKE), you may encounter permission errors. Refer to the official cert-manager documentation for notes on how to elevate your permissions.

  • Create a ClusterIssuer resource for Let's Encrypt certificates. Create a file named letsencrypt-prod.yaml with the following content. Replace the EMAIL-ADDRESS placeholder with a valid email address.
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
 labels:
   name: letsencrypt-prod
 name: letsencrypt-prod
spec:
 acme:
   email: EMAIL-ADDRESS
   http01: {}
   privateKeySecretRef:
     name: letsencrypt-prod
   server: https://acme-v02.api.letsencrypt.org/directory
  • Apply the changes to the cluster:
kubectl create -f letsencrypt-prod.yaml
  • Install cert-manager with Helm and configure Let's Encrypt as the default Certificate Authority (CA):
helm install --name cert-manager --namespace cert-manager --version v0.8.1 jetstack/cert-manager \
 --set ingressShim.defaultIssuerName=letsencrypt-prod \
 --set ingressShim.defaultIssuerKind=ClusterIssuer
  • Install WordPress using Bitnami's Helm chart with additional parameters to integrate with Ingress and cert-manager. Replace the DOMAIN placeholder with your domain name:
helm install stable/wordpress \
 --set service.type=ClusterIP \
 --set ingress.enabled=true \
 --set ingress.certManager=true \
 --set ingress.hosts[0].name=DOMAIN \
 --set ingress.tls[0].hosts[0]=DOMAIN \
 --set ingress.tls[0].secretName=wordpress.local-tls

After the deployment completes, visit the domain in your browser and you should see the WordPress site over a secure TLS connection with a valid Let's Encrypt certificate.

TLS security with Let's Encrypt certificate

Perform rolling upgrades

Rolling updates and rollbacks are important benefits of deploying applications into a Kubernetes cluster. With rolling updates, you can perform zero-downtime WordPress upgrades, which is an important consideration for production environments. You can also rollback to to a previous version of WordPress without a service outage.

Bitnami's WordPress Helm chart always uses the latest version of WordPress. To upgrade your deployment of WordPress, use the command below, replacing DEPLOYMENT-NAME with the name of your WordPress deployment:

helm upgrade DEPLOYMENT-NAME stable/wordpress

When performing an upgrade with Bitnami's WordPress Helm chart, it is important to specify the same parameters as when the chart was initially deployed. For example, if the initial deployment was performed with the command:

helm install --name wordpress stable/wordpress --set wordpressPassword=password,mariadb.rootPassword=password

The corresponding upgrade command would be:

helm upgrade wordpress stable/wordpress --set wordpressPassword=password,mariadb.rootPassword=password
Tip

Before upgrading, always check the chart documentation to see if there are any breaking changes between the latest version of the chart and its previous versions. Breaking changes are signified through changes in the chart's major and minor version numbers; patch versions are typically safe to upgrade.

Useful links

To learn more about the topics discussed in this guide, use the links below:

This tutorial is part of the series

From development to production - customize and secure your WordPress deployment

Learn how to create a custom WordPress container image, deploy it on a Kubernetes production cluster, and secure your deployment with TLS and Let's Encrypt SSL certificates.