Example: Deploying WordPress and MySQL with Persistent Volumes

This tutorial shows you how to implement a WordPress site and MySQL database using Minikube. Both applications use PersistentVolumes and PersistentVolumeClaims to store data.

A PersistentVolume (PV) is a portion of the storage in the cluster that Kubernetes has manually provisioned or that Kubernetes has dynamically provisioned using StorageClass. A PersistentVolumeClaim (PVC) is a storage request by a user that can be fulfilled by a PV. PersistentVolumes and PersistentVolumeClaims are independent of pod lifecycles and preserve data by restarting, reprogramming, and even deleting pods.



  • PersistentVolumeClaims and PersistentVolumes Create
  • a kustomization.yaml with a

    • secret generator
    • MySQL resource configurations

    • WordPress resource configurations
  • Apply the kustomization directory by kubectl apply -k ./
  • Clean up

Before you begin

You must have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. We recommend that you run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you don’t already have a cluster, you can create one using minikube, or you can use one of these

Kubernetes playgrounds:

  • Killercoda
  • Playing with Kubernetes

To check the version, enter kubectl version.

The example shown on this page works with kubectl 1.14 and higher.

Download the following configuration files:


  1. wordpress-deployment.yaml

Create PersistentVolumeClaims and PersistentVolumes

MySQL and WordPress require a PersistentVolume to store data. Your PersistentVolumeClaims will be created in the deployment step.

Many cluster environments have a default StorageClass installed. When a StorageClass is not specified in PersistentVolumeClaim, the cluster’s default StorageClass is used instead.

When you create a PersistentVolumeClaim, a PersistentVolume is dynamically provisioned based on your StorageClass configuration.

Create a kustomization.yaml


a secret generator

A secret is an object that stores a piece of sensitive data such as a password or key. Since 1.14, kubectl supports Kubernetes object management using a kustomization file. You can create a secret using generators in kustomization.yaml.

Add a secret generator in kustomization.yaml from the following command. You will need to replace YOUR_PASSWORD with the password you want to use.

Add resource configurations for MySQL and WordPress

The following manifest describes a single-instance MySQL deployment. The MySQL container mounts the PersistentVolume to /var/lib/mysql. The environment variable MYSQL_ROOT_PASSWORD sets the database password from the Secret.

The following manifest describes a single-instance WordPress implementation. The WordPress container mounts the PersistentVolume in /var/www/html for website data files. The environment variable WORDPRESS_DB_HOST sets the MySQL service name defined above, and WordPress will access the database by service. The environment variable WORDPRESS_DB_PASSWORD sets the database password from the generated secret kustomize.

Download the

  1. MySQL deployment

  2. configuration file.

  3. Download the WordPress configuration

  4. file.

  5. Add them to the kustomization.yaml file.

Apply and verify

The kustomization.yaml contains all the resources to implement a WordPress site and a MySQL database. You can apply the directory by

Now you can verify that all objects exist.

Verify that the

  1. secret exists by running the following command


    response should be as follows

    :NAME TYPE DATA AGE mysql-pass-c57bb4t7mf Opaque 1 9s

  2. Verify that a PersistentVolume was dynamically provisioned.

    The answer should be like this:

    NAME STATE VOLUME CAPACITY ACCESS MODES STORAGECLASS MYSQL-PV-CLAIM Bound pvc-8cbd7b2e-4044-11e9-b2bb-42010a800002 20Gi RWO Standard 77s wp-pv-claim Bound PVC-8CD0DF54-4044-11E9-B2BB-42010A800002 20Gi RWO Standard 77s

  3. Verify that the Pod is running by running the following

  4. command:

    The response should be like this:

    NAME READY STATUS RESTARTS AGE wordpress-mysql-1894417608-x5dzt 1/1 Running 0 40s verify that the service

    is running by running the

  5. following command

    :The answer should be like this:NAME TYPE CLUSTER-EXTERNAL IP-IP PORT(S) AGE wordpress LoadBalancer <pending> 80:32406/TCP 4m Run the following command to get the IP address for the WordPress service:The



  6. look like this:

  7. Copy the IP address, and load the page in your browser to view your site.

    You should see the WordPress settings page similar to the screenshot below.



  1. Run the following command to delete your Secret, Deployments, Services, and PersistentVolumeClaims:

What’s Next

Learn more about

  • introspection and debugging
  • Learn more about jobs

  • Learn more
  • about port
  • forwarding Learn how to bring a shell to a container

Contact US