How to run WordPress and MySQL 5.7 on Kubernetes

Overview

In this tutorial, you will be guided through how to your WordPress and MySQL 5.7 on Kubernetes. You will be shown the different resources types to use for storing passwords, exposing your WordPress blog to the Internet, and storing uploaded content using persistent storage.

Getting Started

The following Gist files were created for this tutorial. Download them to follow along and use as a template in your own environment.

Creating Secrets

It is strongly recommend you do not store your sensitive information in Docker images or Kubernetes resource files. Instead, you should store your sensitive information in a securely away from your application and resources.

Kubernetes secrets allow us to store sensitive information used by resources in the cluster. In this tutorial, you will store two passwords as secrets — one for MySQL root and another for the WordPress admin password.

Passwords are stored as Base64 encoded strings. You will need to create these strings yourself using the base64 command on Linux or OSX, for example. Let’s create those now for both passwords and keep a note of the outputs.

echo "super-secret-mysql-password" | base64
c3VwZXItc2VjcmV0LW15c3FsLXBhc3N3b3JkCg==
echo "super-secret-wp-password" | base64
c3VwZXItc2VjcmV0LXdwLXBhc3N3b3JkCg==

Create a new file named myblog-secrets.yml

touch myblog-secrets.yml

Add the following contents.

---
apiVersion: v1
kind: Secret
metadata:
  name: myblog-secrets
type: Opaque
data:
  mysql_password: c3VwZXItc2VjcmV0LW15c3FsLXBhc3N3b3JkCg==
  admin_password: c3VwZXItc2VjcmV0LXdwLXBhc3N3b3JkCg==

Use the kubectl apply command to create the secrets resource in Kubernetes.

kubectl apply -f myblog-secrets.yml

Deploying MySQL 5.7 Service

Before we can deploy WordPress we will need to create a database for the blogging platform. We will create a deployment resource for the MySQL database that will perform the following actions:

  • Pull down the latest MySQL 5.7 Docker image
  • Create a Pod for the MySQL service
  • Set the environment variables using the secrets we created earlier

Create a new file named myblog-db.yml.

touch myblog-db-deployment.yml

Add the following contents to it.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db1-disk
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db1-deployment
  labels:
    app: db1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db1
  template:
    metadata:
      labels:
        app: db1
    spec:
      containers:
        - name: db1
          image: mysql:5.7
          ports:
            - containerPort: 3306
          volumeMounts:
            - mountPath: "/var/lib/mysql"
              subPath: "mysql"
              name: mysqldb
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db1-secrets
                  key: ROOT_PASSWORD
            - name: MYSQL_USER
              value: site1_user
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db1-secrets
                  key: SITE1_USER_PASSWORD
            - name: MYSQL_DATABASE
              value: site1
      volumes:
        - name: mysqldb
          persistentVolumeClaim:
            claimName: db1-disk
---
apiVersion: v1
kind: Service
metadata:
  name: myblog-db-service
spec:
  selector:
    app: db1
  ports:
  - protocol: TCP
    port: 3306
    targetPort: 3306

Using the kubectl apply command will create the resource declared in the myblog-db.yml file.

kubectl apply -f myblog-db.yml

Deploying WordPress

Create a new file called myblog-wordpress.yml.

touch myblog-wordpress.yml

Add the following content to it.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wordpress-disk
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myblog-wordpress-deployment
  labels:
    app: myblog-wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myblog-wordpress
  template:
    metadata:
      labels:
        app: myblog-wordpress
    spec:
      containers:
        - name: myblog-wordpress
          image: wordpress:5.2
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: "/var/www/html/wp-content"
              subPath: "wp-content"
              name: wordpress-disk
          env:
            - name: WORDPRESS_DB_HOST
              value: myblog-db-service
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db1-secrets
                  key: ROOT_PASSWORD
      volumes:
        - name: wordpress-disk
          persistentVolumeClaim:
            claimName: wordpress-disk
---
apiVersion: v1
kind: Service
metadata:
  name: myblog-wordpress-service
spec:
  selector:
    app: myblog-wordpress
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

Create the resources as declared using the kubectl apply command.

kubectl apply -f myblog-wordpress.yml