kubernetes volumes

in Architetture Software, Informatica

Kubernetes – Volumes

Reading Time: 4 minutes

Lo storage associato ad un container è limitato al suo ciclo di vita: in pratica al momento del riavvio di un container i dati presenti al suo interno vengono persi. Durante la creazione del container, il suo running e la sua terminazione, i dati che sono stati gestiti all’interno del suo file system, vengono cancellati.

Ad una prima occhiata, questo tipo di comportamento può essere considerato anomalo, ma se si pensa alla vera natura del container, può avere senso. Il container è di fatto un istanza di un immagine (scaricata da un repository). Di fatto all’interno del container sono memorizzati i dati che sono stati definiti all’interno dell’immagine stessa.

Docker e i database

In generale docker non progettato per eseguire container con stato: uno dei principali vantaggi dell’utilizzo dei container è quello di poterli avviare e spegnere come si vuole, agganciando fonti dati esterne, come i database.

Per poter gestire lo stato di un container, docker mette a disposizione volume e bind mount. Questi due meccanismi consentono di memorizzare dati all’interno della macchina su cui vengono eseguiti i container. Utilizzando il concetto di mount, una porzione del disco della macchina ospitante “montata” all’interno del container, e quindi disponibili in caso di riavvii successivi.

L’utilizzo del mount di volumi sono il modo migliore per creare uno storage: consentono di creare un volume a cui il container ha accesso.

I bind mount sono molto piu’ semplici e utilizzano i volumi per funzionare. Offrono un’interfaccia piu’ ad alto livello. Consentono di impostare manualmente la mappatura tra la porzione del disco dell’host e il container stesso.

L’utilizzo di entrambi può generare non pochi problemi al momento della pubblicazione dei container all’interno di un ambiente di produzione. Non sempre (anzi, quasi mai) è possibile accedere a queste porzioni di volumi lato server. In pratica il server non consente di effettuare il mount diretto del suo storage allo strato dei container.

Solitamente le soluzioni che vengono adottate sono l’utilizzo di un servizio ECS, oppure nel caso di database di servizi database cloud (es. RDS).

Docker e i database

A questo punto una domanda: “Dove posizionare un database? All’interno di un container?”. La risposta, in generale, è no. Docker porta numerosi vantaggi all’infrastruttura tecnica: scalabilità, integrazione con strumenti CI/CD (build automatizzate) e definizione dell’architettura tramite YAML File.

La maggior parte di questi vantaggi non è facilmente adattabile alle specifiche di un database. Se stiamo cercando qualcosa che consenta di liberarci dalla complessità dell’utilizzo dei database, docker probabilmente non è la strada corretta.

Con molta probabilità, l’utilizzo di un database-as-service completamente gestito nel cloud, risulta essere la soluzione migliore.

L’utilizzo di un database all’interno di un container può essere indicato all’interno di ambienti di sviluppo, dove trova il suo scenario ideale. Docker semplifica la creazione di database con configurazione differente e per la realizzazione di test applicativi.

Kubernetes e lo stato

Per poter fornire uno “stato” o meglio per voler persistere dei dati utilizzando i container, Kubernetes mette a disposizione il concetto di Volume. Un volume è di fatto un oggetto posizionato all’esterno del container e che è dotato di persistenza. Il container accede al volume, può memorizzare dati al suo interno, ma al momento della sua terminazione, i dati saranno ancora presenti all’interno del volume.

Se in futuro verrà eseguito un nuovo container che farà uso di quello specifico volume, troverà al suo interno i valori salvati in precedenza.

La documentazione ufficiale sul portale di Kubernetes su PersistentVolume è descritta qui.

Per la gestione dei volumi, Kubernetes mette a disposizione due oggetti:

  • Persistent Volume
  • Persistent Volume Claim

Il Persistent Volume è una porzione dello storage del cluster, e che viene messo a disposizione utilizzando le StorageClass. Considerando la natura di tutti gli oggetti fin qui analizzati, possiamo considerare il Persistent Volume, come un oggetto come ad esempio i services. I Persistent Volume hanno una propria autonomia: non dipendono in pratica dal ciclo di vita del pods che ne fa uso. Possiamo astrarre il concetto di PersistentVolume come la porzione di spazio nel cluster che qualcuno che ha messo a dispozione per i Pods: questo qualcuno solitamente è l’amministratore del cluster.

Il Persistent Volume Claim è una richiesta di archiviazione in una determinata risorsa di storage precedentemente dichiarata(persistent volume). Come nel caso del Persistent Volume, anche il Persistent Volume claim ha una vita propria, e si comporta a tutti gli effetti come un Pod. Un PVC è in pratica una richiesta di utilizzo di un PV creato precedentemente dall’amministrazione del cluster. Nello specificare le caratteristiche di un claim vengono anche richieste le dimensioni effettive che dovranno essere acquisite e le caratteristiche del volume richiesto. Ad esempio, nella fase di definizione tramite yaml file di un persistent volume claim è possibile specificare la modalità di accesso allo storage (es. read-only).

Persistent Volume e Persistent Volume Claim

Per poter definire i PersistentVolume e i PersistentValumeClaim è necessario definire i due relativi oggetti all’interno dello yaml file. Nell’esempio seguente viene definito un PersistentVolume di dimensione 1Gb.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume-1
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

Nella modalità di accesso è stato indicato ReadWriteOnce, che significa che solo un Nodo può accedere alla risorsa in modalità read/write. Inoltre è stato indicato il path che deve essere utilizzato per l’allocazione.

Dopo la definzione di un PersistentVolume, è necessario definire il relativo PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

utilizzato per poter usare il volume richiamandolo dal claim.