WordPress on Kubernetes Cluster with AWS EBS as storageClass and LoadBalancer as service — Step-by-Step Guide

Syedusmanahmad
5 min readSep 19, 2024

--

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 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”

Steps:

1- Install the AWS EBS CSI driver

2- Create the storageclass “ebs-sc”

5- Apply WordPress and Mysql manifest files

6- Access WordPress dashboard using the LoadBalancer DNS

Step 1: Install AWS EBS CSI Driver using the AWS EKS Console

CSI driver for EBS

Step 2: Create the storageClass “ebs-sc”

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
fsType: ext4
encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
kubectl apply -f storageclass.yaml
kubectl patch storageclass ebs-sc -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

Step 3: Mysql and WordPress manifest files:

MySQL StatefulSet file:

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.

Mysql Service file:

---
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

Create WordPress Deployment and Service files:

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: LoadBalancer
selector:
app: wordpress
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80

In this YAML file, we define a WordPress Deployment with two replicas and a corresponding Service to expose WordPress to the outside world with LoadBalancer type.

Create a Secret for MySQL Password:

Create a Secret to store the MySQL root password securely.

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=

Create Persistent Volume Claim for MySQL and WordPress:

To ensure data persistence for MySQL and WordPress, create a Persistent Volume Claim using the “storageClassName” as “ebs-sc”.

Create a file named mysql-pvc.yaml and wordpress-pvc.yamlwith the following content:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: ebs-sc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wordpress-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: ebs-sc

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-pvc.yaml
kubectl apply -f mysql-statefulset.yaml
kubectl apply -f mysql-service.yaml
kubectl apply -f wordpress-pvc.yaml
kubectl apply -f wordpress-deployment.yaml

To apply all manifest files at a time use the following command:

# 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 pvc *to verify that both of the claim status should be "Bound"
kubectl get svc wordpress-service

Once you have the LoadBalancer DNS, you can access your WordPress site by navigating to that DNS in your web browser.

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
Syedusmanahmad

Written by Syedusmanahmad

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

No responses yet