How to Run WordPress on a Kubernetes Cluster from Scratch

Learning about Kubernetes, in the beginning, would feel like drinking from a fire-hose. They have a number of various abstractions to solve various problems, all related to one essential goal – Running containerized applications across multiple hosts. If you are unfamiliar with what containers are,  take a few minutes to read our post on Docker and containers in general.

Containers are tied down to usually one physical machine or a VM (which again runs on a single physical machine). You can have multiple containers on one machine, but not the other way round. This is where Kubernetes comes into the picture. What Kubernetes tries to do, is allow us to aggregate multiple numbers of these VMs and physical machines and enable us to deploy applications (inside containers) that would seamlessly run over these multiple interconnected computers as if it were one system.

The best approach to learning anything new, like Kubernetes is to get a hands on experience by doing something productive with it. As such, we are going to go through the process of setting up a Kubernetes cluster from scratch and install a WordPress website on it.

Prerequisites

  1. At least two VPS or VMs, most cloud platforms like AWS, Google and Azure are supported. Each VM must have at least 2GB of RAM and 20GB of available storage.
  2. Private networking between all your Kubernetes dedicated VPS.

We will be using Ubuntu 16.04, hosted on DigitalOcean for all of our running nodes.

1. Kubernetes Cluster Setup

Kubernetes architecture involves setting up one master node which would then delegate tasks and manage resources between various ‘worker nodes‘. Accordingly, let’s label one of our VPS master and another as node-1

Once the nodes are up and running, let’s ssh into our master and configure it with Kubernetes. To begin with, we first update the package repository following which we install Docker

$ sudo apt update && sudo apt upgrade -y
$ sudo apt install docker.io

Next, we would want to create an environment variable MASTER_IP which would store the Public IP address of the master node. (Replace the master.server.ip.address with the IP address of your desired master node)

$export MASTER_IP=master.server.ip.address

This is followed by adding the necessary repositories to your master node. To do that run the following commands:

$curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$cat < /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF

Now that we have necessary modifications in place, let’s update our system about the new repositories available, and then install all the desired packages

$apt update
$apt-get install -y --allow-unauthenticated kubelet kubeadm kubectl kubernetes-cni

At this, point you may want to run the exact commands as above on your node-1 VPS. Make sure you haven’t accidentally had your node’s IP assigned to MASTER_IP variable. The MASTER_IP variable must always be containing the master node’s IP, regardless of where it is declared.

Master Node Specific Configuration

Now we pay attention to master node and perform a few actions that would help establish its authority and control over the worker node. We first initialize our Kubernetes master by running the following command, which would also prescribe networking private parameters :

$kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address $MASTER_IP

The command would take a considerable amount to run, so you should wait patiently until you see something like this:

The last line [kubeadm join ...] of the output is very important, the token is what your worker nodes would need to establish a connection with the master. Save it on your local machine as a text file, for we will need it later on.
You will notice that the output also asks us to start running as a regular user, so if you don’t have a regular user, create one, set its password and give it sudo access.

$adduser bob
$usermod -aG sudo bob

Then login as bob, the regular user by running:

$login bob

Now add the Kubernetes configuration in bob’s home directory,

$mkdir -p $HOME/.kube
$sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$sudo chown $(id -u):$(id -g) $HOME/.kube/config

Lastly, we need to establish the networking between various nodes that will join this cluster in the future. To do this, we use yet another software defined networking layer, flannel:

$kubectl create -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel-rbac.yml --namespace=kube-system
$kubectl create -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml --namespace=kube-system

The above commands would grab the .yaml files describing how to set up flannel on this cluster.

Related:  How to Install and Configure Jenkins Server on CentOS 7 to Automate Your WordPress Tasks

Connecting the node

The node is made aware of the master by using the Token that was generated earlier, just after kubeadm init command. Use the command that was generated in your terminal instead of copying the one below and run it on your target node as root user.

root@node-1:~$ kubeadm join --token ee4fea.3c299a9db86b1f1c $MASTER_IP:6443

You can keep adding as many nodes as you desire, using the Token. If your applications need more resources in the future, you can just add another node and the applications would start using it without any down time whatsoever. After this most of the commands would be run on the master node, as bob, the regular user.

Validation

You may want to check if everything is up and running. To do that there are a few handy commands that you may want to keep in the back of your head. These may take a few minutes to up to half an hour, so be patient.

bob@master:~$ kubectl get nodes
bob@master:~$ kubectl get pods --all-namespaces

Both of which would give you an output similar to this:

You may not see the entry with dashboard written in it, but others would work just fine. The dashboard is a web UI for easier monitoring and management of your Kubernetes cluster.

2. WordPress Setup

Once we have our cluster up and running, time to make it work for us. The first thing to know is that every node will talk to the master using Kubectl which is a binary package that we installed earlier in the tutorial.

WordPress would require a persistent volume (a volume which doesn’t get destroyed over reboots or deletion of applications) this volume will be used by mysql for maintaining various databases to be used by WordPress. To do that, open a file persistent-volume.yaml using any terminal text editor that you prefer. Then enter the following contents in the file:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-1
  labels:
    type: local
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/data/pv-1
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-2
  labels:
    type: local
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/data/pv-2

After this is saved, in the same directory as this file, run the command:

 bob@master:~$kubectl create -f local-volumes.yaml

This file consists instructions for creating two persistent volumes. To see if this has indeed worked, run:

bob@master:~$ kubectl get pv

Once the status shows that the volumes are available, let’s move on to creating a secret which would be used to store your mysql password. Replace the YOUR_PASSWORD field with your secure password.

bob@master:~$kubectl create secret generic mysql-pass --from-literal=password=YOUR_PASSWORD

The mysql-pass object is what holds the secret now, and we shall use it to deploy mysql by first creating a file called mysql-deployment.yaml

apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

That file would kick in the mysql database if you run:

kubectl create -f mysql-deployment.yaml

Finally, we are ready for our WordPress installation. Create a wordpress-deployment.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:4.8-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

After creating the above file, run:

$kubectl create -f wordpress-deployment.yaml

This is the final step and now your WordPress deployment should be up and running. To check the port forwarding run the command:

$kubectl get services

You may have to wait a few minutes as Kubectl gets all the necessary files and configuration set up, but eventually, you will see this:

Related:  VestaCP; Installing the Free Website Management Utility on Ubuntu

If the external IP shows as or that is completely fine. The important portion is the port number that it is running on, in the above case it is 31911 so when you enter your node’s IP address along with the port number, as shown below, you will be greeted with WordPress installation page.

Too complicated a procedure?

You may think that most of the rigmarole that we went through is quite fuzzy and disorienting, and while it is true, it is largely because the above procedure is independent of your cloud provider. Most mainstream cloud providers have their custom solution for configuring the cluster which is largely automated.

Even after that, if it seems too much to you, many professional DevOps would agree with that. There’s nothing wrong with not liking overly complicated systems, especially if all you plan is to run a small blog or a portfolio holding website. Kubernetes is one of the many scalability options to choose from. Docker Swarm is yet another emerging technology. Most of them are in Beta, so was Kubernetes a few months back! So hopefully, these technologies will grow and become more user-friendly before your businesses grow to the point where you need to scale up.

References

The following references largely helped me get on my feet with Kubernetes, so giving credit where it is due, here’s the necessary GitHub repository and further in-depth tutorials:

  1. https://github.com/janakiramm/do-k8s
  2. https://kubernetes.io/docs/tutorials/

We hope you have enjoyed reading this post about how to install and run WordPress on a Kubernetes cluster. Feel free to reach out to our support crew in the case of any issues, we offer 24/7 WordPress support at a ridiculously low price. If you liked this article, then please subscribe to our mailing list for WordPress video tutorials. You can also find us on Twitter and Facebook.

How to Run WordPress on a Kubernetes Cluster from Scratch
4.5 (90%) 2 votes