This guide covers creating K8s volumes and configuring a WP instance with a MySQL database in a most simple way — a perfect introduction to Kubernetes and Docker for newbies.
This article is a direct followup to the articles on dockerizing WordPress and automating WordPress delivery, allowing you to introduce the power of Docker to your dev setup. If you already have a running K8s application, check out this guide to learn how to automate your K8s deployments.
Configure a PersistentVolume in the K8s cluster
In this example, we’ll use a hostPath
volume since we only have one node in the cluster. This type of volume mounts the path from the node's filesystem into K8s.
The
hostPath
volume is not recommended for multi-node production clusters. If you're working on multiple nodes, follow the instructions here.
Create volumes.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-1
labels:
type: local
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /k8/volume/pv-1
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-2
labels:
type: local
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /k8/volume/pv-2
This config will create two R/W 10GB volumes in the node paths:
/k8/volume/pv-1
/k8/volume/pv-2
Create your K8s volumes
To create the volumes, run
$ kubectl apply -f volumes.yml
You can check if everything’s working correctly by running
$ kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
local-pv-1 10Gi RWO Retain Available 13s
local-pv-2 10Gi RWO Retain Available 13s
Configure a MySQL database
Start with creating a secret password for the MySQL root user:
$ kubectl create secret generic mysql-pass --from-literal=password=ROOT_PASSWORD
You can check if the password was properly configured by running.
$ kubectl get secrets
NAME TYPE DATA AGE
mysql-pass Opaque 1 17h
Secrets in K8s are hidden and cannot be displayed. This means there’s no risk of exposing them in config files in public repositories.
Create mysql.yml
The file below will create a single MySQL instance with a proper volume and port mapping. It also uses the secret that we created earlier:
apiVersion: v1
kind: Service
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
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
TableMain of mysql.yml
The file consists of 3 separate configs:
Service — maps MySQL’s port 3306 and makes it available for all containers with labels
app:wordpress
&tier:mysql
Persistent volume claim — declares claim on the volume that will be used in the MySQL container configuration
Deployment — declares the creation strategy and specs of our MySQL container:
TableMain of the MySQL container:
- it’s an image from the Docker Hub:
mysql:5.6
- it has
app:wordpress
&tier:frontend
labels (used inService
) - it contains an environment variable called
MYSQL_ROOT_PASSWORD
which holds the value from our secret password - it has an open port 3306
- it has a volume claim mounted in
/var/lib/mysql
- it’s an image from the Docker Hub:
Create your MySQL instance on K8s
To create the database, run
``bash kubectl apply -f mysql.yml ```
You can check the progress of deployment by running
kubectl get pods
Once you see status:Running
, the MySQL service is ready for action.
Deploy WordPress to Kubernetes
Begin with downloading WordPress sources from https://wordpress.org/download/.
Configure the Docker file
Now we need to dockerize the WordPress instance. The Docker file only requires WP sources:
FROM wordpress:php7.1-apache
COPY . /usr/src/wordpress/
Build & push the Docker image
The next step is building the Docker image and pushing it to your Docker registry:
$ docker login
$ docker build -t buddy/wordpress .
$ docker push buddy/wordpress
Create wordpress.yml
To deploy WordPress on a Kubernetes node you need to create a proper config file:
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
nodePort: 30000
selector:
app: wordpress
tier: frontend
type: NodePort
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
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: buddy/wordpress:latest
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
TableMain of wordpress.yml
The file consists of 3 separate configs:
Service — maps port 80 of the container to the node’s external IP:30000 for all containers with labels
app:wordpress
&tier:frontend
Persistent volume claim — declares claim on the volume that will be used in the WP container configuration
Deployment — declares the creation
strategy
andspec
of our WordPress container:TableMain of the WP container:
- it’s an image from the Docker Hub:
buddy/wordpress:latest
- it has
app:wordpress
&tier:frontend
labels (used inService
) - it contains environment variables
WORDPRESS_DB_HOST
, which is the internal host name of the MySQL instance, andWORDPRESS_DB_PASSWORD
, which holds the value from our secret password - it has an open port 80
- it has a volume claim mounted in
/var/www/html
from which the WP sources are served
- it’s an image from the Docker Hub:
Create your WP instance on K8s
To deploy your WP instance, run
kubectl apply -f wordpress.yml
You can check the progress of deployment by running
kubectl get pods
Once you see status:Running
, the WordPress service is ready for action.
Congratulations! You have successfully deployed your WordPress project to Kubernetes. You can visit the site by going to node IP:30000.
Advantages & Extenstions
Running WordPress and other web projects on Kubernetes gives you a series of benefits:
easy configuration in just a few files
you can recreate the whole configuration on any host with a couple of commands:
$ kubectl apply -f volumes.yml
$ kubectl create secret generic mysql-pass --from-literal=password=ROOT_PASSWORD
$ kubectl apply -f mysql.yml
$ kubectl apply -f wordpress.yml
you can extend the configuration by using volumes on AWS or other production-ready volumes
you can change the external port mapping for proper load balancing
you can change the deployment strategy from
Recreate
toRollingUpdate
to increase container counts and ensure no downtime during the deployment
Automate Kubernets delivery with Buddy
With Buddy, you can streamline the whole K8s deployment down to a single push to branch: from building the Docker image, to applying config changes, to updating the image on your Kubernetes cluster. Check out the guide to see how it looks in action!
You can also automate deployment of any other popular language or framework. Just let us know what you do on the live-chat or drop a line support@buddy.works and we’ll create a delivery pipeline for your project free of charge!