Contexte
Quand on travaille sur l’observabilité, il y a un outil qui vient toujours en tête en premier : Grafana.
Grafana est un outil de visualisation open source développé par Grafana Labs, et je suis sûr que vous le connaissez tous (et j’ai aussi écrit à son sujet de nombreuses fois). Mais au-delà de cela, ils développent également beaucoup d’autres outils utiles dans le paysage de l’observabilité, au point qu’on peut en théorie construire toute sa stack d’observabilité uniquement avec des outils Grafana Labs.
Pour répondre au manque de stockage long terme de Prometheus et au manque de fonctionnalités de haute disponibilité (je n’ai JAMAIS compris pourquoi l’équipe Prometheus refuse de travailler là-dessus), Grafana Labs a forké Cortex il y a quelques années et l’a renommé Mimir.
Je ne vais pas couvrir l’installation de Mimir ici, il y a plein de tutoriels sur Internet et une documentation officielle pour ça.
À la place, je vais parler d’un problème que j’ai avec le chart helm officiel de Mimir, et plus précisément avec les dashboards Grafana intégrés qui viennent avec.
Des dashboards, vous dites ?
Mimir est livré avec de nombreux dashboards Grafana utiles pour s’assurer que les composants fonctionnent correctement.

Ces dashboards sont compatibles avec les différents modes de déploiement de Mimir. Dans Kubernetes, si vous utilisez le chart helm officiel mimir-distributed, cela peut être activé par une simple valeur :
metaMonitoring:
dashboards:
enabled: true
Mais, par défaut, tous les dashboards installés via la valeur metaMonitoring dans les charts helm de Mimir sont des manifestes JSON précompilés utilisant jsonnet/mixin.
Par exemple, voici la version précompilée du “Mimir / Overview dashboard” :
Par conception, vous ne pouvez pas changer des choses comme le préfixe du nom des pods mimir, ce qui rend ces dashboards précompilés inutiles dans un environnement type helm où le nom de release (mimir-) est un préfixe du pod.
kubectl -n monitoring get pods
NAME READY STATUS RESTARTS AGE
mimir-alertmanager-0 1/1 Running 0 24h
mimir-alertmanager-1 1/1 Running 0 24h
mimir-compactor-0 1/1 Running 0 24h
mimir-distributor-5d668b479f-ksltr 1/1 Running 1 (24h ago) 6d1h
...
Dans ce cas, tous les dashboards seront cassés, affichant tous “no data” dans Grafana car les données seront incorrectement filtrées. Par exemple, le panneau “Write requests / sec” dans “Mimir / Overview dashboard” a un label job=~"($namespace)/((distributor..., mais notre pod est mimir-distributor, pas distributor :
sum by (status) (
label_replace(label_replace(rate(cortex_request_duration_seconds_count{cluster=~"$cluster", job=~"($namespace)/((distributor.*|cortex|mimir|mimir-write.*))", route=~"/distributor.Distributor/Push|/httpgrpc.*|api_(v1|prom)_push|otlp_v1_metrics"}[$__rate_interval]),
"status", "${1}xx", "status_code", "([0-9]).."),
"status", "${1}", "status_code", "([a-zA-Z]+)"))
La solution est de désactiver le flag metaMonitoring du chart, et de construire / déployer les dashboards séparément.
Procédure
Récupérez les sources de Mimir :
git clone https://github.com/grafana/mimir.git
Heureusement, les fichiers jsonnet/mixin incluent une variable job_prefix qui va nous aider à corriger cela :
sed -i.bak "s/job_prefix: '(\$namespace)\/',/job_prefix: '(\$namespace)\/mimir-',/" operations/mimir-mixin/config.libsonnet
Recompilez les dashboards :
make build-mixin
podman image inspect grafana/mimir-build-image:pr9491-80f5778956 >/dev/null 2>&1 || podman pull grafana/mimir-build-image:pr9491-80f5778956
podman tag grafana/mimir-build-image:pr9491-80f5778956 grafana/mimir-build-image:latest
[...]
make: Leaving directory '/go/src/github.com/grafana/mimir'
10,10 real 0,02 user 0,01 sys
Note : Si vous n’avez pas docker sur votre machine (j’utilise podman), la commande make va échouer car elle ne peut pas trouver docker et le binaire docker est hardcodé dans les commandes make. Modifiez le Makefile pour remplacer docker par podman.
Les fichiers json dans operations/mimir-mixin-compiled/dashboards sont maintenant construits avec les noms de pods corrects.
Créez un chart helm grafana-dashboards (appelé yourDashboardsChart ici).
helm create yourDashboardsChart
Dans ce chart, créez un répertoire src/dashboards/mimir (pour les sources des dashboards json) à côté du répertoire classique templates contenant les manifestes YAML go-templatés. Nous allons créer les fichiers helm gotemplate juste après :
cp operations/mimir-mixin-compiled/dashboards/* ../yourDashboardsChart/src/dashboards/mimir
Maintenant, pour chaque fichier json généré par jsonnet, nous allons créer un fichier yaml helm gotemplaté, qui à son tour créera une ConfigMap pour chaque dashboard dans notre cluster Kubernetes. Ils ressembleront à ceci :
---
# Source: mimir-distributed/templates/metamonitoring/grafana-dashboards.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mimir-alertmanager-dashboard
namespace: '{{ $.Release.Namespace }}'
labels:
grafana_dashboard: "1"
annotations:
k8s-sidecar-target-directory: /tmp/dashboards/Mimir Dashboards
data:
mimir-alertmanager.json: |-
{{ $.Files.Get "src/dashboards/mimir/mimir-alertmanager.json" | fromJson | toJson }}
Pour accélérer le processus, vous pouvez réutiliser helm template et quelques commandes bash pour générer tous les fichiers helm gotemplate pour vous :
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
mkdir -p mimir
helm -n monitoring template mimir grafana/mimir-distributed --set metaMonitoring.dashboards.enabled=true > helm-output.yaml
# Compter le nombre de séparateurs de documents
doc_count=$(grep -c '^---$' helm-output.yaml)
# Diviser le fichier YAML en fichiers séparés pour chaque document
csplit -f mimir/helm-output- helm-output.yaml '/---/' "{$((doc_count - 2))}" >/dev/null
# Un peu de nettoyage
for file in mimir/helm-output-*; do
if grep -q 'kind: ConfigMap' "$file" && grep -q 'dashboard' "$file"; then
name=$(yq eval '.metadata.name' "$file")
yq eval -i 'del(.metadata.labels."helm.sh/chart", .metadata.labels."app.kubernetes.io/name", .metadata.labels."app.kubernetes.io/instance", .metadata.labels."app.kubernetes.io/version", .metadata.labels."app.kubernetes.io/managed-by")' "$file"
yq eval -i '.metadata.namespace = "{{ $.Release.Namespace }}"' "$file"
yq eval -i '.data |= with_entries(.value = "{{ $.Files.Get \"src/dashboards/mimir/" + .key + "\" | fromJson | toJson }}")' "$file"
mv "$file" "mimir/${name}.yaml"
else
rm "$file"
fi
done
mv mimir/* ../yourDashboardsChart/templates/mimir
Maintenant, vous devriez avoir tous les fichiers nécessaires pour régénérer les dashboards Grafana dans votre cluster Kubernetes, avec le préfixe correct.
Have fun!
