kubernetes-hands-on/17-volumes/README.md

141 lines
4.6 KiB
Markdown
Raw Normal View History

2019-05-09 19:40:55 +06:00
# Running a stateful application: `volumes`
## Introduction
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.
2019-05-09 19:40:55 +06:00
So how can we deploy a stateful application with a persistent storage in Kubernetes? Let's deploy a mysql.
2019-05-09 19:40:55 +06:00
## Volumes
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`.
2019-05-09 19:40:55 +06:00
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.
2019-05-09 19:40:55 +06:00
Here we will use `PersistentVolumeClaim`, it's an abstraction over the hard drives of the Kubernetes nodes - a fancy name for local hard drive.
2019-05-09 19:40:55 +06:00
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.
2019-05-09 19:40:55 +06:00
2019-05-21 15:09:13 +06:00
```yml
2019-05-09 19:40:55 +06:00
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 volume
* `storage`: the volume size - here `1Gb`
* `accessModes`: how this volume will be accessed, here `ReadWriteOnce`
* `ReadWriteOnce`: the volume can be mounted as read-write by a single node
* `ReadOnlyMany`: the volume can be mounted read-only by many nodes
* `ReadWriteMany`: the volume can be mounted as read-write by many nodes
* `hostPath`: where the storage will be stored on the host, here `/mnt/data`
2019-05-09 19:40:55 +06:00
Apply it:
2019-05-21 15:10:59 +06:00
```sh
kubectl apply -f 01-simple-mysql-pv.yml
2019-05-09 19:40:55 +06:00
```
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.
```yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
```
The manifest is pretty similar to the `PersistentVolume`:
2019-05-21 15:10:59 +06:00
```sh
kubectl apply -f 02-simple-mysql-pvc.yml
2019-05-09 19:40:55 +06:00
```
## Stateful application
Now let's create the `deployment` of mysql:
2019-05-21 15:10:59 +06:00
```sh
kubectl apply -f 03-simple-mysql-deployment.yml
2019-05-09 19:40:55 +06:00
```
There is a bunch of parameters we haven't seen yet:
* `strategy`: the strategy of updates of the pods
* `type`: `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.
2019-05-09 19:40:55 +06:00
* `env`: the list of environment variables to pass to the container
* `name`: the name of the env variable
* `value`: the value of the env variable
* `volumeMounts`: the volumes, think directories, to give access to the container
* `name`: the name of the volume to mount
* `mountPath`: where in the container to mount the volume
* `volumes`: the volumes to request access to
* `name`: the name of the volume, same as `volumeMounts.name`
* `persistentVolumeClaim`: the `PersistentVolumeClaim` we want
* `claimName`: the name of the claim
Let's finish by creating a `service` to have stable DNS entry inside our cluster.
2019-05-21 15:10:59 +06:00
```sh
kubectl apply -f 04-simple-mysql-service.yml
2019-05-09 19:40:55 +06:00
```
Finally let's access the mysql:
2019-05-09 19:40:55 +06:00
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:55 +06:00
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:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:55 +06:00
mysql> CREATE DATABASE testing;
Query OK, 1 row affected (0.01 sec)
```
Now delete the service and the deployment:
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:55 +06:00
kubectl delete service,deployment --all
```
Recreate them, reconnect to mysql and see if you still have the database `testing` you created.
## Clean up
2019-05-21 15:10:59 +06:00
```sh
2019-05-09 19:40:55 +06:00
kubectl delete service,deployment,pvc,pv,pod --all
```