Deploying WordPress on Kubernetes Clusters

Overview

In this tutorial, you will be guided on how to deploy WordPress on Kubernetes platforms. The instruction can be used for any Kubernetes cluster, whether it is on-premise, GKE (Google Kubernetes Engine), AKS (Azure Kubernetes Service), or EKS (Elastic Kubernetes Service).

The first section of this tutorial will show you how to launch your first WordPress instance in Kubernetes.

Kubernetes Pods

Kubernetes runs containers within a construct called a pod, which are the smallest atomic unit of a Kubernetes cluster. All containers run within a Kubernetes pod, but a container does not equal a pod.

Each pod provides a single, shared namespace for networking and storage. Multiple containers may run within a single pod, where each container will have access to the same networking namespace and storage. And while multiple containers may run within a single pod, it is best practice for each application being deployed to Kubernetes to have its own pod.

You may be asking yourself why allow running multiple containers within a single pod if it isn’t best practice. The answer to the question is this allows us to attach utility containers to our pods, such as log aggregators, for example.

For a pod to start successfully all containers within it must execute successfully. If your application container starts, but your logging or application monitoring container fails, the pod will not transition to a running state.

Creating a WordPress Pod

To create our first WordPress pod you will need to create a declarative configuration in YAML. The configuration if declarative because we are instructing Kubernetes to set the desired state for our pod.

Create a YAML file named wordpress-blog.yml

---
apiVersion: v1
kind: Pod
metadata:
  name: wordpress-blog
spec:
  containers:
  - name: wordpress-blog
    image: wordpress:5.2
    env:
    - name: WORDPRESS_DB_HOST
      value: database.host.name:3306
    - name: WORDPRESS_DB_NAME
      value: wordpress
    - name: WORDPRESS_DB_PREFIX
      value: myblog_ 

Create the configuration in Kubernetes

kubectl create -f wordpress-blog.yml

The output of the create command will display the status of your request, so will know right away if the pod was created successfully or not. To list your running pods you will use the kubectl get command.

kubectl get pods

The output will look similar to the following, depending on how many pods are running in your cluster and which Kubernetes namespace you are querying against.

NAME             READY   STATUS    RESTARTS   AGE
 wordpress-blog   1/1     Running   0          65s

Getting Pod Details

The kubectl get command will only show you basic information about your pods. For a detailed look at the configuration and state of your pod you will use the kubectl describe command.

kubectl describe pods wordpress-blog
Name:               wordpress-blog
 Namespace:          default
 Priority:           0
 PriorityClassName:  
 Node:               worker/192.168.1.131
 Start Time:         Sat, 18 May 2019 06:38:16 -0400
 Labels:             
 Annotations:        cni.projectcalico.org/podIP: 172.20.1.56/32
 Status:             Running
 IP:                 172.20.1.56
 Containers:
   wordpress-blog:
     Container ID:   docker://f9b860f167fb990992cc4c0d57e51f7934bb58cd377848e0cbf90dfc4d0fc42b
     Image:          wordpress:5.2
     Image ID:       docker-pullable://wordpress@sha256:8eb650ebbc8ea8bf743e046967c06a789c43c4baa46252013faf3c6f5ddd0d58
     Port:           
     Host Port:      
     State:          Running
       Started:      Sat, 18 May 2019 06:38:18 -0400
     Ready:          True
     Restart Count:  0
     Environment:
       WORDPRESS_DB_HOST:    database.host.name:3306
       WORDPRESS_DB_NAME:    wordpress
       WORDPRESS_DB_PREFIX:  myblog_
     Mounts:
       /var/run/secrets/kubernetes.io/serviceaccount from default-token-x8jnp (ro)
 Conditions:
   Type              Status
   Initialized       True
   Ready             True
   ContainersReady   True
   PodScheduled      True
 Volumes:
   default-token-x8jnp:
     Type:        Secret (a volume populated by a Secret)
     SecretName:  default-token-x8jnp
     Optional:    false
 QoS Class:       BestEffort
 Node-Selectors:  
 Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                  node.kubernetes.io/unreachable:NoExecute for 300s
 Events:
   Type    Reason     Age    From               Message
   ----    ------     ----   ----               -------
   Normal  Scheduled  7m40s  default-scheduler  Successfully assigned default/wordpress-blog to worker
   Normal  Pulling    7m40s  kubelet, worker    pulling image "wordpress:5.2"
   Normal  Pulled     7m38s  kubelet, worker    Successfully pulled image "wordpress:5.2"
   Normal  Created    7m38s  kubelet, worker    Created container
   Normal  Started    7m38s  kubelet, worker    Started container

Using the describe command against your pods is useful for troubleshooting problems. The Events section, found at the bottom of the output, provides a window into the activities performed to run the containers within the pod, and if there are any errors during container execution they will be outputted here.

Updating a Pod

It is very unlikely that your pod’s state will be static during its entire lifespan. You will likely need to update it at some point, such as to update WordPress version.

To update a pod you will first update the wordpress-blog.yml file used to create the pod. Then you apply the new configuration using kubectl apply.

kubectl apply -f wordpress-blog.yml

Creating a WordPress Pod Deployment

Kubernetes deployments are used to set a desired deployment state for your pods. You can set the number of replicas you want of your pod to run, for example.

Creating a WordPress Service

Pods are ephemeral by design, so they would not be good candidates for exposing to other services or to the public Internet. Instead, when we want to expose our applications running within a pod we must create a service definition.

Service definitions set how a service will be exposed on the network. There are several options to choose from, and the one you select will be for the particular use case of your service.

LoadBalancer
The load balancer service type will assign a public, routable IP address to your service. The load balancer provisioned will be determined by your Kubernetes network settings. If your cluster is running in GKE or Digital Ocean, for example, a compute load balancer will be provisioned.

NodePort
Node level service types will expose your service using a port local a node. To access the service the IP address of the Kubernetes node the pods are running on will be used.

ClusterIP
A cluster service type will expose the service to entire Kubernetes cluster. This type is useful for exposing internal services to other services and pods. For instance, if you were running a database service within your cluster it would unlikely need to be exposed to the Internet. Instead we can limit the expose to only resources running within our cluster.

Creating a Service

Create new filed called wordpress-blog-service.yml, and add the following contents to the file.

---
apiVersion: v1
kind: Service
metadata:
  name: wordpress-blog-service
spec:
  type: LoadBalancer
  selector:
    application: wordpress-blog
  ports:
  - port: 80
  targetPort:
  - port: 80 

To attach the service definition to your application a selector is used. The value specified in the selector’s application key is the name key value from your pod or deployment yaml file.

Create the service using the kubectl apply command.

kubectl apply -f wordpress-blog-service.yml