WordPress on Kubernetes Cluster — Step-by-Step Guide

Syedusmanahmad
5 min readSep 11, 2023

--

Introduction:

WordPress is a popular Content Management System (CMS) that allows you to create and manage websites easily. Kubernetes is a powerful container orchestration platform that can help you deploy and manage WordPress with high availability and scalability.

This guide will walk you through setting up WordPress on a Kubernetes cluster using a MySQL StatefulSet for database storage. We will provide you with the necessary deployment files, secret files, Persistent Volume (PV) and Persistent Volume Claim (PVC) files, and service files to get you started.

Prerequisites:

Before we dive into setting up WordPress on Kubernetes, you’ll need the following prerequisites:

  1. A running Kubernetes cluster.
  2. kubectl command-line tool configured to interact with your Kubernetes cluster.
  3. Helm, a package manager for Kubernetes. You can install Helm by following the official documentation: https://helm.sh/docs/intro/install/ — Optional (for this example not needed)

Follow the link to see the “WordPress deployment on Kubernetes EKS Cluster using HELM Charts”

Step 1: Create MySQL StatefulSet

We will begin by creating a MySQL StatefulSet. Save the following content to a file named mysql-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
labels:
app: mysql
spec:
replicas: 1
serviceName: mysql
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: database
image: mysql:5.7
args:
- "--ignore-db-dir=lost+found"
envFrom:
- secretRef:
name: mysql-secret
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc

This YAML file defines a MySQL StatefulSet with a single replica, using a Persistent Volume Claim (PVC) for data storage. The MySQL root password is fetched from a secret named mysql-secret.

Step2: Create Mysql Service

---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
ports:
- port: 3306
protocol: TCP
selector:
app: mysql

Mysql service file is the type of “ClusterIP” because this is for internal communication between MySQL and WordPress

Step 3: Create WordPress Deployment and Service

Now, create a WordPress Deployment YAML file. Save the following content to a file named wordpress-deployment.yaml: Here you have deployment and service files

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
replicas: 2
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wordpress
image: wordpress:5.8.3-php7.4-apache
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-data
mountPath: /var/www/html
env:
- name: WORDPRESS_DB_HOST
value: mysql-service.default.svc.cluster.local
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
- name: WORDPRESS_DB_USER
value: root
- name: WORDPRESS_DB_NAME
value: mysql
volumes:
- name: wordpress-data
persistentVolumeClaim:
claimName: wordpress-pvc
---
kind: Service
apiVersion: v1
metadata:
name: wordpress-service
spec:
type: NodePort
selector:
app: wordpress
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30007

In this YAML file, we define a WordPress Deployment with two replicas and a corresponding Service to expose WordPress to the outside world with NodePort. You can use the Service type as “LoadBalancer” as well. It uses the MySQL StatefulSet as the database host.

Step 4: Create a Secret for MySQL Password

Create a Secret to securely store the MySQL root password. Save the following content to a file named mysql-secret.yaml:

  • First, you have to encode your password with BASE64. Example command is
#echo "mypassword" | base64
  • To decode the password you can run the following command:
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
MYSQL_ROOT_PASSWORD: bXlwYXNzd29yZAo=

Step 5: Create Persistent Volume and Persistent Volume Claim for MySQL and WordPress

To ensure data persistence for both MySQL and WordPress, create Persistent Volumes and Persistent Volume Claims. Create a file named mysql-pv-pvc.yaml with the following content:

apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data/mysql

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
selector:
matchLabels:
app: mysql

This YAML file defines a Persistent Volume and a Persistent Volume Claim for MySQL. Ensure the hostPath in the Persistent Volume definition points to a suitable directory on your Kubernetes nodes.

apiVersion: v1
kind: PersistentVolume
metadata:
name: wordpress-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /home/ubuntu/project/wp-data

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wordpress-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: manual

For this YAML file, we have defined the “/home/ubuntu/project/wp-data” directory to mount with volume

Step 6: Apply the Configurations

Apply the configurations to your Kubernetes cluster using the following commands:

kubectl apply -f mysql-secret.yaml
kubectl apply -f mysql-pv-pvc.yaml
kubectl apply -f mysql-statefulset.yaml
kubectl apply -f mysql-service.yaml
kubectl apply -f wordpress-pv-pvc.yaml
kubectl apply -f wordpress-deployment.yaml

If can apply your all configuration files at a time as well by calling your directory like:

# kubectl apply -f directory_name

Step 6: Access Your WordPress Site

To access your WordPress site, obtain the external IP address of the WordPress Service with the following command:

kubectl get svc wordpress-service

Once you have the external IP address, you can access your WordPress site by navigating to that IP address in your web browser.

As I have specified the NodePort 30007, the WordPress is reachable on your IP address and port
Add your WordPress Information
WordPress Dashboard is Accessible :)

Conclusion

You’ve successfully set up WordPress on a Kubernetes cluster using a MySQL StatefulSet. This configuration provides data persistence and scalability for your WordPress website. You can further customize and secure your deployment based on your specific requirements or use the HELM package manager for Kubernetes.

I hope you enjoyed reading this article, please feel free to contact me Syedusmanahmad if you have any questions.

Please feel free to write @ engr.syedusmanahmad@gmail.com | Linkedin https://www.linkedin.com/in/engrusman-ahmad for any queries on AWS/DevOps & stay tuned for the next write-up.

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author 👇

--

--

Syedusmanahmad

AWS & DevOps Architect | Linux, Docker, Kubernetes, Terraform, Jenkins, Git&GitHub, Ansible expert