Kubestr et CNPG Bench pour tester vos volumes persistants
Testez la performance de vos Volumes Persistants avec 2 outils; kubestr et cnpg-bench

"C'est lent", "Ça marche mieux sur mon poste local", des remarques que j'ai eues il y a quelque temps sur des bases de données hébergées sur Kubernetes, avec des Volumes Persistants. Souhaitant avoir des données objectives avant de râler contre ceux qui se plaignent, j'ai trouvé 2 outils sympa pour tester les performances des PV (Persistant Volumes) sur mes clusters. Voici un aperçu.
Note : Je ne vais pas expliquer ici comment tuner vos disques, ni tuner les applications de test pour optimiser les perfs.
Kubestr
Kubestr est une collection d'outils pour "découvrir, valider et évaluer les options de stockages sur Kubernetes". C'est un outil fournit par Kasten, un des leaders des solutions de protection des données en environnement Kubernetes.
Parmi les outils proposés par kubestr, on retrouve le fameux fio, que les "vieux" sysadmin comme moi connaissent. Pour faire simple, fio va faire des tests de lecture / écriture avec plusieurs paramètres, et en sortir des stats.
Ainsi, kubestr va nous permettre assez simplement de :
- Créer un volume de taille définie à partir d'une classe de stockage choisie
- Lancer un test de performances avec FIO
- Nous donner les résultats.
Un schéma repris du blogpost de Kasten expliquant le process :

Installation
Kubestr est un binaire qui se télécharge directement depuis la page de releases GitHub. À la date d'écriture de l'article, nous sommes à la version v0.4.41. On récupère l'archive, on la décompresse et on lui donne les droits d'exécution :
$ curl -LJO https://github.com/kastenhq/kubestr/releases/download/v0.4.41/kubestr_0.4.41_Linux_amd64.tar.gz
$ tar zxvf kubestr_0.4.41_Linux_amd64.tar.gz kubestr
$ chmod +x kubestr
$ ./kubestr --help
kubestr is a tool that will scan your k8s cluster
and validate that the storage systems in place as well as run
performance tests.Utilisation
Il existe plusieurs options d'utilisation de l'outil, ce qui nous intéresse ici est le module "FIO". Plusieurs options de lancement sont possibles, notamment :
-f, --fiofile: un fichier de configuration fio. On pourra trouver des exemples ici-z, --size: taille du volume qui sera créé. Selon les providers, les I/O dépendent de la taille du volume (exemple avec le High Speed Gen2 de chez OVHCloud)-s, --storageclass: type de StorageClass du volume persistant utilisé pour le test
Pour l'exemple, on va tester les 2 types de classe de stockage par défaut d'un cluster OVHCloud, avec un volume de 25Gb.
$ ./kubestr fio -z 25Gi -s csi-cinder-high-speed
PVC created kubestr-fio-pvc-wn4f6
Pod created kubestr-fio-pod-hxfvs
Running FIO test (default-fio) on StorageClass (csi-cinder-high-speed) with a PVC of Size (25Gi)
Elapsed time- 1m20.178437269s
FIO test results:
FIO version - fio-3.34
Global options - ioengine=libaio verify=0 direct=1 gtod_reduce=1
JobName: read_iops
blocksize=4K filesize=2G iodepth=64 rw=randread
read:
IOPS=1412.357544 BW(KiB/s)=5666
iops: min=1220 max=1724 avg=1427.666626
bw(KiB/s): min=4880 max=6896 avg=5711.066895
JobName: write_iops
blocksize=4K filesize=2G iodepth=64 rw=randwrite
write:
IOPS=825.023193 BW(KiB/s)=3316
iops: min=462 max=1292 avg=827.566650
bw(KiB/s): min=1848 max=5170 avg=3310.566650
JobName: read_bw
blocksize=128K filesize=2G iodepth=64 rw=randread
read:
IOPS=1657.303345 BW(KiB/s)=212667
iops: min=1490 max=1858 avg=1671.933350
bw(KiB/s): min=190720 max=237824 avg=214017.406250
JobName: write_bw
blocksize=128k filesize=2G iodepth=64 rw=randwrite
write:
IOPS=862.746399 BW(KiB/s)=110966
iops: min=692 max=1298 avg=865.000000
bw(KiB/s): min=88576 max=166144 avg=110755.734375
Disk stats (read/write):
sdb: ios=51692/28087 merge=445/670 ticks=2147425/2151581 in_queue=4303451, util=99.532051%
- OKLa même commande sur une StorageClass "classic" :
$ ./kubestr fio -z 25Gi -s csi-cinder-classic
PVC created kubestr-fio-pvc-8pnmw
Pod created kubestr-fio-pod-z9bnn
Running FIO test (default-fio) on StorageClass (csi-cinder-classic) with a PVC of Size (25Gi)
Elapsed time- 41.494978608s
FIO test results:
FIO version - fio-3.34
Global options - ioengine=libaio verify=0 direct=1 gtod_reduce=1
JobName: read_iops
blocksize=4K filesize=2G iodepth=64 rw=randread
read:
IOPS=120.751854 BW(KiB/s)=498
iops: min=44 max=184 avg=123.064514
bw(KiB/s): min=176 max=736 avg=492.354828
[...]
Disk stats (read/write):
sdb: ios=4468/2655 merge=8/151 ticks=2224172/1996479 in_queue=4222117, util=99.475037%
- OKL'application a créé à chaque fois un PVC avec la bonne taille, dans la bonne StorageClass, créé un pod, monté le volume persistant, fait les tests FIO et nous a sorti les résultats. Easy !
Résultats
Les résultats nous arrivent par défaut sur la console, et on peut voir que plusieurs tests ont été faits :
- read_iops
- write_iops
- read_bw
- write_bw
Je ne vais pas commenter les performances des volumes persistants ici, mais on voit bien que le "high-speed" est plus rapide que le "classic" ;)
Exemple sur les tests en lecture :
# High-Speed
JobName: read_iops
blocksize=4K filesize=2G iodepth=64 rw=randread
read:
IOPS=1412.357544 BW(KiB/s)=5666
iops: min=1220 max=1724 avg=1427.666626
bw(KiB/s): min=4880 max=6896 avg=5711.066895
# Classic
JobName: read_iops
blocksize=4K filesize=2G iodepth=64 rw=randread
read:
IOPS=120.751854 BW(KiB/s)=498
iops: min=44 max=184 avg=123.064514
bw(KiB/s): min=176 max=736 avg=492.354828Il est possible de sortir les résultats au format JSON si besoin.
CloudNativePG Bench
En cherchant d'autres outils, je suis tombé sur l'opérateur CloudNativePG qui permet de gérer des bases de données PSQL. Au premier abord aucun lien avec les tests de performances des disques. Sauf que le projet propose un plugin kubectl, avec la possibilité de benchmarker les disques sur lesquels pourront tourner les bases psql !
Le plugin cnpg utilise comme l'outil précédent fio, plus d'infos sur les options du plugin ici.
Installation
Quand on parle de plugin kubectl, le meilleur moyen d'installer est d'utiliser krew. On va donc utiliser cette méthode :
$ kubectl krew install cnpg
Updated the local copy of plugin index.
Installing plugin: cnpg
Installed plugin: cnpg
\
| Use this plugin:
| kubectl cnpg
| Documentation:
| https://github.com/cloudnative-pg/cloudnative-pg
/
$ kubectl cnpg version
Build: {Version:1.21.0 Commit:9bc5b9b2 Date:2023-10-12}
$ kubectl cnpg fio --help
Creates a fio deployment that will execute a fio job on the specified pvc.Utilisation
On retrouve sensiblement les mêmes options que kubestr pour tester les volumes :
--pvcSize: taille du PVC--storageClass: type de classe de stockage- Nom du job à fournir
Ici pas de possibilité de fournir un fichier de configuration FIO. Par contre, l'option --dry-run permet de générer les manifests YAML qui seront utilisés pour le déploiement. On remarquera la création d'une ConfigMap qui contient les paramètres suivants :
apiVersion: v1
kind: ConfigMap
metadata:
name: fio-job
data:
job: |-
[read]
direct=1
bs=8k
size=1G
time_based=1
runtime=60
ioengine=libaio
iodepth=32
end_fsync=1
log_avg_msec=1000
directory=/data
rw=read
write_bw_log=read
write_lat_log=read
write_iops_log=readOn pourra modifier alors cela si besoin de lancer des jobs fio différents.
On lance les 2 tests avec les mêmes caractéristiques que précédemment (les 2 StoragesClass, avec disque de 25Gb) :
$ kubectl cnpg fio fio-job-high-speed --storageClass csi-cinder-high-speed --pvcSize 25Gi
Running this directly to the cluster may produce a disruption in the service, are you sure you want to proceed? (y/n)
y
PersistentVolumeClaim/fio-job-high-speed created
ConfigMap/fio-job-high-speed created
Deployment/fio-job-high-speed created
To remove this test you need to delete the Deployment, ConfigMap and PVC with the name fio-job-high-speed
The most simple way to do this is to re-run the command that was runto generate the deployment with the --dry-run flag and pipe that output to kubectl delete, e.g.:
kubectl cnpg fio <fio-job-name> --dry-run | kubectl delete -f Tiens ! Ici pas de résultats... Mais un déploiement qui se crée, fait sa vie, et ne sera pas arrêté à la fin du test. On devra supprimer le déploiement nous-même.
Lançons le 2ème test :
$ kubectl cnpg fio fio-job-classic --storageClass csi-cinder-classic --pvcSize 25Gi
Running this directly to the cluster may produce a disruption in the service, are you sure you want to proceed? (y/n)
y
PersistentVolumeClaim/fio-job-classic created
ConfigMap/fio-job-classic created
Deployment/fio-job-classic created
To remove this test you need to delete the Deployment, ConfigMap and PVC with the name fio-job-classic
The most simple way to do this is to re-run the command that was runto generate the deployment with the --dry-run flag and pipe that output to kubectl delete, e.g.:
kubectl cnpg fio <fio-job-name> --dry-run | kubectl delete -f -Bon, on a bien nos 2 déploiements, avec mes 2 PVCs, il a dû se passer des "trucs" ?
$ kubectl get deploy,pvc
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/fio-job-classic 0/1 1 0 83s
deployment.apps/fio-job-high-speed 1/1 1 1 5m17s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/fio-job-classic Bound ovh-managed-kubernetes-wqforj-pvc-fec4df30-b026-4f34-9dc2-6ad59dde805e 25Gi RWO csi-cinder-classic 83s
persistentvolumeclaim/fio-job-high-speed Bound ovh-managed-kubernetes-wqforj-pvc-92f26269-6c0d-4953-9e5f-d4b4c88ab12e 25Gi RWO csi-cinder-high-speed 5m17sRésultats
Pour voir les résultats, en fait le déploiement utilise fio-tools pour générer de "beaux" graphiques, et les données sont disponibles via un service web ! Il va falloir lancer un navigateur web pour voir cela, avec un coup de port-forwarding :
$ kubectl port-forward deployment/fio-job-high-speed 8000
Forwarding from 127.0.0.1:8000 -> 8000
Forwarding from [::1]:8000 -> 8000On va retrouver sur l'interface web :
- les résultats du job
fioau format texte - les données de chaque job, au format brut/texte (fichiers .log)
- des graphes visuels montrant les perfs au format PNG
Voici, pour l'exemple, le résultat du précédent tests sur du disque "high-speed" :

Mes remarques
Avec ces tests, j'ai pu confirmer que les gens qui se plaignaient au début avaient raison, et j'ai pu adapter le type de PVC pour coller au besoin applicatif. Remarque pour celles & ceux travaillant sur des clusters OVHcloud, pensez à créer la StorageClass "high-speed-gen2" qui n'est pas activée par défaut ;)
Concernant les 2 outils, ma préférence pour les tests va au plugin cpng, qui avec la ConfigMap & les graphes est plus sympa d'utilisation. Juste pensez-bien à supprimer les déploiements après tests.
Pour kubestr, ne pas négliger les autres options de l'outil comme kubestr browse qui permet de créer un snapshot de volume et naviguer dedans, très pratique !