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.
- 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.
- 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)
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:
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.
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
[email protected]:~$ 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.
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.
[email protected]:~$ kubectl get nodes [email protected]:~$ 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:
[email protected]:~$kubectl create -f local-volumes.yaml
This file consists instructions for creating two persistent volumes. To see if this has indeed worked, run:
[email protected]:~$ 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.
[email protected]:~$kubectl create secret generic mysql-pass --from-literal=password=YOUR_PASSWORD
mysql-pass object is what holds the secret now, and we shall use it to deploy
mysql by first creating a file called
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
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:
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.
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:
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.