Ajout du monitoring automatique de vos applications locales avec Monday
Si vous ne connaissez pas encore Monday, je vous invite à vous rendre sur https://github.com/eko/monday pour en apprendre plus dans un premier temps.
Rapidement, c'est un outil open-source que j'ai développé qui permet aux développeurs travaillant sur plusieurs micro-services à la fois de lancer des projets
, ensemble d'applications lancées localement
et de simuler l'exécution d'autres en faisant du port-forwarding
depuis un environnement Kubernetes, une connexion SSH ou simplement en faisant du proxy TCP.
À mon sens il manquait une fonctionnalité qui me semble intéressante pour les développeurs : pouvoir avoir accès à du monitoring
de leur application directement en local.
Pour la plupart des clients avec lesquels j'ai pu travailler jusqu'à maintenant, j'ai beaucoup utilisé Prometheus comme serveur de stockage des métriques temporelles et Grafana pour la visualisation.
J'ai donc dans cet article écrit un exemple permettant de lancer cette stack technique de monitoring mais l'important pour moi sur Monday étant de laisser le plus possible la main aux développeurs et ainsi leur permettre d'implémenter la solution qu'ils désirent.
Aussi, il me semble intéressant de partager avec vous les étapes de réflexion pour la mise en place de cette fonctionnalité, permettant de :
- Faire évoluer l'outil avec de nouvelles fonctionnalités,
- Garder un comportement ouvert, ne fermant pas la porte aux développeurs pour d'autres intégrations.
Pré-requis pour l'exécution de Grafana et Prometheus
Après un rapide état des lieux du projet, pour pouvoir ajouter Grafana et Prometheus et avoir du monitoring automatique, à tout moment, en fonction des différentes grappes de service que je souhaitais lancer, il me manquait quelques fonctionnalités essentielles.
Avant de commencer, un petit rappel sur le fonctionnement de Prometheus et Grafana avec ce petit schema :
- Prometheus va venir récupérer les métriques des applications que nous allons déclarer dans son fichier de configuration,
- Grafana va venir intérroger la base de données timeseries Prometheus pour récupérer les métriques et les afficher sur des dashboard que vous aurez créés.
Lancer des applications de manière globale
Jusqu'ici, un projet est déclaré comme suit :
projects:
- name: project-a
local:
- *service-a-local
forward:
- *service-b-forward
- name: project-b
local:
- *service-b-local
forward:
- *service-c-forward
Si j'avais voulu ajouter Grafana et Prometheus, j'aurais dû les ajouter pour les deux projets, cette première pull request m'a donc permis d'ajouter la notion de globalité sur les applications locales et de forward, ainsi, je peux maintenant déclarer à la racine de la configuration YAML :
local:
- *grafana-global
- *prometheus-global
forward:
- *graylog-forward-kubernetes
Simple, efficace, des applications locales ou des port-forward peuvent désormais être effectués dans tous les cas.
Pouvoir générer des fichiers de configuration
Grafana et Prometheus pouvant maintenant être exécutés, il fallait maintenant générer les fichiers de configuration suivants :
- Prometheus : répertorier les applications pour lesquelles les métriques doivent être récupérées (scrapping),
- Grafana : déclarer l'URL du serveur Prometheus comme source de données (datasource).
Ces deux besoins représentent en fait un seul besoin : pouvoir déclarer pour une application locale des fichiers, et pouvoir générer dynamiquement ces fichiers à partir des valeurs fournies dans la configuration de l'utilisateur.
Le package text/template
de Go m'a été très utile pour cette fonctionnalité, comme vous pouvez le voir dans la pull request suivante.
Il permet en effet l'utilisation d'une syntaxe permettant de parcourir un objet Go ou encore d'ajouter des fonctions pouvant être utilisées dans le template.
Pour écrire un template, rien de plus simple :
content := `
{{- range $app := .Applications }}
Application: {{ $app.Name }}
{{- end }}
`
t := template.Must(template.New("/my/output/file").Parse(content))
_ = t.Execute(f, project) // project est ici la struct représentant le projet courant
Ainsi, pour le projet project-a
donné plus haut, la sortie dans le fichier /my/output/file
ici correspondant au nom donné à mon application locale service-a
:
Application: Service A
Cette fonctionnalité mise en place, nous sommes donc maintenant capable de déclarer, pour des applications locales, une section files
permettant de générer les fichiers de configuration, comme celui de Prometheus par exemple :
<: &prometheus-global
name: prometheus
...
files:
- type: content
to: ~/.monday/prometheus-2.22.1.darwin-amd64/prometheus.yml
content: | # Prepare the Prometheus configuration with all services that have to be scrapped from monday
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
{{- range $app := .Applications }}
{{- if $app.Monitoring }}
- job_name: '{{ $app.Name }}'
static_configs:
- targets: ['{{ $app.Hostname }}:{{ $app.Monitoring.Port }}']
metrics_path: {{ $app.Monitoring.URL }}
{{- end }}
{{- end }}
La même fonctionnalité est utilisée pour créer les configurations Grafana nécessaires.
Mise en place du monitoring
Nous avons maintenant toutes les fonctionnalités nécessaires !
La dernière pull request consistait uniquement à ajouter dans les entrées de configuration YAML une section monitoring
(utilisée dans le template de configuration Prometheus juste avant) afin de pouvoir déclarer pour chaque application, sur quel hostname / port et URL Prometheus doit venir chercher les données.
Sur une application, il nous faut donc simplement ajouter les sections suivantes :
<: &service-a-local
name: Service A
...
hostname: service-a.svc.local
monitoring:
port: 8001
url: /metrics
Notez qu'il est aussi possible de spécifier cette configuration sur une application de type forward
, car après tout vous pouvez aussi accéder à leurs métriques, même si elles ne sont pas directement exécutées chez vous, pourquoi se priver ?
Voici donc les configurations complètes pour Grafana et Prometheus permettant d'ajouter le monitoring à vos micro-services en local :
Configuration Monday pour Prometheus
# Defines Prometheus server setup steps and configuration files
<: &prometheus-global
name: prometheus
path: ~/.monday/prometheus-2.22.1.darwin-amd64
hostname: "prometheus.svc.local"
setup:
commands:
- mkdir -p ~/.monday/download
- curl -Lo ~/.monday/download/prometheus.tar.gz https://github.com/prometheus/prometheus/releases/download/v2.22.1/prometheus-2.22.1.darwin-amd64.tar.gz
- tar -xzvf ~/.monday/download/prometheus.tar.gz --directory ~/.monday/
- rm -rf ~/.monday/download/prometheus*
run:
command: ./prometheus
files:
- type: content
to: ~/.monday/prometheus-2.22.1.darwin-amd64/prometheus.yml
content: | # Prepare the Prometheus configuration with all services that have to be scrapped from monday
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
{{- range $app := .Applications }}
{{- if $app.Monitoring }}
- job_name: '{{ $app.Name }}'
static_configs:
- targets: ['{{ $app.Hostname }}:{{ $app.Monitoring.Port }}']
metrics_path: {{ $app.Monitoring.URL }}
{{- end }}
{{- end }}
Configuration Monday pour Grafana
# Defines Grafana setup steps and configuration files
<: &grafana-global
name: grafana
path: ~/.monday/grafana-7.1.5
hostname: "grafana.svc.local"
setup:
commands:
- mkdir -p ~/.monday/download
- curl -Lo ~/.monday/download/grafana.tar.gz https://dl.grafana.com/oss/release/grafana-7.1.5.darwin-amd64.tar.gz
- tar -xzvf ~/.monday/download/grafana.tar.gz --directory ~/.monday/
- rm -rf ~/.monday/download/grafana*
run:
command: ./bin/grafana-server web
files:
- type: content
to: ~/.monday/grafana-7.1.5/conf/provisioning/datasources/prometheus.yml
content: | # Specify the Prometheus datasource in Grafana
apiVersion: 1
datasources:
- name: prometheus
type: prometheus
access: proxy
url: http://prometheus.svc.local:9090
- type: content
to: ~/.monday/grafana-7.1.5/conf/provisioning/dashboards/monday.yml
content: | # In case you want to provision some dashboards, specify the path
apiVersion: 1
providers:
- name: 'monday'
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: true
options:
path: $HOME/.monday/grafana-7.1.5/conf/provisioning/dashboards
- type: copy # In case you want to prepare a Grafana dashboard that will be provisionned with Grafana
from: ~/.monday/grafana-dashboard.json
to: ~/.monday/grafana-7.1.5/conf/provisioning/dashboards/dashboard.json
Note : si vous êtes sous linux, pensez à modifier
darwin
enlinux
.
Conclusion
Notez qu'avec la déclaration des étapes de setup
, un développeur de l'équipe aura simplement à copier ces nouvelles configurations et à la fois Prometheus et Grafana seront automatiquement installés et exécutés lorsqu'il utilisera Monday.
Il pourra alors accéder à son interface Grafana en se rendant sur http://grafana.svc.local:3000
et, si besoin, Prometheus via http://prometheus.svc.local:9090
.