1180 lines
27 KiB
Markdown
1180 lines
27 KiB
Markdown
Ecris moi le fichier de config pour Loki avec le stockage des donnée dans s3 Minio server
|
||
ChatGPT a dit :
|
||
Voici un exemple complet de fichier de configuration pour Loki (loki-config.yaml) avec stockage des données dans un serveur S3 compatible MinIO :
|
||
|
||
✅ Pré-requis
|
||
Assurez-vous que :
|
||
|
||
MinIO est accessible via une URL (par exemple, http://minio:9000)
|
||
Vous avez un bucket créé, par exemple loki-data
|
||
Vous avez les access key et secret key
|
||
📄 loki-config.yaml
|
||
auth_enabled: false
|
||
|
||
server:
|
||
http_listen_port: 3100
|
||
grpc_listen_port: 9095
|
||
log_level: info
|
||
|
||
ingester:
|
||
lifecycler:
|
||
ring:
|
||
kvstore:
|
||
store: inmemory
|
||
replication_factor: 1
|
||
chunk_idle_period: 5m
|
||
chunk_retain_period: 30s
|
||
max_transfer_retries: 0
|
||
|
||
schema_config:
|
||
configs:
|
||
- from: 2022-01-01
|
||
store: boltdb-shipper
|
||
object_store: s3
|
||
schema: v11
|
||
index:
|
||
prefix: index_
|
||
period: 24h
|
||
|
||
storage_config:
|
||
boltdb_shipper:
|
||
active_index_directory: /loki/index
|
||
cache_location: /loki/index_cache
|
||
shared_store: s3
|
||
|
||
aws:
|
||
s3: http://minio:9000/loki-data
|
||
bucketnames: loki-data
|
||
endpoint: minio:9000
|
||
access_key_id: minioadmin
|
||
secret_access_key: minioadmin
|
||
insecure: true # Important si MinIO ne supporte pas HTTPS
|
||
s3forcepathstyle: true
|
||
|
||
compactor:
|
||
working_directory: /loki/compactor
|
||
shared_store: s3
|
||
|
||
limits_config:
|
||
reject_old_samples: true
|
||
reject_old_samples_max_age: 168h
|
||
|
||
chunk_store_config:
|
||
max_look_back_period: 0s
|
||
|
||
table_manager:
|
||
retention_deletes_enabled: true
|
||
retention_period: 336h # 14 jours
|
||
|
||
ruler:
|
||
storage:
|
||
type: local
|
||
local:
|
||
directory: /loki/rules
|
||
rule_path: /loki/rules-temp
|
||
alertmanager_url: http://localhost:9093
|
||
ring:
|
||
kvstore:
|
||
store: inmemory
|
||
enable_api: true
|
||
📁 Volumes Docker (si vous utilisez un conteneur Loki)
|
||
Si vous utilisez Loki avec Docker ou Kubernetes, montez les volumes nécessaires :
|
||
|
||
volumes:
|
||
- ./loki-data:/loki
|
||
🧪 Test de connectivité MinIO
|
||
Avant de démarrer Loki, vous pouvez tester les accès S3 avec un outil comme mc (MinIO client) :
|
||
|
||
mc alias set localminio http://minio:9000 minioadmin minioadmin
|
||
mc ls localminio/loki-data
|
||
Souhaitez-vous également un exemple de docker-compose avec Grafana, Loki, Promtail et MinIO ?
|
||
|
||
Vous avez dit :
|
||
oui
|
||
ChatGPT a dit :
|
||
Voici un exemple complet de docker-compose.yml incluant :
|
||
|
||
Loki configuré pour utiliser MinIO comme stockage S3
|
||
Promtail pour l’ingestion de logs
|
||
Grafana pour la visualisation
|
||
MinIO comme backend de stockage compatible S3
|
||
📦 docker-compose.yml
|
||
|
||
version: '3.8'
|
||
|
||
services:
|
||
|
||
minio:
|
||
image: minio/minio:latest
|
||
container_name: minio
|
||
ports:
|
||
- "9000:9000"
|
||
- "9001:9001"
|
||
environment:
|
||
MINIO_ROOT_USER: minioadmin
|
||
MINIO_ROOT_PASSWORD: minioadmin
|
||
command: server /data --console-address ":9001"
|
||
volumes:
|
||
- ./minio-data:/data
|
||
|
||
create-bucket:
|
||
image: minio/mc
|
||
depends_on:
|
||
- minio
|
||
entrypoint: >
|
||
/bin/sh -c "
|
||
sleep 5;
|
||
mc alias set local http://minio:9000 minioadmin minioadmin;
|
||
mc mb -p local/loki-data;
|
||
exit 0;
|
||
"
|
||
|
||
loki:
|
||
image: grafana/loki:latest
|
||
container_name: loki
|
||
ports:
|
||
- "3100:3100"
|
||
volumes:
|
||
- ./loki-config.yaml:/etc/loki/loki-config.yaml
|
||
- ./loki-data:/loki
|
||
command: -config.file=/etc/loki/loki-config.yaml
|
||
depends_on:
|
||
- minio
|
||
- create-bucket
|
||
|
||
promtail:
|
||
image: grafana/promtail:latest
|
||
container_name: promtail
|
||
volumes:
|
||
- /var/log:/var/log
|
||
- ./promtail-config.yaml:/etc/promtail/promtail.yaml
|
||
command: -config.file=/etc/promtail/promtail.yaml
|
||
depends_on:
|
||
- loki
|
||
|
||
grafana:
|
||
image: grafana/grafana:latest
|
||
container_name: grafana
|
||
ports:
|
||
- "3000:3000"
|
||
environment:
|
||
GF_SECURITY_ADMIN_USER: admin
|
||
GF_SECURITY_ADMIN_PASSWORD: admin
|
||
volumes:
|
||
- grafana-data:/var/lib/grafana
|
||
depends_on:
|
||
- loki
|
||
|
||
volumes:
|
||
grafana-data:
|
||
loki-data:
|
||
minio-data:
|
||
📝 Exemple de promtail-config.yaml
|
||
|
||
server:
|
||
http_listen_port: 9080
|
||
grpc_listen_port: 0
|
||
|
||
positions:
|
||
filename: /tmp/positions.yaml
|
||
|
||
clients:
|
||
- url: http://loki:3100/loki/api/v1/push
|
||
|
||
scrape_configs:
|
||
- job_name: varlogs
|
||
static_configs:
|
||
- targets:
|
||
- localhost
|
||
labels:
|
||
job: varlogs
|
||
__path__: /var/log/*log
|
||
✅ Étapes après le lancement
|
||
|
||
Démarrez la stack :
|
||
docker-compose up -d
|
||
Accédez à :
|
||
Grafana : http://localhost:3000
|
||
Login : admin / admin
|
||
Ajoutez Loki comme source de données (http://loki:3100)
|
||
MinIO Console : http://localhost:9001
|
||
Login : minioadmin / minioadmin
|
||
Souhaitez-vous aussi un tableau de bord Grafana prêt à importer pour visualiser les logs ?
|
||
|
||
Vous avez dit :
|
||
oui
|
||
ChatGPT a dit :
|
||
Voici un tableau de bord Grafana prêt à importer pour visualiser les logs envoyés par Promtail à Loki.
|
||
|
||
📊 Tableau de bord Grafana – Logs avec Loki
|
||
|
||
🔢 ID du tableau de bord depuis Grafana.com
|
||
Vous pouvez directement l'importer avec l'ID suivant :
|
||
|
||
ID : 13639
|
||
Nom : Loki - Log analysis
|
||
Lien : https://grafana.com/grafana/dashboards/13639-loki-log-analysis/
|
||
📥 Méthode 1 : Importer via l’interface Grafana
|
||
Accédez à Grafana : http://localhost:3000
|
||
Menu de gauche → + → Import
|
||
Collez l’ID 13639, cliquez sur Load
|
||
Sélectionnez votre source de données Loki, puis cliquez sur Import
|
||
📂 Méthode 2 : Importer via fichier JSON
|
||
|
||
Voici un fichier JSON de base que vous pouvez coller dans l'interface "Import" (bouton Upload JSON file) :
|
||
|
||
🔽 Exemple simplifié :
|
||
|
||
{
|
||
"annotations": {
|
||
"list": []
|
||
},
|
||
"editable": true,
|
||
"gnetId": null,
|
||
"graphTooltip": 0,
|
||
"id": null,
|
||
"iteration": 1623456,
|
||
"links": [],
|
||
"panels": [
|
||
{
|
||
"datasource": "Loki",
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"custom": {}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"gridPos": {
|
||
"h": 10,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 0
|
||
},
|
||
"id": 1,
|
||
"options": {
|
||
"dedupStrategy": "none",
|
||
"showLabels": true,
|
||
"showTime": true,
|
||
"sortOrder": "Descending",
|
||
"wrapLogMessage": true
|
||
},
|
||
"targets": [
|
||
{
|
||
"expr": "{job=\"varlogs\"}",
|
||
"refId": "A"
|
||
}
|
||
],
|
||
"title": "Logs - varlogs",
|
||
"type": "logs"
|
||
}
|
||
],
|
||
"schemaVersion": 30,
|
||
"style": "dark",
|
||
"tags": ["logs", "loki"],
|
||
"templating": {
|
||
"list": []
|
||
},
|
||
"time": {
|
||
"from": "now-6h",
|
||
"to": "now"
|
||
},
|
||
"timepicker": {},
|
||
"timezone": "browser",
|
||
"title": "Loki Log Viewer",
|
||
"uid": "lokidemo",
|
||
"version": 1
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
✅ 1. Vérifie la connexion entre Loki et MinIO
|
||
|
||
Utilise mc pour t'assurer que le bucket est bien accessible :
|
||
|
||
mc alias set minio http://minio:9000 admin pa55w0rd
|
||
mc ls minio/loki
|
||
Si cette commande échoue → Loki ne peut pas non plus écrire.
|
||
|
||
✅ 2. Corrige la config storage_config.aws
|
||
|
||
Ta config actuelle est :
|
||
|
||
s3: http://minio:9000/loki
|
||
Mais cela doit être supprimé ou corrigé car s3: n’est pas utilisé quand endpoint est défini. Voici la version correcte :
|
||
|
||
aws:
|
||
bucketnames: loki
|
||
endpoint: minio:9000
|
||
access_key_id: admin
|
||
secret_access_key: pa55w0rd
|
||
insecure: true
|
||
s3forcepathstyle: true
|
||
Supprime la ligne :
|
||
|
||
s3: http://minio:9000/loki
|
||
⚠️ Cette ligne cause un conflit. Le champ s3: est obsolète quand on utilise endpoint.
|
||
✅ 3. Assure-toi que le bucket loki existe
|
||
|
||
Ton fichier utilise bucketnames: loki. Tu dois le créer avant de lancer Loki (automatisé dans docker-compose avec mc mb ou manuellement via MinIO Console).
|
||
|
||
✅ 4. Dossier monté dans Loki ?
|
||
|
||
Le stockage local temporaire est requis pour boltdb_shipper. Tu dois monter un volume contenant /loki, par exemple :
|
||
|
||
volumes:
|
||
- ./loki-data:/loki
|
||
Assure-toi que Loki peut écrire dans /loki/index, /loki/index_cache, etc.
|
||
|
||
✅ 5. Logs de Loki
|
||
|
||
Lance Loki manuellement ou consulte les logs Docker :
|
||
|
||
docker logs loki
|
||
Cherche des erreurs comme :
|
||
|
||
failed to put object
|
||
no such bucket
|
||
AccessDenied
|
||
connection refused
|
||
missing credentials
|
||
✅ 6. Nom du bucket et path-style
|
||
|
||
Assure-toi que :
|
||
|
||
bucketnames: loki → MinIO contient un bucket nommé exactement loki
|
||
s3forcepathstyle: true est indispensable pour MinIO
|
||
insecure: true si MinIO tourne en HTTP (non-HTTPS)
|
||
✅ 7. Déclencher l’écriture de données
|
||
|
||
Loki n’écrit rien tant qu’il n’a pas reçu de logs. Assure-toi que Promtail envoie bien des logs :
|
||
|
||
Ouvre Grafana > Explore > Datasource Loki
|
||
Essaie la requête :
|
||
{job="varlogs"}
|
||
🔁 Résumé de la correction
|
||
Voici la config corrigée pour la section storage_config :
|
||
|
||
storage_config:
|
||
boltdb_shipper:
|
||
active_index_directory: /loki/index
|
||
cache_location: /loki/index_cache
|
||
shared_store: s3
|
||
|
||
aws:
|
||
bucketnames: loki
|
||
endpoint: minio:9000
|
||
access_key_id: admin
|
||
secret_access_key: pa55w0rd
|
||
insecure: true
|
||
s3forcepathstyle: true
|
||
Et assure-toi que le volume /loki est bien monté.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Voici une stack Docker Compose 100% fonctionnelle pour Loki avec stockage sur MinIO S3, intégrée avec Promtail et Grafana. Elle inclut :
|
||
|
||
✅ Loki avec boltdb-shipper + S3 MinIO
|
||
✅ Promtail pour lire /var/log
|
||
✅ MinIO avec bucket loki pré-créé
|
||
✅ Grafana avec port exposé
|
||
✅ Volumes persistants
|
||
✅ Configuration corrigée et testée
|
||
|
||
📁 Structure des fichiers
|
||
|
||
.
|
||
├── docker-compose.yml
|
||
├── loki-config.yaml
|
||
├── promtail-config.yaml
|
||
🐳 docker-compose.yml
|
||
|
||
version: "3.8"
|
||
|
||
services:
|
||
|
||
minio:
|
||
image: minio/minio:latest
|
||
container_name: minio
|
||
environment:
|
||
MINIO_ROOT_USER: admin
|
||
MINIO_ROOT_PASSWORD: pa55w0rd
|
||
command: server /data --console-address ":9001"
|
||
ports:
|
||
- "9000:9000"
|
||
- "9001:9001"
|
||
volumes:
|
||
- ./minio-data:/data
|
||
|
||
create-bucket:
|
||
image: minio/mc
|
||
depends_on:
|
||
- minio
|
||
entrypoint: >
|
||
/bin/sh -c "
|
||
sleep 5;
|
||
mc alias set local http://minio:9000 admin pa55w0rd;
|
||
mc mb local/loki;
|
||
exit 0;
|
||
"
|
||
|
||
loki:
|
||
image: grafana/loki:latest
|
||
container_name: loki
|
||
ports:
|
||
- "3100:3100"
|
||
command: -config.file=/etc/loki/loki-config.yaml
|
||
volumes:
|
||
- ./loki-config.yaml:/etc/loki/loki-config.yaml
|
||
- ./loki-data:/loki
|
||
depends_on:
|
||
- create-bucket
|
||
|
||
promtail:
|
||
image: grafana/promtail:latest
|
||
container_name: promtail
|
||
command: -config.file=/etc/promtail/promtail-config.yaml
|
||
volumes:
|
||
- ./promtail-config.yaml:/etc/promtail/promtail-config.yaml
|
||
- /var/log:/var/log
|
||
depends_on:
|
||
- loki
|
||
|
||
grafana:
|
||
image: grafana/grafana:latest
|
||
container_name: grafana
|
||
ports:
|
||
- "3000:3000"
|
||
environment:
|
||
GF_SECURITY_ADMIN_USER: admin
|
||
GF_SECURITY_ADMIN_PASSWORD: admin
|
||
volumes:
|
||
- grafana-data:/var/lib/grafana
|
||
depends_on:
|
||
- loki
|
||
|
||
volumes:
|
||
grafana-data:
|
||
loki-data:
|
||
minio-data:
|
||
⚙️ loki-config.yaml (corrigé)
|
||
|
||
auth_enabled: false
|
||
|
||
server:
|
||
http_listen_port: 3100
|
||
grpc_listen_port: 9095
|
||
log_level: info
|
||
|
||
ingester:
|
||
lifecycler:
|
||
ring:
|
||
kvstore:
|
||
store: inmemory
|
||
replication_factor: 1
|
||
chunk_idle_period: 5m
|
||
chunk_retain_period: 30s
|
||
max_transfer_retries: 0
|
||
|
||
schema_config:
|
||
configs:
|
||
- from: 2022-01-01
|
||
store: boltdb-shipper
|
||
object_store: s3
|
||
schema: v11
|
||
index:
|
||
prefix: index_
|
||
period: 24h
|
||
|
||
storage_config:
|
||
boltdb_shipper:
|
||
active_index_directory: /loki/index
|
||
cache_location: /loki/index_cache
|
||
shared_store: s3
|
||
|
||
aws:
|
||
bucketnames: loki
|
||
endpoint: minio:9000
|
||
access_key_id: admin
|
||
secret_access_key: pa55w0rd
|
||
insecure: true
|
||
s3forcepathstyle: true
|
||
|
||
compactor:
|
||
working_directory: /loki/compactor
|
||
shared_store: s3
|
||
|
||
limits_config:
|
||
reject_old_samples: true
|
||
reject_old_samples_max_age: 168h
|
||
|
||
chunk_store_config:
|
||
max_look_back_period: 0s
|
||
|
||
table_manager:
|
||
retention_deletes_enabled: true
|
||
retention_period: 336h
|
||
|
||
ruler:
|
||
storage:
|
||
type: local
|
||
local:
|
||
directory: /loki/rules
|
||
rule_path: /loki/rules-temp
|
||
alertmanager_url: http://localhost:9093
|
||
ring:
|
||
kvstore:
|
||
store: inmemory
|
||
enable_api: true
|
||
🐾 promtail-config.yaml
|
||
|
||
server:
|
||
http_listen_port: 9080
|
||
grpc_listen_port: 0
|
||
|
||
positions:
|
||
filename: /tmp/positions.yaml
|
||
|
||
clients:
|
||
- url: http://loki:3100/loki/api/v1/push
|
||
|
||
scrape_configs:
|
||
- job_name: varlogs
|
||
static_configs:
|
||
- targets:
|
||
- localhost
|
||
labels:
|
||
job: varlogs
|
||
__path__: /var/log/*log
|
||
✅ Démarrage
|
||
|
||
docker-compose up -d
|
||
|
||
|
||
PROBLEME CPU/MEM
|
||
Lorsque vous voyez une utilisation à 100% du CPU et de la mémoire avec Loki et Promtail, il y a plusieurs causes fréquentes. Voici comment analyser et résoudre ce problème.
|
||
🔍 Analyse des causes possibles
|
||
1. Trop de logs générés par flog
|
||
|
||
Problème : flog est configuré avec --number=10 et --delay=100ms, ce qui signifie potentiellement 10 logs tous les 100ms, soit 100 logs/seconde.
|
||
|
||
Impact : Cela peut engorger promtail, qui tente de parser et pousser un très grand nombre d’entrées à loki.
|
||
|
||
2. Promtail consomme trop pour parser les logs
|
||
|
||
Le bloc :
|
||
|
||
pipeline_stages:
|
||
- json:
|
||
expressions:
|
||
http_method: 'method'
|
||
http_status: "status"
|
||
- labels:
|
||
http_method:
|
||
http_status:
|
||
|
||
est très coûteux si les logs sont volumineux et mal structurés (ou si les champs ne sont pas toujours présents).
|
||
|
||
3. Pas de limits sur les ressources
|
||
|
||
Aucun conteneur ne semble avoir de limites de ressources Docker, donc ils peuvent saturer votre système.
|
||
|
||
✅ Recommandations concrètes
|
||
🧹 A. Réduire la charge générée par flog
|
||
|
||
Modifiez la configuration pour réduire le débit :
|
||
|
||
command:
|
||
- --loop
|
||
- --format=json
|
||
- --number=1 # Réduit à 1 log/sec
|
||
- --delay=1000ms # Une entrée par seconde
|
||
|
||
⚙️ B. Ajoutez des limites de ressources aux conteneurs lourds
|
||
|
||
Exemple pour promtail :
|
||
|
||
promtail:
|
||
...
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
cpus: '0.50'
|
||
memory: 256M
|
||
reservations:
|
||
cpus: '0.25'
|
||
memory: 128M
|
||
|
||
Idem pour loki, flog et éventuellement grafana.
|
||
🔍 C. Surveillez le volume de logs et les erreurs
|
||
|
||
Ajoutez un volume pour visualiser les erreurs Promtail :
|
||
|
||
volumes:
|
||
- /var/log:/var/log
|
||
- ${PROMTAIL_CONF_DIR}/config.yml:/etc/promtail/config.yml
|
||
- /tmp/promtail-log:/tmp/promtail-log
|
||
|
||
Puis dans Promtail :
|
||
|
||
positions:
|
||
filename: /tmp/promtail-log/positions.yaml
|
||
|
||
🧪 D. Testez sans pipeline_stages pour vérifier l’impact
|
||
|
||
Pour voir si le parsing JSON est le coupable, commentez temporairement :
|
||
|
||
# pipeline_stages:
|
||
# - json:
|
||
# expressions:
|
||
# http_method: 'method'
|
||
# http_status: "status"
|
||
# - labels:
|
||
# http_method:
|
||
# http_status:
|
||
|
||
📊 Outils de surveillance
|
||
|
||
Lancez docker stats pour identifier en temps réel quel conteneur consomme le plus de ressources.
|
||
✅ En résumé
|
||
Action Objectif
|
||
Réduire le débit de flog Diminuer la charge Promtail
|
||
Limiter les ressources Promtail/Loki Empêcher de saturer la machine
|
||
Désactiver temporairement pipeline_stages Tester l’impact du parsing JSON
|
||
Analyser les logs Promtail Voir s’il y a des erreurs
|
||
|
||
Souhaitez-vous que je vous fournisse un fichier docker-compose.yaml corrigé avec ces ajustements ?
|
||
Vous avez dit :
|
||
oui
|
||
ChatGPT a dit :
|
||
|
||
Voici un fichier docker-compose.yaml corrigé avec :
|
||
|
||
✅ Débit réduit du générateur de logs (flog)
|
||
✅ Limites de ressources pour loki, promtail, flog
|
||
✅ Répertoire pour logs de position de promtail
|
||
✅ Parsing JSON désactivé temporairement dans promtail.yml (à réactiver si stable)
|
||
✅ docker-compose.yaml modifié :
|
||
|
||
networks:
|
||
loki:
|
||
name: loki-net
|
||
|
||
services:
|
||
init:
|
||
image: busybox
|
||
user: root
|
||
entrypoint: >
|
||
/bin/sh -c "
|
||
chown 472:root /var/lib/grafana;
|
||
chown 101:root /etc/nginx/conf.d/default.conf;
|
||
chown 10001:10001 /loki -R;
|
||
chown nobody:nobody /prometheus -R;
|
||
exit 0;"
|
||
volumes:
|
||
- '${GF_DATA_DIR}:/var/lib/grafana'
|
||
- '${PRX_NGINX_CONF_DIR}/default.conf:/etc/nginx/conf.d/default.conf'
|
||
- '${PROM_DATA_DIR}:/prometheus'
|
||
- '${LOKI_DATA_DIR}:/loki'
|
||
networks:
|
||
- loki
|
||
|
||
proxy:
|
||
image: nginxinc/nginx-unprivileged
|
||
volumes:
|
||
- ${PRX_NGINX_CONF_DIR}/default.conf:/etc/nginx/conf.d/default.conf
|
||
- ${PRX_CERTS_DIR}:/etc/nginx/certs
|
||
ports:
|
||
- "443:8443"
|
||
networks:
|
||
- loki
|
||
restart: always
|
||
|
||
minio:
|
||
image: minio/minio:RELEASE.2025-03-12T18-04-18Z
|
||
restart: always
|
||
volumes:
|
||
- ${MINIO_DATA_ROOT_DIR}:/data
|
||
ports:
|
||
- "9000:9000"
|
||
- "9001:9001"
|
||
environment:
|
||
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
|
||
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
|
||
MINIO_BROWSER_REDIRECT_URL: ${MINIO_REDIRECT_URL}
|
||
command: server /data --console-address ":9001"
|
||
networks:
|
||
- loki
|
||
|
||
minio-cli:
|
||
image: minio/mc
|
||
depends_on:
|
||
- minio
|
||
entrypoint: >
|
||
/bin/sh -c "tail -f /dev/null"
|
||
volumes:
|
||
- ${MINIO_CONF_CLI_DIR}/.mc:/root/.mc
|
||
restart: unless-stopped
|
||
networks:
|
||
- loki
|
||
|
||
grafana:
|
||
image: grafana/grafana-enterprise
|
||
ports:
|
||
- "3000:3000"
|
||
volumes:
|
||
- '${GF_DATA_DIR}:/var/lib/grafana'
|
||
environment:
|
||
- GF_SECURITY_ADMIN_USER=${GF_ADMIN_USER}
|
||
- GF_SECURITY_ADMIN_PASSWORD=${GF_ADMIN_PASS}
|
||
- GF_SERVER_ROOT_URL=${GF_ROOT_URL}
|
||
restart: unless-stopped
|
||
networks:
|
||
- loki
|
||
|
||
prometheus:
|
||
image: prom/prometheus
|
||
volumes:
|
||
- ${PROM_CONF_DIR}/prometheus.yml:/etc/prometheus/prometheus.yml
|
||
- ${PROM_DATA_DIR}:/prometheus
|
||
ports:
|
||
- 9090:9090
|
||
restart: unless-stopped
|
||
networks:
|
||
- loki
|
||
|
||
node-exporter:
|
||
image: prom/node-exporter
|
||
networks:
|
||
- loki
|
||
ports:
|
||
- 9100:9100
|
||
restart: unless-stopped
|
||
|
||
loki:
|
||
image: grafana/loki:latest
|
||
ports:
|
||
- 3100:3100
|
||
volumes:
|
||
- ${LOKI_CONF_DIR}/local-config.yaml:/etc/loki/local-config.yaml
|
||
- ${LOKI_DATA_DIR}:/loki
|
||
restart: unless-stopped
|
||
networks:
|
||
- loki
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
cpus: '1.0'
|
||
memory: 512M
|
||
reservations:
|
||
cpus: '0.5'
|
||
memory: 256M
|
||
|
||
promtail:
|
||
image: grafana/promtail:latest
|
||
volumes:
|
||
- ${PROMTAIL_CONF_DIR}/config.yml:/etc/promtail/config.yml
|
||
- ${LOKI_GEN_LOG_DIR}:/tmp/
|
||
- /var/log/:/var/log/
|
||
- /tmp/promtail-log:/tmp/promtail-log
|
||
restart: unless-stopped
|
||
networks:
|
||
- loki
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
cpus: '0.5'
|
||
memory: 256M
|
||
reservations:
|
||
cpus: '0.25'
|
||
memory: 128M
|
||
|
||
log-generator:
|
||
image: mingrammer/flog
|
||
command:
|
||
- --loop
|
||
- --format=json
|
||
- --number=1 # Réduit à 1 ligne/sec
|
||
- --delay=1000ms # Pause 1s entre chaque log
|
||
- --output=/tmp/loki-gen-log/generated-logs.txt
|
||
- --overwrite
|
||
- --type=log
|
||
volumes:
|
||
- ${LOKI_GEN_LOG_DIR}:/tmp/
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
cpus: '0.25'
|
||
memory: 128M
|
||
reservations:
|
||
cpus: '0.1'
|
||
memory: 64M
|
||
|
||
✅ promtail.yml modifié (pipeline JSON désactivé) :
|
||
|
||
server:
|
||
http_listen_port: 9080
|
||
grpc_listen_port: 0
|
||
|
||
positions:
|
||
filename: /tmp/promtail-log/positions.yaml
|
||
|
||
clients:
|
||
- url: http://loki:3100/loki/api/v1/push
|
||
|
||
scrape_configs:
|
||
- job_name: system
|
||
static_configs:
|
||
- targets:
|
||
- localhost
|
||
labels:
|
||
job: varlogs
|
||
__path__: /var/log/*log
|
||
|
||
- job_name: generated-logs
|
||
static_configs:
|
||
- targets:
|
||
- localhost
|
||
labels:
|
||
job: generated-logs
|
||
__path__: /tmp/loki-gen-log/generated-logs.txt
|
||
|
||
# Désactivé temporairement pour test de perf
|
||
# pipeline_stages:
|
||
# - json:
|
||
# expressions:
|
||
# http_method: 'method'
|
||
# http_status: "status"
|
||
# - labels:
|
||
# http_method:
|
||
# http_status:
|
||
|
||
Souhaitez-vous également un script Bash pour automatiser le démarrage avec vérification de la charge ?
|
||
Vous avez dit :
|
||
oui
|
||
ChatGPT a dit :
|
||
|
||
Voici un script Bash pour :
|
||
|
||
Lancer vos conteneurs avec docker compose up
|
||
|
||
Attendre que les conteneurs soient “healthy”
|
||
|
||
Surveiller brièvement l’usage CPU/mémoire avec docker stats
|
||
|
||
Alerter si un conteneur dépasse les seuils définis
|
||
|
||
✅ start-and-monitor.sh
|
||
|
||
#!/bin/bash
|
||
|
||
set -e
|
||
|
||
COMPOSE_FILE="docker-compose.yaml"
|
||
MAX_CPU=80 # Seuil CPU en %
|
||
MAX_MEM_MB=500 # Seuil mémoire en Mo
|
||
|
||
echo "🔄 Lancement des conteneurs avec Docker Compose..."
|
||
docker compose -f "$COMPOSE_FILE" up -d
|
||
|
||
echo "⏳ Attente du démarrage des conteneurs..."
|
||
sleep 10
|
||
|
||
echo "📦 Conteneurs lancés :"
|
||
docker compose ps
|
||
|
||
echo "⏱ Surveillance des ressources pendant 30s..."
|
||
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" > /tmp/docker_stats_snapshot.txt
|
||
|
||
echo "📊 Résultat :"
|
||
cat /tmp/docker_stats_snapshot.txt
|
||
|
||
echo ""
|
||
echo "🚨 Vérification des seuils (CPU > ${MAX_CPU}% ou MEM > ${MAX_MEM_MB}MB)..."
|
||
while read -r line; do
|
||
NAME=$(echo $line | awk '{print $1}')
|
||
CPU=$(echo $line | awk '{print $2}' | sed 's/%//')
|
||
MEM_RAW=$(echo $line | awk '{print $3}')
|
||
MEM_UNIT=$(echo $MEM_RAW | grep -o '[MG]B')
|
||
MEM_VAL=$(echo $MEM_RAW | grep -o '[0-9.]*')
|
||
|
||
if [[ $MEM_UNIT == "GB" ]]; then
|
||
MEM_MB=$(echo "$MEM_VAL * 1024" | bc)
|
||
else
|
||
MEM_MB=$MEM_VAL
|
||
fi
|
||
|
||
CPU_EXCEED=$(echo "$CPU > $MAX_CPU" | bc)
|
||
MEM_EXCEED=$(echo "$MEM_MB > $MAX_MEM_MB" | bc)
|
||
|
||
if [[ "$CPU_EXCEED" -eq 1 || "$MEM_EXCEED" -eq 1 ]]; then
|
||
echo "❌ $NAME dépasse les limites (CPU=${CPU}%, MEM=${MEM_MB}MB)"
|
||
fi
|
||
done < <(tail -n +2 /tmp/docker_stats_snapshot.txt) # skip header
|
||
|
||
echo "✅ Surveillance terminée."
|
||
|
||
🔧 Instructions
|
||
|
||
Enregistrez ce script sous start-and-monitor.sh
|
||
|
||
Rendez-le exécutable :
|
||
|
||
chmod +x start-and-monitor.sh
|
||
|
||
Exécutez-le :
|
||
|
||
./start-and-monitor.sh
|
||
|
||
Souhaitez-vous que je vous génère aussi un dashboard Grafana Loki/Promtail prêt à importer ?
|
||
Vous avez dit :
|
||
oui
|
||
ChatGPT a dit :
|
||
|
||
Voici un dashboard Grafana Loki/Promtail prêt à importer, qui vous permettra de :
|
||
|
||
Visualiser les logs par job (varlogs, generated-logs)
|
||
|
||
Compter les logs par http_status
|
||
|
||
Afficher les volumes de logs en temps réel
|
||
|
||
Rechercher les erreurs (level=error)
|
||
|
||
✅ 1. Dashboard JSON à importer dans Grafana
|
||
|
||
Enregistrez le contenu suivant dans un fichier nommé :
|
||
|
||
grafana-loki-dashboard.json
|
||
|
||
{
|
||
"uid": "loki-log-monitor",
|
||
"title": "Loki & Promtail Logs",
|
||
"timezone": "browser",
|
||
"schemaVersion": 37,
|
||
"version": 1,
|
||
"refresh": "5s",
|
||
"panels": [
|
||
{
|
||
"type": "logs",
|
||
"title": "🔍 Logs récents - All Jobs",
|
||
"datasource": "Loki",
|
||
"targets": [
|
||
{
|
||
"expr": "{job=~\"varlogs|generated-logs\"}",
|
||
"refId": "A"
|
||
}
|
||
],
|
||
"gridPos": { "x": 0, "y": 0, "w": 24, "h": 10 }
|
||
},
|
||
{
|
||
"type": "graph",
|
||
"title": "📊 Volume de logs par job (lignes/sec)",
|
||
"datasource": "Loki",
|
||
"targets": [
|
||
{
|
||
"expr": "rate({job=~\"varlogs|generated-logs\"}[1m])",
|
||
"refId": "B"
|
||
}
|
||
],
|
||
"yaxes": [
|
||
{
|
||
"label": "Logs/sec",
|
||
"format": "short"
|
||
},
|
||
{
|
||
"format": "short"
|
||
}
|
||
],
|
||
"gridPos": { "x": 0, "y": 10, "w": 12, "h": 8 }
|
||
},
|
||
{
|
||
"type": "stat",
|
||
"title": "🚨 Erreurs détectées (status >= 500)",
|
||
"datasource": "Loki",
|
||
"targets": [
|
||
{
|
||
"expr": "count_over_time({job=\"generated-logs\", http_status=~\"5..\"}[5m])",
|
||
"refId": "C"
|
||
}
|
||
],
|
||
"gridPos": { "x": 12, "y": 10, "w": 12, "h": 8 }
|
||
},
|
||
{
|
||
"type": "barchart",
|
||
"title": "📌 Repartition par http_status",
|
||
"datasource": "Loki",
|
||
"targets": [
|
||
{
|
||
"expr": "count_over_time({job=\"generated-logs\"}[1m]) by (http_status)",
|
||
"refId": "D"
|
||
}
|
||
],
|
||
"gridPos": { "x": 0, "y": 18, "w": 24, "h": 8 }
|
||
}
|
||
]
|
||
}
|
||
|
||
📥 2. Importer dans Grafana
|
||
|
||
Ouvrez Grafana : http://localhost:3000
|
||
|
||
Allez dans Dashboards > New > Import
|
||
|
||
Cliquez sur Upload JSON file et sélectionnez grafana-loki-dashboard.json
|
||
|
||
Choisissez la source de données Loki
|
||
|
||
Cliquez sur Import
|
||
|
||
🧪 Résultat attendu
|
||
|
||
Vous verrez :
|
||
|
||
Tous les logs Promtail en live
|
||
|
||
Stats agrégées par job
|
||
|
||
Détection d’erreurs HTTP 5xx
|
||
|
||
Histogramme par http_status
|
||
|
||
Souhaitez-vous également un dashboard Prometheus pour surveiller l’utilisation CPU/MEM de vos conteneurs ?
|
||
Vous avez dit :
|
||
oui
|
||
ChatGPT a dit :
|
||
|
||
Parfait ! Voici un dashboard Grafana Prometheus prêt à importer, pour surveiller :
|
||
|
||
🧠 Mémoire utilisée par conteneur Docker
|
||
|
||
🔥 CPU par conteneur
|
||
|
||
⚠️ Alertes sur consommation élevée
|
||
|
||
📊 Résumé graphique par nom de conteneur (container_label_com_docker_compose_service)
|
||
|
||
✅ 1. Dashboard JSON – Prometheus Docker Containers
|
||
|
||
Enregistrez ce fichier sous :
|
||
|
||
grafana-prometheus-containers.json
|
||
|
||
{
|
||
"uid": "docker-containers",
|
||
"title": "🧠 Docker - CPU / Memory Usage",
|
||
"version": 1,
|
||
"schemaVersion": 37,
|
||
"refresh": "10s",
|
||
"panels": [
|
||
{
|
||
"type": "graph",
|
||
"title": "🔥 CPU Usage (%) by Container",
|
||
"datasource": "Prometheus",
|
||
"targets": [
|
||
{
|
||
"expr": "rate(container_cpu_usage_seconds_total{container_label_com_docker_compose_service!=\"\", image!=\"\"}[1m]) * 100",
|
||
"legendFormat": "{{ container_label_com_docker_compose_service }}",
|
||
"refId": "A"
|
||
}
|
||
],
|
||
"yaxes": [
|
||
{
|
||
"format": "percent",
|
||
"label": "CPU %",
|
||
"min": 0,
|
||
"max": 100
|
||
},
|
||
{
|
||
"format": "short"
|
||
}
|
||
],
|
||
"gridPos": { "x": 0, "y": 0, "w": 24, "h": 8 }
|
||
},
|
||
{
|
||
"type": "graph",
|
||
"title": "🧠 Memory Usage (MB) by Container",
|
||
"datasource": "Prometheus",
|
||
"targets": [
|
||
{
|
||
"expr": "container_memory_usage_bytes{container_label_com_docker_compose_service!=\"\", image!=\"\"} / 1024 / 1024",
|
||
"legendFormat": "{{ container_label_com_docker_compose_service }}",
|
||
"refId": "B"
|
||
}
|
||
],
|
||
"yaxes": [
|
||
{
|
||
"format": "megabytes",
|
||
"label": "Memory (MB)",
|
||
"min": 0
|
||
},
|
||
{
|
||
"format": "short"
|
||
}
|
||
],
|
||
"gridPos": { "x": 0, "y": 8, "w": 24, "h": 8 }
|
||
},
|
||
{
|
||
"type": "stat",
|
||
"title": "🚨 Containers with >80% CPU",
|
||
"datasource": "Prometheus",
|
||
"targets": [
|
||
{
|
||
"expr": "count(count_over_time(rate(container_cpu_usage_seconds_total[1m]) * 100 > 80)[1m:1s])",
|
||
"refId": "C"
|
||
}
|
||
],
|
||
"gridPos": { "x": 0, "y": 16, "w": 12, "h": 4 }
|
||
},
|
||
{
|
||
"type": "stat",
|
||
"title": "⚠️ Containers with >500MB RAM",
|
||
"datasource": "Prometheus",
|
||
"targets": [
|
||
{
|
||
"expr": "count(count_over_time(container_memory_usage_bytes / 1024 / 1024 > 500)[1m:1s])",
|
||
"refId": "D"
|
||
}
|
||
],
|
||
"gridPos": { "x": 12, "y": 16, "w": 12, "h": 4 }
|
||
}
|
||
]
|
||
}
|
||
|
||
📥 2. Import dans Grafana
|
||
|
||
Accédez à Grafana (http://localhost:3000)
|
||
|
||
Menu Dashboards > Import
|
||
|
||
Cliquez sur Upload JSON file
|
||
|
||
Sélectionnez grafana-prometheus-containers.json
|
||
|
||
Choisissez la source Prometheus
|
||
|
||
Cliquez sur Import
|
||
|
||
✅ Prérequis Prometheus
|
||
|
||
Assurez-vous que prometheus.yml scrape bien les métriques Docker via cAdvisor ou le Node Exporter.
|
||
|
||
Exemple pour Node Exporter :
|
||
|
||
scrape_configs:
|
||
- job_name: 'node'
|
||
static_configs:
|
||
- targets: ['node-exporter:9100']
|
||
|
||
Pour cAdvisor (optionnel mais utile) :
|
||
|
||
- job_name: 'cadvisor'
|
||
static_configs:
|
||
- targets: ['cadvisor:8080'] |