feat: add section on volumes

This commit is contained in:
Rémy-Christophe Schermesser 2019-05-09 15:40:55 +02:00
parent 925bc4a4a7
commit 0902fd0bb0
5 changed files with 206 additions and 0 deletions

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv-volume
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View File

@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: 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

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None

144
10-volumes/README.md Normal file
View File

@ -0,0 +1,144 @@
# 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 k8s 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 k8s? Let's deploy a mysql.
## 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'll 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. K8s handles a lot of different kind of volumes - 26 has 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 k8s 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`. Ir 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 cluster resource.
```yaml
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/`
Apply it:
```bash
kubectl apply -f 10-volumes/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.
```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`:
```bash
kubectl apply -f 10-volumes/02-simple-mysql-pvc.yml
```
## Stateful application
Now let's create the `deployment` of mysql:
```bash
kubectl apply -f 10-volumes/03-simple-mysql-deployment.yml
```
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.
* `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.
```bash
kubectl apply -f 10-volumes/04-simple-mysql-service.yml
```
Finally let's access the mysql
```bash
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:
```bash
mysql> CREATE DATABASE testing;
Query OK, 1 row affected (0.01 sec)
```
Now delete the service and the deployment:
```bash
kubectl delete service,deployment --all
```
Recreate them, reconnect to mysql and see if you still have the database `testing` you created.
## Exercices
Nothing to see here.
## Clean up
```bash
kubectl delete service,deployment,pvc,pv,pod --all
```