Running WordPress in Kubernetes – Mounting WP_CONTENT to NFS

Despite a lot of articles written on how to run WordPress in Kubernetes, in a previous blog post, I identified two key challenges around horizontally scaling WordPress in Kubernetes. In this post, I will cover how to solve the first challenge when running WordPress in Kubernetes: how do you ensure each replica of a WordPress site is exposing the exact same content?

The easiest solution to ensuring each replica is exposing the same content is to host all the content in a Network File Share (NFS) and mounting the NFS at the location where your wp-content is expected. For default WordPress installations, this is <Wordpress directory>/wp-content (e.g. /var/www/html/wp-content).

Because I had created a Kubernetes cluster in Azure, the rest of this blog will talk about how to create and mount an Azure File share (which is a NFS offering in Azure). But if your Kubernetes cluster is running on other cloud provides like Amazon Web Services, Google Cloud Platform, Oracle Cloud Infrastructure, etc., then you need to identify the equivalent service that offer NFS like capability and then perform the following steps.

Azure File Share

While you can create and maintain your own Samba file share on a regular Linux VM that is exposed via Public IP, Azure offers a fully managed NFS service via Azure File share. You can find instructions on how to create and mount a static Azure File share to your Kubernetes cluster over here. I will specify each of the Kubernetes resources you need to create in the next section, so all you need to do at the moment is the following:

  1. Create a new Azure Storage account. You can also use an existing one if you would like.
  2. Create a new Azure File share.
  3. Upload all of your WordPress File share content to a directory. If you are creating a new WordPress site, and have nothing to upload, just create a new directory where you want all the content for this site to be hosted at.
  4. Have your Azure Storage account name and key ready for the next section.

Kubernetes Resources

Once you have created a new Azure File share and uploaded all your WordPress content to it, you will have to do the following tasks:

  1. Create a Secret storing credentials to your Azure storage account
  2. Create a PersistentVolume that points to your Azure File share
  3. Create a PersistentVolumeClaim that points to your PersistentVolume
  4. Create a Deployment that consumes PersistentVolumeClaim
  5. Create a Service to expose WordPress to public internet

Create Kubernetes Secret

# TODO: replace <Azure Storage account name> with name of your account
# TODO: replace <Azure Storage account key> with your storage account key
kubectl create secret generic azure-secret --from-literal=azurestorageaccountname=<Azure Storage account name> --from-literal=azurestorageaccountkey=<Azure Storage account key>

Create Kubernetes PersistentVolume

Copy the following content into a file called pv.yml and then run: “kubectl create -f pv.yml” command on terminal.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: azurefile
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  storageClassName: azurefile
  azureFile:
    secretName: azure-secret
    shareName: "<your Azure File share name>" # TODO: fill in this value
    readOnly: false
  mountOptions:
  - dir_mode=0777
  - file_mode=0777
  - uid=1000
  - gid=1000
  - mfsymlinks
  - nobrl

Create Kubernetes PersistentVolumeClaim

Copy the following content into a file called pvc.yml and then run: “kubectl create -f pvc.yml” command on terminal.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: azurefile
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: azurefile
  resources:
    requests:
      storage: 10Gi

Create Kubernetes Deployment for WordPress

Copy the following content into a file called deploy.yml and then run: “kubectl create -f deploy.yml” command on terminal.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  replicas: 3
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress:5.5.1-php7.4-apache
        env:
        - name: WORDPRESS_DB_HOST
          value: "<your host>" # TODO: fill in this value
        - name: WORDPRESS_DB_NAME
          value: "<your DB>" # TODO: fill in this value
        - name: WORDPRESS_DB_USER
          value: "<your user>" # TODO: fill in this value
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: "<your DB password secret>" # TODO: fill in this value
              key: "<your DB password key>" # TODO: fill in this value
        ports:
        - containerPort: 80
        volumeMounts:
          - name: azurefile
            subPath: "<Azure File share path containing wp_content>" # TODO: fill in this value
            mountPath: /var/www/html/wp-content
      volumes:
      - name: azurefile
        persistentVolumeClaim:
          claimName: azurefile

Create Kubernetes Service

Copy the following content into a file called service.yml and then run: “kubectl create -f service.yml” command on terminal.

apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  selector:
    app: wordpress
  ports:
  - name: wordpress
    protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer

One thought on “Running WordPress in Kubernetes – Mounting WP_CONTENT to NFS

Leave a Reply

Your email address will not be published. Required fields are marked *