Storaggio
Kubernetes supporta numerosi tipi di storaggio: iSCSI, SMB, NFS, object storage blobs, ecc. I fornitori (Provisioner) di storaggio possono essere in-house o nel cloud.
E' necessario che Kubernetes installi un plugin per supportare lo storaggio specifico, fornito dal Provisioner.
Il plugin deve essere conforme allo standard CSI - Container Storage Interface.
Purtroppo i cluster Kind e Minikube non supportano questa funzionalità e sono limitati allo storaggio Standard - locale, o NFS visto come directory locale.
Per esempio un cluster è implementato su AWS e l'amministratore di AWS ha creato un volume di 25GB chiamato ebs-vol. L'amministratore di Kubernetes crea un PV chiamato k8s-vol collegato al volume ebs-vol dal plugin kubernetes.io/aws-ebs
.
Sistema Persistent Volume
Le tre risorse principlali del sistema Persistent Volume sono:
- Persistent Volume (pv)
- Persistent Volume Claim (pvc)
- Storage Class (sc)
I passi in Kubernetes sono:
- Creare il PV
- Creare il PVC
- Definire il volume nelle specifiche di un Pod
- Montarlo in un container
Esempio di creazione di PV.
vim gke-volume.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
accessModes:
- ReadWriteOnce
storageClassName: test
capacity:
storage: 10Gi
persistentVolumeReclaimPolicy: Retain
gcePersistentDisk:
pdName: user-disk
Il PV è altamente specifico al Provisioner. Per esempio l'attributo gcePersistentDisk
si riferisce a Gookle e ha bisogno della presenza del plugin GCE. Il volume user-disk deve essere stato creato prima da GCE.
Anche la storage class di nome test è creata altrove.
Questo è solo un esempio illustrativo, non funziona col nostro cluster.
L'effetto graficamente espresso sarebbe:
La proprietò .spec.persistentVolumeReclaimPolicy
dice a Kubernetes cosa farne del disco PV quando non è più in uso.
Due possibilità:
Delete
Retain
Retain
ne conserva i dati, ma non sono più accessibili da un altro PVC in futuro. Il PV deve essere rimosso a mano.
Un PVC corrispondente a questo PV sarebbe ad esempio:
vim gke-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteOnce
storageClassName: test
resources:
requests:
storage: 10Gi
Vi sono alcune proprietà che devono essere in corrispondenza:
Un pod che usa questo PVC potrebbe essere:
vim volpod.yml
apiVersion: v1
kind: Pod
metadata:
name: volpod
spec:
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc1
containers:
- name: ubuntu-ctr
image: ubuntu:latest
command:
- /bin/bash
- "-c"
- "sleep 60m"
volumeMounts:
- mountPath: /data
name: data
Dynamic Provisioning
Il Dynamic Provisioning è la fornitura da parte del Provider di spazio disco on-demand, quando c'è un Pod che effettivamente lo usa.
Questa funzionalità è basata sul concetto di Storage Class.
Storage Class
Una StorageClass è una risorsa definita nel gruppo API storage.k8s.io/v1
. Si riferisce ad un tipo di storaggio offerto da un Provisioner.
Esempio.
vim fast-sc.yml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
zones: eu-west-1a
opsPerGB: "10"
Sottomettere il manifest:
kubectl apply -f fast-sc.yml
Si visionano le storage classes con:
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
fast kubernetes.io/aws-ebs Delete Immediate false 19s
standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 42h
La storage class viene creata anche se il plugin non è disponibile. E' solo al momento di creazione del PVC e Pod che si presentano dei problemi.
Si possono avere molte Storage Classee configurate. I parametri di ciascuna dipendono dal plugin del provisioner.
Per esempio:
vim sc-secure.yml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: portworx-db-secure
provisioner: kubernetes.io/portworx-volume
parameters:
fs: "xfs"
block_size: "32"
repl: "2"
snap_interval: "30"
io-priority: "medium"
secure: "true"
Una StorageClass è un oggetto immutabile. Non si può modificare, solo cancellare e ricreare.
Le fasi d'uso sono:
- Creare il cluster Kubernetes
- Installare i necessari plugin per lo storage
- Creare una StorageClass
- Creare un PVC che si riferisce alla StorageClass
- Creare un Pod che usa un volume basato sul PVC
Non occorre quindi creare un oggetto PV, che è sostituito dalla StorageClass.
Esercizio Demo
Creare una StorageClass
Preparare la directory e creare il file di manifest:
mkdir -p ~/ex/sc
cd ~/ex/sc
vim google-sc.yml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: slow
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
reclaimPolicy: Retain
Applicare il file di manifest:
kubectl apply -f google-sc.yml
Verifica:
kubectl get sc
kubectl describe sc slow
Creare un PVC
Il file di manifest:
vim google-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-ticket
spec:
accessModes:
- ReadWriteOnce
storageClassName: slow
resources:
requests:
storage: 25Gi
Applicare il file di manifest:
kubectl apply -f google-pvc.yml
Verificare:
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pv-ticket Pending slow 3s
Notare lo stato Pending
. Non abbiamo il driver CSI installato ed è in attesa che venga installato.
Ctreare un Pod
Il file fi manifest:
vim google-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: class-pod
spec:
volumes:
- name: data
persistentVolumeClaim:
claimName: pv-ticket
containers:
- name: ubuntu-ctr
image: ubuntu:latest
command:
- /bin/bash
- "-c"
- "sleep 60m"
volumeMounts:
- mountPath: /data
name: data
Applicare il file di manifest:
kubectl apply -f google-pod.yml
Verifica:
kubectl get pod
NAME READY STATUS RESTARTS AGE
class-pod 0/1 Pending 0 56s
Anch'esso è nello stato Pending
.
Ispezionandolo con:
kubectl describe pod class-pod
Notiamo che:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 3m5s default-scheduler 0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling.
Di più non possiamo fare con Kind.
Ripoliamo l'esercizio:
kubectl delete -f google-pod.yml
kubectl delete -f google-pvc.yml
kubectl delete -f google-sc.yml