Nella lezione precedente, abbiamo visto un'altra modalità per il salvataggio persistente di dati in applicazioni Kubernetes rispetto a quanto già analizzato con i Volume. La struttura che si può realizzare con PersistentVolume
e PersistentVolumeClaim
è una delle modalità più diffuse negli scenari applicativi ma ancora le soluzioni per la persistenza in Kubernetes non sono finite.
In questa lezione, incontriamo lo StatefulSet, un meccanismo che implementa la persistenza in una maniera che ricorda molto i Deployment con la loro capacità di avere delle unità replicate e mantenute: proprio l'abilità di mantenere in vita le repliche desiderate è una delle caratteristiche più distintive del modo di gestire le applicazioni da parte di Kubernetes.
Quello che faremo sarà creare uno StatefulSet basandoci su un'immagine MySQL, per toccare con mano come questo tipo di componente sia in grado di integrare repliche e spazio di Storage: con l'occasione potenzieremo il tutto esponendolo in Rete con un Service ed utilizzando un Secret per proteggere la password del nostro account root
su MySQL.
StatefulSet al lavoro
Ecco il nostro file di esempio a cui attribuiremo il nome mysql-db.yaml
. Come si può osservare esso è composto da più sezioni separate da <code>---</code>
(tale, ricordiamo, è la modalità con cui possiamo integrare più configurazioni YAML in un unico file). Queste contempleranno un Secret, la prima, il Service per la condivisione dello StatefulSet, la seconda, e lo StatefulSet stesso, la terza:
apiVersion: v1
kind: Secret
metadata:
name: mypwd
data:
password: dG9wb2xpbm8=
---
apiVersion: v1
kind: Service
metadata:
name: mysql-db
labels:
app: mysql-db
spec:
type: NodePort
selector:
app: mysql-db
ports:
- port: 3306
nodePort: 31111
targetPort: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-db
spec:
selector:
matchLabels:
app: mysql-db
serviceName: mysql-db
replicas: 2
template:
metadata:
labels:
app: mysql-db
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mysql-db
image: mysql:8
ports:
- containerPort: 3306
name: mysql-db
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mypwd
key: password
volumeMounts:
- mountPath: /var/lib/mysql
name: vol-db
volumeClaimTemplates:
- metadata:
name: vol-db
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
Facciamo subito caso ad un paio di aspetti. Nella configurazione del Secret troviamo il valore password
impostato come dG9wb2xpbm8=
, corrispondente alla versione in codifica Base64 della parola chiave "topolino" del nostro account root
nel server MySQL.
Inoltre, vediamo che abbiamo prima dichiarato un Service chiamato mysql-db
e nella componente StatefulSet troviamo la proprietà serviceName: mysql-db
. Il Service in questione servirà per offrire connettività ai Pod che attuano la persistenza ma dovrà essere specificato mediante la proprietà serviceName
e dovrà essere dichiarato in anticipo.
Lo StatefulSet metterà in campo più repliche (proprietà replicas
) del Pod definito nell'unico template presente nell'area templates
che corrisponderà in questo caso a servizi basati sull'immagine MySQL versione 8. Un aspetto originale che ci mette in relazione con i PersistentVolume
è quanto specificato alla fine del file, nella sezione volumeClaimTemplates
dove sarà definito il volume vol-db
che, poche righe più in alto, sarà agganciato al template del Pod e definirà esattamente lo Storage che
vogliamo implementare.
L'esempio alla prova
Per il momento con la definizione delle componenti ci fermiamo qui in attesa di ulteriori aspetti che saranno più chiari quando parleremo di Kubernetes nel Cloud. Le componenti possono essere avviate con:
$ kubectl apply -f mysql-db.yaml
Dopo alcuni secondi avremo operativi i Pod messi in piedi dallo StatefulSet:
$ kubectl get sts
NAME READY AGE
mysql-db 2/2 2m21s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-db-0 1/1 Running 0 2m24s
mysql-db-1 1/1 Running 0 2m11s
Notiamo che ogni Pod replicato avrà un nome identico allo StatefulSet con la sola aggiunta di un numero progressivo come suffisso (mysql-db-0
e mysql-db-1
).
Potremo ora connetterci al nostro gestore di database sfruttando il Service. Si noti, a proposito, che abbiamo definito il Service come NodePort
e specificato al suo interno la proprietà nodePort: 31111
. Pertanto la connessione con MySQL sarà disponibile all'indirizzo (siamo su minikube):
$ minikube service mysql-db --url
http://192.168.49.2:31111
e nella disponibilità di un client mysql
potremo connetterci ad esso con:
$ mysql -h 192.168.49.2 --port=31111 -u root -p
Enter password:
Da qui si immetterà la password ("topolino" per noi) e daremo il via alla sperimentazione.