Kasten K10 – Repository NFS e Policy di Backup

Dopo aver completato l’installazione di Kasten K10 sul cluster Kubernetes, il passo successivo è configurare una destinazione dove salvare i backup e creare la prima policy di protezione.

In questo articolo vedremo una configurazione minimale ma funzionante, utilizzando una share NFS come repository di backup.

Prerequisiti

  • Cluster Kubernetes funzionante
  • K10 installato
  • accesso alla console K10
  • una share NFS accessibile dal cluster

Nel laboratorio utilizzo una share NFS Western Digiatal che espone le proprie risorse al seguente indirizzo: 192.168.16.92:/mnt/HD/HD_a2/kasten-nfs.

Al fine di verificarne  i mount point esposti è necessario lanciare il comando  showmount -e 192.168.16.92  da qualsiasi nodo del cluster.
Per verificare successivamente che tale share sia disponibile seguite la seguente procedura sul nodo che preferite:

sudo mkdir -p /mnt/k10-nfs-test

sudo mount -t nfs -o vers=3 \
192.168.16.92:/mnt/HD/HD_a2/kasten-nfs \
/mnt/k10-nfs-test

Test:

Touch /mnt/k10-nfs-test/file-test.txt

Il repository è ora utilizzabile.

Ora passiamo alla console di K10 e aggiungiamo una Location Profile:

Aprire la dashboard di K10 e nel seguente percorso:

Settings
→ Location Profiles
→ Create New

Selezionate come provider NFS/SMB e configurate i parametri come indicato nella tabella sottostante:

parametro valore
Name nfs-wd
Server 192.168.16.92
Path /mnt/HD/HD_a2/kasten-nfs

Salvate la configurazione.

La Location Profile rappresenta la destinazione dove K10 esporterà le snapshot dei backup appena effettuati.

Nota: nel laboratorio per una pura necessità didattica ho utilizzato una configurazione kubernetes approach. Ho cioè creato una Storage Class NFS che permettesse la creazione di PV e PVC da utilizzare per l’export dei backup.

Creazione policy di Backup

Policies
→ Create Policy

Configurazione minimale:

parametro valore
Policy Type Backup
Namespace default (o quello desiderato)
Frequency Manual o Daily
Snapshot Enabled
Export Enabled

Nel campo Export Location selezionare il location profile appena creata:

Avvio del primo backup

Dopo aver salvato la policy è possibile avviarla manualmente selezionando Run Once

K10 eseguirà:

  • Snapshot dei volumi
  • Esportazione dei dati sul repository NFS

Lo stato può essere monitorato nella Dashboard

Conclusione

Con pochi passaggi è possibile configurare una protezione di base per il cluster Kubernetes.

La combinazione di:

  • snapshot storage
  • export su repository NFS
  • policy schedulate

permette di implementare rapidamente una strategia di backup e recovery per le applicazioni containerizzate.

LLM in locale con Kubernetes e Ollama

L’intelligenza artificiale sta diventando sempre più presente nelle moderne architetture.

Tuttavia, molte organizzazioni preferiscono eseguire i modelli AI in locale, evitando di inviare dati sensibili a servizi cloud esterni.

In questo articolo vedremo come eseguire un Large Language Model (LLM) all’interno di un cluster Kubernetes utilizzando Ollama, una piattaforma che consente di gestire ed eseguire modelli linguistici direttamente on-premise.

L’obiettivo è integrare un modello AI locale nel laboratorio Kubernetes, mantenendo il pieno controllo su infrastruttura e dati.

Perché Ollama

Ollama è un runtime leggero progettato per eseguire modelli linguistici in modo semplice e rapido.

Le sue principali caratteristiche sono:

  • esecuzione di modelli LLM in locale.
  • nessuna dipendenza da servizi cloud esterni.
  • API REST semplici da integrare.
  • gestione dei modelli con pochi comandi.
  • runtime leggero e facilmente containerizzabile.

Queste caratteristiche rendono Ollama una soluzione ideale per esperimenti AI in ambienti Kubernetes.

Architettura dello stack AI

Nel laboratorio K8s lo stack AI è composto da tre componenti principali:

  • Ollama → L’ incubatore per il modello linguistico. Vedetelo come un hypervisor per LLM: non virtualizza sistemi operativi, ma fornisce l’ambiente necessario per eseguire modelli AI in locale.
  • Open WebUI → Fornisce un’interfaccia web per interagire con il modello.
  • Qdrant → Database vettoriale utilizzato per scenari RAG.

Il flusso è il seguente:

Utente


OpenWebUI


API Ollama


Modello LLM locale

Questa tipologia di architettura permette di costruire assistenti AI completamente locali, senza dipendere da provider esterni.

Deploy di Ollama in Kubernetes

La runtime Ollama può essere distribuito come un normale deployment Kubernetes.

Esempio di deployment:

È poi necessario esporre il servizio all’interno del cluster:

Una volta avviato il deployment, l’API Ollama sarà raggiungibile all’interno del cluster Kubernetes.
Installazione di un modello

Ollama permette di scaricare i modelli direttamente dal proprio registry.

Nel lab ho scelto il modello Qwen 2.5 1.5B che ho installato con il seguente comando:

  • kubectl -n ai exec deploy/ollama ollama pull qwen2.5:1.5b
Il modello viene scaricato e salvato all’interno del container Ollama.
Per conoscere i modelli installati:
  • kubectl -n ai exec deploy/ollama ollama list

Verifica dell’API Ollama

Ollama espone via API REST; può essere interrogata per verificare i modelli disponibili:

  • curl http://ollama:11434/api/tags

Risposta:

E’ la conferma che il modello è stato caricato correttamente.

Collegare un’interfaccia Web

Al fine di semplificare l’interazione con il modello è possibile installare la Open WebUI che fornisce:

  • interfaccia tipo ChatGPT
  • selezione del modello
  • cronologia delle conversazioni
  • integrazione con database vettoriali

L’interfaccia comunica con Ollama utilizzando l’endpoint:

  • http://ollama:11434
Il vantaggio è che una volta configurato, è possibile utilizzare il modello direttamente dal browser.

Perchè utilizzare un LLM locale in k8s?

Utilizzare i modelli linguistici localmente apre diversi scenari interessanti quali ad esempio:

  • assistenti AI interni aziendali
  • ricerca documentale avanzata
  • copiloti per applicazioni interne
  • integrazione AI in architetture a microservizi

Ciò permette di mantenere controllo completo su infrastruttura, dati e ciclo di vita dei modelli.

Nel prossimo articolo estenderemo lo stack AI introducendo Retrieval Augmented Generation (RAG) utilizzando Qdrant.

Installazione di Kasten K10 su Kubernetes: guida passo-passo

Installare Kasten K10 in un cluster Kubernetes è un’operazione semplice, ma richiede alcune verifiche preliminari fondamentali, specialmente lato snapshot e CSI driver.

In questo articolo vedremo:

  • Verificare prerequisiti con script ufficiale
  • Installazione di K10
  • Etichettatura delle SnapshotClass
  • Avvio e verifica finale

Verifica prerequisiti con k10_primer

Prima di installare K10 è obbligatorio verificare che il cluster sia pronto.

Kasten fornisce uno script ufficiale chiamato k10_primer.sh.

curl https://docs.kasten.io/downloads/8.0.4/tools/k10_primer.sh | bash

Lo script verifica:

  • La presenza del CSI driver (nel mio caso synology)
  • Snapshot CRD installate
  • VolumeSnapshotClass disponibili
  • Permessi RBAC
  • Storage supportato
  • Compatibilità Kubernetes

Output attesoCluster meets K10 requirements

Se compaiono dei warning o errori in particolare sulle snapshot, bisogna riconfigurare correttamente la SnapshotClass come indicato ad esempio nella nota 1.

Installazione di K10

Aggiungere il repository Helm:

  • helm repo add kasten https://charts.kasten.io/
  • helm repo update

Creare il namespace:

  • kubectl create namespace kasten-io

Installazione di K10:

  • helm install k10 kasten/k10 \
  • –namespace kasten-io

Per verificare lo stato dei pod avviare il semplice comando:

  • kubectl -n kasten-io get pods

Quando tutti i pod sono Running, K10 è operativo.

Nota 1: Etichettare la VolumeSnapshotClass

Affinché K10 possa utilizzare le snapshot CSI, è necessario etichettare la VolumeSnapshotClass attraverso dapprima la verifica che le snapshotclass siano disponibili:

  • kubectl get volumesnapshotclass

Dopo averle individuate (nel mio laboratorio sono indicate come Synology iSCSI), devono essere etichettate con il comando:

  • kubectl label volumesnapshotclass <NOME_SNAPSHOTCLASS> \
  • k10.kasten.io/is-snapshot-class=true

Questa label è fondamentale: senza di essa K10 non utilizzerà quella snapshot class per i backup.

Verifica: kubectl get volumesnapshotclass –show-labels

Avvio e accesso a K10

Come ogni microservizio è possibile esporre k10 via LoadBalancer o Ingress.

Dopo aver indivuduato il servizio k10 (kubectl -n kasten-io get svc gateway) lanciate i corretti comandi per esporre il servizio K10.

Dalla dashboard verificate che:
  • Lo storage venga rilevato
  • Le snapshot siano disponibili

Ora è possibile creare una prima policy di test che sfrutti unicamente le snapshot come primo repository.

In un prossimo articolo mostreremo come aggiungere attraverso le location profile un repository.

Conclusione

L’installazione di Kasten K10 è lineare, ma la parte critica è:

  • Verificare preliminare con k10_primer
  • Configurazione corretta delle SnapshotClass

Ricostruire un Cluster RKE2 con Storage Synology CSI + Snapshot

L’obiettivo del presente articolo è illustrare come realizzare un cluster Kubernetes basato su RKE2, con la seguente architettura:

Reinstallazione Pulita di RKE2

Dopo i test precedenti, al fine di avere una situazione pulita ho deciso di ripartire da zero.

Disinstallazione completa

Su ogni nodo:

  • sudo /usr/local/bin/rke2-uninstall.sh
  • sudo rm -rf /var/lib/rancher /var/lib/kubelet /etc/cni /var/lib/cni /opt/cni

Pulizia mount iSCSI eventualmente attivi:

  • sudo umount -l /var/lib/kubelet/plugins/kubernetes.io/csi/*/*/globalmount

Reboot nodi.

Installazione RKE2 Server (Management Node)

Configurazione /etc/rancher/rke2/config.yaml:

  • write-kubeconfig-mode: “0644”
  • tls-san:
  •   – “IP”
  • node-ip: “IP”

In Kubernetes (k8s), TLS SAN è l’acronimo di  Subject Alternative Name. E’ un’estensione del certificato SSL/TLS X.509 utilizzata per specificare molteplici nomi host (DNS) o indirizzi IP validi per un singolo certificato

Installazione:

  • curl -sfL https://get.rke2.io | sh –
  • sudo systemctl enable rke2-server –now

Esportazione kubeconfig:

  • export KUBECONFIG=/etc/rancher/rke2/rke2.yaml

Join Worker Nodes

Su ciascun worker:

  • curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=”agent” sh –

All’interno del file di configurazione /etc/rancher/rke2/config.yaml è necessario aggiungere le voci server e il token di accesso

  • server: https://ip-management:9345
  • token: <server_token>

NB: per generare il token sul management lanciare il comando:

  • sudo cat /var/lib/rancher/rke2/server/node-token

Avvio: sudo systemctl enable rke2-agent –now

Al fine di separare i diversi ruoli nel cluster conviene assegnare delle label ai worker con i seguenti comandi:

  • kubectl label node nuc-01 workload=apps
  • kubectl label node nuc-02 workload=apps
  • kubectl label node nuc-03 workload=apps

Taint Management: Il taint (macchia/marchio) di Kubernetes è una proprietà applicata a un nodo per “respingere” i pod, impedendo loro di pianificarvi sopra a meno che non abbiano una specifica toleration (tolleranza). Nel nostro caso viene applicato al nodo di mangement.

  • kubectl taint nodes nuc-mng node-type=management:NoSchedule

Risultato: Nessun microservizio girerà sul management, lo scheduling è forzato sui worker

Ingress NGINX: Un controller Kubernetes Ingress è un componente software specializzato che gestisce il traffico in entrata verso le applicazioni in esecuzione 

Installazione via Helm:

  • helm install ingress-nginx ingress-nginx/ingress-nginx \
  •   –namespace ingress-nginx \
  •   –create-namespace \
  •   –set controller.nodeSelector.workload=apps

Cert-Manager: cert-manager è un add-on open-source per Kubernetes che automatizza la gestione, l’emissione e il rinnovo dei certificati TLS/SSL

Installazione CRD:

  • kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.crds.yaml
  • Installazione Helm (disabilitando startupapicheck nel lab):
  • helm install cert-manager jetstack/cert-manager \
  •   –namespace cert-manager \
  •   –create-namespace \
  •   –set startupapicheck.enabled=false \
  •   –set nodeSelector.workload=apps

Installazione Synology CSI Driver

E’ necessario che ogni singolo worker veda via iSCSI lo storage in modo che il comando sudo iscsiadm -m discovery -t sendtargets -p <IP_NAS> mostri i target.

Per installare il csi driver:

  • git clone https://github.com/SynologyOpenSource/synology-csi.git
  • cd synology-csi

Nella cartella

Modificare il file ~/synology-csi/config/client-info.yaml inserendo le credenziali richieste

Creare un secret:

kubectl -n kube-system create secret generic synology-csi-secret \
–from-literal=username='<DSM_USER>’ \
–from-literal=password='<DSM_PASSWORD>’

e per ultimo caricare il config.yaml nel config map:

kubectl -n kube-system create configmap synology-csi-config \
–from-file=config.yml=./config.yml

Gli ultimi passaggi sono quelli di creare una Storage Class (sc) e una Volume Snapshot Class al fine di rendere il cluster k8s in grado di:

  • Gestire snapshot nativi
  • Ripristini di PVC da snapshot
  • Pronto per integrazione con Kasten K10

🏁 Stato Finale del Cluster

✔ RKE2
✔ Calico
✔ Ingress NGINX
✔ Cert-Manager
✔ Synology CSI (iSCSI)
✔ Snapshot Kubernetes
✔ Separazione Management / Workload

Prossimi step: 

  • Kasten K10
  • Disaster Recovery test
  • AI workload
  • Database stateful

Snapshot e protezione dei dati

Con lo storage ormai integrato nel cluster, il passo successivo è  “salvare dati”, anche se preferisco la dizione proteggerli.
In questo capitolo il desiderio è stato quello di far passare il laboratorio da semplice piattaforma Kubernetes a sistema resiliente.

Perché gli snapshot sono fondamentali

In Kubernetes i dati vivono dentro volumi persistenti (PVC), ma senza snapshot:

  • non puoi fare rollback
  • non puoi fare restore veloci
  • non puoi garantire recovery point affidabili

Gli snapshot sono l’equivalente moderno dei checkpoint delle macchine virtuali, ma applicati ai volumi containerizzati.

Snapshot CSI: la base tecnologica

Tramite Il CSI driver di Synology, il cluster ha ottenuto una nuova capacità:

K8s può chiedere allo storage di creare snapshot dei volumi.

Questo introduce tre nuove entità:

  • VolumeSnapshotClass
  • VolumeSnapshot
  • VolumeSnapshotContent

Non sono file.
Sono oggetti Kubernetes che rappresentano snapshot reali creati sul NAS.

Il legame tra Kubernetes e Synology

Quando Kubernetes crea un VolumeSnapshot:

  • Il CSI driver invia la richiesta al Synology
  • Il NAS crea uno snapshot iSCSI nativo
  • Kubernetes riceve l’ID dello snapshot
  • Il VolumeSnapshot diventa ReadyToUse

A questo punto lo snapshot è:

  • consistente (non da un punto di vista applicativo)
  • puntuale
  • indipendente dal pod

Ed è pronto per essere usato per backup o restore.

Validazione degli snapshot

Nel laboratorio è stato creato un PVC di test con dati scritti da un pod.
Da lì sono stati generati snapshot CSI e verificato che:

  • esistono nel NAS
  • sono visibili come oggetti Kubernetes
  • possono essere usati per creare nuovi volumi

Questo ha dimostrato che lo storage era snapshot-aware, requisito essenziale per Kasten K10.

Perché questo passaggio è cruciale per il backup

Kasten K10 non lavora direttamente con i filesystem ma lavora con Snapshot CSI consistenti.

Senza questa aggiunta, Kasten avrebbe potuto solo fare backup “file based”, con gli snapshot, invece è possibile effettuare:

  • backup istantanei
  • consistenza applicativa
  • restore rapidi

È qui che nasce la vera data protection cloud-native.

Risultato

Alla fine di questo step il cluster possiede:

  • Storage persistente
  • Snapshot nativi
  • API Kubernetes per gestirli

Il laboratorio è pronto per introdurre un altro protagonista:
Kasten K10.

Storage e k8s cluster

Con il cluster Kubernetes operativo, il passo successivo è quello di gestire la cosa più critica di tutte i dati.

Un cluster senza storage persistente è solo una piattaforma di calcolo.
Un cluster con storage condiviso diventa invece una piattaforma applicativa reale 🙂

Il problema da risolvere

Le applicazioni Kubernetes non possono dipendere dai dischi locali dei nodi:

  • un pod può spostarsi da un nodo all’altro
  • un nodo può spegnersi
  • un container può essere ricreato

Quindi se i dati restano legati al nodo, vengono persi.

Serve quindi uno storage:

  • condiviso tra i nodi
  • persistente
  • gestito dinamicamente da Kubernetes

Lo storage esterno: Synology e WD

Nel laboratorio erano disponibili due sistemi di storage esterni:

  • Synology → usato come storage primario con supporto iSCSI e snapshot
  • WD NAS → usato come repository NFS per la seconda copia (backup)

Integrazione dello storage con Kubernetes

Per permettere a Kubernetes di usare lo storage Synology come se fosse nativo, è stato installato:

  • CSI Driver di Synology
  • Snapshot Controller CSI

Questi componenti trasformano lo storage fisico in risorse Kubernetes:

  • PersistentVolumes
  • PersistentVolumeClaims
  • VolumeSnapshots

In pratica, Kubernetes ha iniziato a parlare direttamente con il NAS, senza script o mount manuali.

Le StorageClass

Una volta installato il driver, sono state create le StorageClass, che definiscono:

  • tipo di storage (iSCSI)
  • policy di cancellazione
  • supporto snapshot

Ogni applicazione che richiede storage non chiede più “un disco”, ma chiede una Storage Class con determinate caratteristiche.

Ed è K8s, tramite il CSI driver, che crea automaticamente i volumi sul NAS.

Verifica con PV, PVC e Pod

Per validare l’integrazione sono stati creati:

  • un PVC (PersistentVolumeClaim)
  • un PV (creato dinamicamente dal NAS)
  • un Pod di test che scrive dati sul volume

In quel momento è stato verificato che:

  • il volume esiste realmente sul Synology
  • il pod può scrivere dati
  • i dati sopravvivono al riavvio del pod

Questo è stato il primo vero test di persistenza reale del cluster.

Risultato

Il cluster è diventato un cluster Kubernetes con storage condiviso.

Ora il sistema era pronto per:

  • snapshot
  • backup
  • restore
  • disaster recovery

Prossimo capitolo, usare Kasten K10 per proteggere l’ambiente.