Cosa sono i Volumes
I Volumes di
Kubernetes sono un tipo di oggetto adatto ad astrarre le memorie secondarie. Abbiamo parlato della possibilità di usare memorie all'interno dei container. Infatti, Docker fornisce dei driver che fungono da volumi e che possono essere attaccati all'interno di un container sotto forma di directory. Tuttavia, le funzionalità di questo strumento sono piuttosto limitate.
Al contrario, Kubernetes mette a disposizione diversi tipi di volumi, che i Pod possono usare in vari modi. Un Pod può anche usare più volumi contemporaneamente. In particolare, distinguiamo tra volumi "persistenti" (persistent volumes) e volumi "effimeri" o volatili (ephemeral volumes): i primi implementano delle vere e proprie memorie secondarie, mentre i secondi vivono insieme ai Pod che li usano.
I Volumi sono in pratica dei dischi virtuali che Kubernetes associa ai servizi, che per definizione sono Stateless, in quanto scalabili. I Volumes possono essere considerati come directory accessibili ai Pod del cluster. Tra i Volumes possono anche esistere file overlapping.
Kubernetes supporta diverse tipologie di Volumi, come File System distribuiti (NFS, CephFS, local, altro ...).
Persistent Volume
I persistent volume sono oggetti di storage persistenti, che vengono usati quando si vuole memorizzare dati in maniera permanente. Possono essere creati e gestiti solo dall'amministratore di sistema, non vengono infatti gestiti da Kubernetes stesso. L'uso dei volumi persistenti all'interno di un Application Server è tipicamente associato allo streaming, ma anche a molti altri contesti applicativi.
Per istanziare un persistent volume, l'amministratore deve fornire una risorsa di storage e creare un oggetto Kubernetes
PersistentVolume
, ad uso degli utenti. Quando un utente fa richiesta per lo storage, viene creato un oggetto dinamico. La creazione dinamica di oggetti Volume è supportata da tutti i cloud provider integrabili con Kubernetes.
Le modalità di utilizzo dei Persistent Volume sono essenzialmente due:
- Allocare spazi di memoria attraverso la specifica di uno o più oggetti
PersistentVolume
- Creare una richiesta tramite un oggetto
PersistentVolumeClaim
. In questo caso, un Pod effettua una richiesta per un PersistentVolume
e il nodo Master si occupa di gestire tale richiesta.
Un Pod può specificare che tipo di volume utilizzare e dove montarlo. In particolare:
- Specifica il tipo di Volume nel campo
spec.volumes
- Specifica dove montare il Volume nel campo
spec.containers.volumeMounts
Possiamo quindi riassumere la creazione e l'utilizzo dei Volumi nel seguente modo:
- L'amministratore di sistema definisce degli spazi di memoria, fisici o virtuali, sul cluster o sul cloud provider.
- Lo sviluppatore, o l'utente, richiede uno spazio di memoria attraverso delle richieste (claim) specificate all'interno del file di Deployment
- Il nodo Master sceglie i Volumi adatti alle richieste e li monta dinamicamente sui Pod deployati.
Creare un Volume
Definiamo un oggetto
PersistentVolume
all'interno di un file
local_volume.yaml
:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
In ordine, abbiamo definito:
kind
: il tipo di oggetto (persistent volume)
metadata
: il nome del disco e un'etichetta che identifica il disco come locale
spec
: le specifiche del disco, che verranno utilizzate per associare il disco ai claim
capacity
: definisce la capacità dello storage
accessMode
: definisce l'accesso alla memoria. In questo caso, abbiamo definito un tipo di accesso ordinato di lettura e scrittura.
hostPath
: specifica la posizione dei dati
Creare richieste per i Volume
I Pod usano gli oggetti
PersistentVolumeClaim per richiedere memoria fisica (o virtuale). Se il nodo Master trova una corrispondenza tra una richiesta e un Volume esistente, instaura una connessione tra il Pod e il Volume. Se non esiste un volume che soddisfi le specifiche della richiesta, il master ritorna un'eccezione.
Definiamo un
PersistentVolumeClaim
come segue, in un file
pvclaim.yaml
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
A questo punto, eseguiamo i seguenti comandi sul terminale per deployare gli oggetti pv-volume e pv-claim. Creiamo prima il Persistent Volume.
$ kubectl create -f local_volume.yaml
Output:
persistentvolume/pv-volume created
Ora creiamo il claim:
$ kubectl create -f pvclaim.yaml
Output:
persistentvolumeclaim/pv-claim created
Infine, verifichiamo gli storage del nostro cluster:
$ kubectl get persistentvolumes
Output:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS AGE
pv-nfs-client 10Mi RWO Delete Bound default/pvc-nfs-client 6d
pv-volume 10Gi RWO Retain Bound default/pv-claim manual 108s
Notiamo che, oltre al volume creato, è già presente il volume del file system di NFS, settato in fase di creazione del cluster.
$ kubectl get persistentvolumeclaims
Output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pv-claim Bound pv-volume 10Gi RWO manual 7m1s
pvc-nfs-client Bound pv-nfs-client 10Mi RWO 6d1h
A questo punto abbiamo creato un Persistent Volume e un Claim. Ora, qualsiasi Pod può sfruttare l'oggetto claim per fare richiesta per un certo tipo di Persistent Volume. Andiamo quindi a definire un nuovo Pod tramite il seguente manifesto YAML, che chiameremo
pv_Pod.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pvPod
labels:
run: pvPod
spec:
replicas: 1
selector:
matchLabels:
run: pvPod
template:
metadata:
labels:
run: pvPod
spec:
containers:
- name: pvPod
image: g1g1/py-kybe:0.2
imagePullPolicy: Always
command: ["/bin/bash","-c","while true; do sleep 10; done"]
volumeMounts:
- name: pv-volume
mountPath: "/mnt/data"
volumes:
- name: pv-volume
persistentVolumeClaim:
claimName: pv-claim
Ora applichiamo il Pod al cluster:
$ kubectl apply -f pv_Pod.yaml
Output:
deployment.apps/pvPod created
Molto bene. Ora possiamo finalmente provare a scrivere e memorizzare un file sul path
/mnt/data
. Per farlo, bisogna eseguire il Pod appena creato. Questo lo si fa tramite il comando kubectl
exec
. Tuttavia, questo comando richiede di specificare il nome esatto assegnato al Pod da Kubernetes.
Per conoscere il nome esatto del Pod eseguiamo:
$ kubectl get Pod | grep pvPod
Vedremo un output del tipo:
Output:
pvPod-6484fd9d45-9j657 1/1 Running 1 2m22s
Per nostra sfortuna, il deployment assegna ai Pod nomi diversi ogni volta che questi vengono rieseguiti. In questo caso ci vengono incontro le Label, che ci permettono di accedere al nome corretto tramite l'etichetta assegnata al Pod, in questo modo:
$ kubectl get Pod -l pvPod -o custom-columns=NAME:.metadata.name
Output:
pvPod-6484fd9d45-9j657
Ora andiamo a eseguire il nuovo Pod, inserendo il nome corretto appena ottenuto:
$ kubectl exec -it pvPod-6484fd9d45-9j657
Ed eseguiamo i seguenti comandi per creare un file all'interno del Volume:
root@pvPod-6484fd9d45-9j657: ls /mnt/data
root@pvPod-6484fd9d45-9j657: cd /data/
root@pvPod-6484fd9d45-9j657: echo "tutorial kubernetes" > kube.txt
root@pvPod-6484fd9d45-9j657: cat kube.txt
Ecco l'output:
tutorial kubernetes
Ora possiamo verificare che il nostro file sia stato creato e inserito nel Volume. Per essere sicuri dell'inserimento, eliminiamo il vecchio Pod e creiamone uno nuovo:
$ kubectl delete Pod pvPod-6484fd9d45-9j657
$ kubectl create -f pv_Pod.yaml
Quindi eseguiamo nuovamente:
$ kubectl get Pod -l pvPod -o custom-columns=NAME:.metadata.name
Output:
pvPod-6484fd9d45-wwtx8
$ kubectl exec -it pvPod-6484fd9d45-wwtx8
root@pvPod-6484fd9d45-wwtx8: cat /mnt/data/kube.txt
Se l'output corrisponde a:
Output:
tutorial kubernetes
Allora l'operazione è avvenuta con successo! Abbiamo montato manualmente il nostro primo storage Kubernetes.
In questa serie abbiamo visto i Volumi di Kubernetes e come definire dei Persistent Volume e richieste per Persistent Volume. I volumi sono oggetti di storage che Kubernetes mette a disposizione degli sviluppatori per creare delle istanze dinamiche di memoria all'interno dei Pod. Un amministratore del cluster può creare dei volumi permanenti fornendo a Kubernetes uno storage esterno, come un file system o uno storage cloud. Nei prossimi capitoli torniamo a parlare di Service Kubernetes e di bilanciamento del carico. Pronti?