In this section you will learn how to deploy a stateful application, mysql in this example.
As you know a pod
is mortal, meaning it can be destroyed by Kubernetes anytime, and with it it's local data, memory, etc. So it's perfect for stateless applications. Of course, in the real world we need a way to store our data, and we need this data to be persistent in time.
So how can we deploy a stateful application with a persistent storage in Kubernetes? Let's deploy a mysql.
We need to review what a volume is before continuing with the deployment of our mysql. As stated above, the disk of a pod is destroyed with it, so it's lost. For a database it would be nice if we could keep the data between restarts of the pods. Here comes the volume
.
We can see a pod
as something that requests CPU & RAM. We can see a volume
as something that requests a storage on disk. Kubernetes handles a lot of different kind of volumes - 26 as this file hands on is written - from local disk storage to s3.
Here we will use PersistentVolumeClaim
, it's an abstraction over the hard drives of the Kubernetes nodes - a fancy name for local hard drive.
Let's create the volume where our mysql data will be stored.
First we create the PersistentVolume
. It is a piece of storage in the cluster that has been provisioned by a cluster administrator. It is a resource in the cluster just like a node is a resource of the cluster.
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv-volume
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
Let's review some parameters:
capacity
: the capacity of the volumestorage
: the volume size - here1Gb
accessModes
: how this volume will be accessed, hereReadWriteOnce
ReadWriteOnce
: the volume can be mounted as read-write by a single nodeReadOnlyMany
: the volume can be mounted read-only by many nodesReadWriteMany
: the volume can be mounted as read-write by many nodes
hostPath
: where the storage will be stored on the host, here/mnt/data
Apply it:
kubectl apply -f 01-simple-mysql-pv.yml
Now that we have a storage, we need to claim it, make it available for our pods. So we need a PersistentVolumeClaim
. It is a request for storage by a user. It is similar to a pod. Pods consume node resources and PersistentVolumeClaim
consume PersistentVolume
resources.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
The manifest is pretty similar to the PersistentVolume
:
kubectl apply -f 02-simple-mysql-pvc.yml
Now let's create the deployment
of mysql:
kubectl apply -f 03-simple-mysql-deployment.yml
There is a bunch of parameters we haven't seen yet:
strategy
: the strategy of updates of the podstype
:Recreate
. This instructs Kubernetes to not use rolling updates. Rolling updates will not work, as you cannot have more than one Pod running at a time.
env
: the list of environment variables to pass to the containername
: the name of the env variablevalue
: the value of the env variable
volumeMounts
: the volumes, think directories, to give access to the containername
: the name of the volume to mountmountPath
: where in the container to mount the volume
volumes
: the volumes to request access toname
: the name of the volume, same asvolumeMounts.name
persistentVolumeClaim
: thePersistentVolumeClaim
we wantclaimName
: the name of the claim
Let's finish by creating a service
to have stable DNS entry inside our cluster.
kubectl apply -f 04-simple-mysql-service.yml
Finally let's access the mysql:
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
If you don't see a command prompt, try pressing enter.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
+--------------------+
3 rows in set (0.02 sec)
Create a new database in mysql:
mysql> CREATE DATABASE testing;
Query OK, 1 row affected (0.01 sec)
Now delete the service and the deployment:
kubectl delete service,deployment --all
Recreate them, reconnect to mysql and see if you still have the database testing
you created.
kubectl delete service,deployment,pvc,pv,pod --all