Introduction
WordPress is a free, open-source content management system (CMS), built with PHP and MySQL. It offers ease of use and flexibility that allow users to create and manage websites and blogs. It is a popular choice among web developers and content creators.
Deploying WordPress on Kubernetes offers several benefits, such as scalability, high availability and deployment of multiple environments. You can scale your WordPress website on the Rcs Kubernetes Engine, ensuring that the website can handle increased traffic. Kubernetes deployment also ensures your website's high availability, making it more fault tolerant. It also allows deploying and managing multiple environments such as development, staging, production, and so on.
This article demonstrates the steps to deploy a WordPress website on the Rcs Kubernetes Engine using the official container image and Rcs Managed Database as the database backend.
Prerequisites
Before you begin, you should:
- Deploy a Rcs Kubernetes Engine cluster.
- Deploy a Managed Database for MySQL cluster.
- Have access to the DNS settings of a domain name. This article uses
wordpress.example.com
for demonstration. - Deploy a Ubuntu 22.04 server to use as a management workstation. On the management workstation:
- Install Kubectl.
- Download your VKE configuration and configure Kubectl.
Ensure that you provision all the services in the same region for low latency between the services.
Install OpenEBS and Dynamic NFS Provisioner
OpenEBS is an open-source storage platform for Kubernetes. It provides a highly available storage solution for the containers. Dynamic NFS Provisioner is an add-on that automates the provisioning of Network File System (NFS) volumes in a Kubernetes cluster. It provides a new storage class that allows the creation of ReadWriteMany
volumes so that multiple pods can share the storage and endure the stateful nature of WordPress.
Install the OpenEBS operator.
# kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
The above command installs the OpenEBS operator on the cluster creating all the required resources, such as role bindings, custom resource definitions and more.
Install the Dynamic NFS Provisioner.
# kubectl apply -f https://openebs.github.io/charts/nfs-operator.yaml
The above command installs the NFS operator on the cluster creating a new storage class named openebs-rbx
that allows creating abstract volumes using a backend storage class to create ReadWriteMany
volumes. It uses the openebs-hostpath
storage class as the default backend storage class. In the next step, you update this storage class to use the vultr-block-storage
as the backend storage class.
Create a new file named sc-rbx.yaml
.
# nano sc-rbx.yaml
Add the following contents to the file.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-rwx
annotations:
openebs.io/cas-type: nfsrwx
cas.openebs.io/config: |
- name: NFSServerType
value: "kernel"
- name: BackendStorageClass
value: "vultr-block-storage"
provisioner: openebs.io/nfsrwx
reclaimPolicy: Delete
The above manifest updates the openebs-rwx
storage class to use the vultr-block-storage
as the backend storage class.
Apply the manifest file.
# kubectl apply -f sc-rbx.yaml
Create the Persistent Volume
You installed the OpenEBS and the Dynamic NFS Provisioner in the previous section to create a new ReadWriteMany
volume. This section demonstrates the steps to create a new Persistent Volume Claim (PVC) using the openebs-rwx
storage class for the WordPress deployment.
Create a new file named wp-pvc.yaml
.
# nano wp-pvc.yaml
Add the following contents to the file.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wordpress-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: "openebs-rwx"
resources:
requests:
storage: 20Gi
The above manifest creates a new PVC resource for the WordPress deployment with 20GB storage. You can change the spec.resources.requests.storage
value to match your storage need.
Apply the manifest file.
# kubectl apply -f wp-pvc.yaml
Verify the deployment.
# kubectl get pvc wordpress-pvc
You can also confirm the deployment by going to the customer portal, opening the cluster page and navigating to the Linked Resources tab. You should see a new block storage resource linked to the cluster matching the storage size of the wordpress-pvc
resource.
Prepare the Kubernetes Cluster
You must prepare the Kubernetes cluster for the WordPress deployment by installing the required plugins and creating a few resources. This section demonstrates the steps to install the ingress-nginx
controller, install the cert-manager
plugin, and create a ClusterIssuer
resource for issuing Let's Encrypt certificates.
Install the ingress-nginx
controller and the cert-manager
plugin.
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml
# kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.0/cert-manager.yaml
The above commands install the ingress-nginx
controller and the cert-manager
plugin on the cluster using the official manifest files. The ingress-nginx
controller provisions a load balancer add-on to handle incoming HTTP requests on the Ingress
resources.
Fetch the load balancer IP address.
# kubectl get services/ingress-nginx-controller -n ingress-nginx
It may take up to 5 minutes before the load balancer is ready. You can confirm the deployment by going to the customer portal, opening the cluster page and navigating to the Linked Resources tab. You should see a new load balancer resource linked to the cluster. You must point the A
record for wordpress.example.com
to the IP address of the load balancer.
Create a new file named le_clusterissuer.yaml
.
# nano le_clusterissuer.yaml
Add the following contents to the file.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: "YOUR_EMAIL"
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
The above manifest creates a ClusterIssuer
resource for issuing Let's Encrypt certificates. It uses the HTTP01
challenge solver to verify the ownership. You must change the spec.acme.email
value to your email address.
Apply the manifest file.
# kubectl apply -f le_clusterissuer.yaml
Verify the deployment.
# kubectl get clusterissuer letsencrypt-prod
Create a new database for the WordPress deployment.
- Log in to the customer portal.
- Navigate to the Databases tab.
- Open your MySQL cluster page.
- Navigate to the Users & Databases tab.
- Add a new database named
wordpress
by clicking the Add New Database button. - Navigate to the Overview tab.
- Copy the credentials, including the hostname, port, user and password.
You can optionally create a new user as well.
Create a new secret resource named wordpress-db-pass
.
# kubectl create secret generic wordpress-db-pass --from-literal=password="MYSQL_USER_PASSWORD"
The above command creates a new secret resource containing the MySQL user's password. You must change the --from-literal=password=
to the MySQL user password.
Deploy the WordPress Website
You installed the required add-ons and created all the necessary resources in the previous sections, such as the PVC and secret resources. This section demonstrates the steps to create a new Deployment
resource for the WordPress deployment and a new Service
resource to expose the connections to the WordPress pods within the cluster.
Create a new file named wp-deployment.yaml
.
# nano wp-deployment.yaml
Add the following contents to the file.
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wordpress
image: wordpress:6.1.1-php8.2-apache
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-data
mountPath: /var/www/html
env:
- name: WORDPRESS_DB_HOST
value: HOST:PORT
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: wordpress-db-pass
key: password
- name: WORDPRESS_DB_USER
value: USER
- name: WORDPRESS_DB_NAME
value: DATABASE
volumes:
- name: wordpress-data
persistentVolumeClaim:
claimName: wordpress-pvc
The above manifest creates a new deployment resource named wordpress
on the cluster. It uses the wordpress-pvc
resource as the volume and the wordpress-db-pass
resource for fetching the MySQL user password. You must change the environment variable values in the container template specification to the credentials of your MySQL cluster, such as the hostname, port, user and database name. You can also change the spec.replicas
value to change the number of initial replicas.
Apply the manifest file.
# kubectl apply -f wp-deployment.yaml
Verify the deployment.
# kubectl get deployment wordpress
# kubectl get pods
Create a new file named wp-svc.yaml
.
# nano wp-svc.yaml
Add the following contents to the file.
apiVersion: v1
kind: Service
metadata:
name: wordpress-svc
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: wordpress
The above manifest creates a new service resource named wordpress-svc
with the app: wordpress
selector to expose the connections to the WordPress pods within the cluster. This resource allows exposing the connections to the internet using an Ingress
resource you create in the next section.
Apply the manifest file.
# kubectl apply -f wp-svc.yaml
Verify the deployment.
# kubectl get svc wordpress-svc
Set Up External Access
This section demonstrates the steps to create an Ingress
resource to set up external access to your WordPress website. It also gives an overview of the session affinity configuration with the ingress-nginx
controller. You must verify that the letsencrypt-prod
cluster issuer resource is ready before you proceed with these steps.
Create a new file named wp-ingress.yaml
.
# nano wp-ingress.yaml
Add the following contents to the file.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wordpress-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "wordpress-cluster"
nginx.ingress.kubernetes.io/session-cookie-expires: "14400"
nginx.ingress.kubernetes.io/session-cookie-max-age: "14400"
spec:
tls:
- secretName: wordpress-tls
hosts:
- wordpress.example.com
rules:
- host: wordpress.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wordpress-svc
port:
number: 80
The above manifest creates a new ingress resource named wordpress-ingress
that enables external access to the wordpress-svc
resource. It uses the letsencrypt-prod
cluster issuer resource to issue a new SSL certificate for wordpress.example.com
and store it as the wordpress-tls
secret resource.
The above manifest also configures session affinity in the annotations using cookie affinity. This means a cookie directs future incoming requests to a specific pod, to prevent getting logged out of the WordPress dashboard due to load balancing between available pods. Refer to the Session Affinity section for more information.
Apply the manifest file.
# kubectl apply -f wp-ingress.yaml
Verify the deployment.
# kubectl get ingress wordpress-ingress
You can now access the WordPress website and complete the installation by opening https://wordpress.example.com
in your web browser. The Let's Encrypt Certificate stored in the wordpress-tls
secret resource secures the website. The ingress-nginx
controller handles the automatic renewals of the certificate when it comes close to the expiry date.
After the installation is complete, you can migrate your existing WordPress website using plugins such as Duplicator, BackupBuddy, UpdraftPlus, Jetpack and more.
Scale the WordPress Deployment
The WordPress deployment demonstrated in the previous sections uses a ReadWriteMany
volume that allows the WordPress pods to share the same volume. This section demonstrates the steps to increase or decrease the number of WordPress pods.
Increase the number of replicas.
# kubectl scale deployment/wordpress --replicas=6
The above command increases the number of deployment/wordpress
replicas to 6.
Verify the change.
# kubectl get deployment wordpress
# kubectl get pods
Decrease the number of replicas.
# kubectl scale deployment/wordpress --replicas=2
The above command decreases the number of deployment/wordpress
replicas to 2.
Verify the change.
# kubectl get deployment wordpress
# kubectl get pods
You can also test the fault tolerance of your WordPress deployment by deleting any running pod using the kubectl delete pod
command. Kubernetes detects the state change and instantly creates a new pod to keep the deployment in a healthy state. New pods get detected by the ingress resource that starts serving the incoming requests in no time.
Conclusion
This article demonstrated the steps to deploy a WordPress website on the Rcs Kubernetes Engine using the official container image and Rcs Managed Database as the database backend. It also walked you through installing the OpenEBS storage platform and the Dynamic NFS Provisioner add-on for creating the ReadWriteMany
volume based on the Rcs Block Storage volume.
You can further enhance the performance of your WordPress website by setting up a Rcs Managed Redis cluster as the object caching backend. This reduces the amount of SQL queries going to the MySQL cluster, reducing the request turn-around time. Refer to the Boost WordPress Performance with Rcs Managed Databases for Redis article for more information.