Solution Challenge CI/CD et Observabilité des Données
Cette solution présente une stack d’observabilité complète intégrant PostgreSQL, Prometheus et Grafana, avec un déploiement automatisé via GitLab CI/CD.
📋 Vue d’ensemble
Cette architecture permet de monitorer en temps réel les métriques d’une base de données PostgreSQL, visualisées via Grafana, avec un déploiement entièrement automatisé.
Voici l’organisation des fichiers du projet :
cicd-observability-challenge/
├── .gitlab-ci.yml # Pipeline CI/CD
├── docker-compose.yml # Orchestration des services
├── prometheus/
│ └── prometheus.yml # Configuration Prometheus
├── grafana/
│ ├── dashboards/
│ │ └── postgres-dashboard.json
│ └── provisioning/
│ ├── dashboards/
│ │ └── dashboard.yml
│ └── datasources/
│ └── datasource.yml
├── postgres/
│ └── init.sql # Script d'initialisation DB
└── README.md
Le fichier docker-compose.yml orchestre l’ensemble de la stack :
version: '3.8'
services:
postgres:
image: postgres:15
container_name: postgres-db
environment:
POSTGRES_DB: monitoring_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres123
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- monitoring
postgres-exporter:
image: prometheuscommunity/postgres-exporter:latest
container_name: postgres-exporter
environment:
DATA_SOURCE_NAME: "postgresql://postgres:postgres123@postgres:5432/monitoring_db?sslmode=disable"
ports:
- "9187:9187"
depends_on:
- postgres
networks:
- monitoring
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
depends_on:
- postgres-exporter
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin123
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
- ./grafana/dashboards:/var/lib/grafana/dashboards
depends_on:
- prometheus
networks:
- monitoring
volumes:
postgres_data:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridge✅ Bonnes pratiques
Le fichier prometheus/prometheus.yml définit les cibles de collecte :
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'postgres-exporter'
static_configs:
- targets: ['postgres-exporter:9187']
scrape_interval: 5s
metrics_path: /metricspg_up - Statut de PostgreSQLpg_stat_database_numbackends - Connexions activespg_stat_database_xact_commit - Transactions validéespg_stat_database_xact_rollback - Transactions annuléesLe fichier .gitlab-ci.yml automatise le déploiement :
stages:
- build
- deploy
- test
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: "/certs"
services:
- docker:20.10.16-dind
before_script:
- docker info
- docker-compose --versionbuild:
stage: build
image: docker:20.10.16
script:
- echo "Building custom postgres exporter image..."
- docker build -t custom-postgres-exporter .
- echo "Build completed successfully"
only:
- main
- developdeploy:
stage: deploy
image: docker/compose:latest
script:
- echo "Starting deployment..."
- docker-compose up -d
- echo "Waiting for services to be ready..."
- sleep 30
- docker-compose ps
- echo "Checking service health..."
- docker-compose logs postgres
- docker-compose logs postgres-exporter
- docker-compose logs prometheus
- docker-compose logs grafana
after_script:
- docker-compose down
only:
- maintest:
stage: test
image: alpine:latest
before_script:
- apk add --no-cache curl
script:
- echo "Testing Prometheus metrics collection..."
- sleep 10
- curl -f http://prometheus:9090/-/ready || exit 1
- echo "Testing PostgreSQL exporter metrics..."
- curl -f http://postgres-exporter:9187/metrics | grep -q "pg_up" || exit 1
- echo "Testing Grafana availability..."
- curl -f http://grafana:3000/api/health || exit 1
- echo "All tests passed!"
dependencies:
- deploy
only:
- main⚠️ Points d’attention
Fichier : grafana/provisioning/datasources/datasource.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: trueFichier : grafana/provisioning/dashboards/dashboard.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /var/lib/grafana/dashboardsLe dashboard postgres-dashboard.json comprend :
{
"title": "PostgreSQL Monitoring Dashboard",
"panels": [
{
"title": "PostgreSQL Active Connections",
"type": "timeseries",
"targets": [
{
"expr": "pg_stat_database_numbackends{datname=\"monitoring_db\"}",
"legendFormat": "Active Connections"
}
]
},
{
"title": "PostgreSQL Status",
"type": "stat",
"targets": [
{
"expr": "pg_up",
"legendFormat": "PostgreSQL Status"
}
]
}
]
}Fichier : postgres/init.sql
-- Création d'une base de données de test
CREATE DATABASE monitoring_db;
-- Connexion à la base
\c monitoring_db;
-- Table de test pour générer des métriques
CREATE TABLE IF NOT EXISTS user_sessions (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
session_start TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
session_end TIMESTAMP,
active BOOLEAN DEFAULT TRUE
);
-- Données de test
INSERT INTO user_sessions (user_id, active)
VALUES
(1, true),
(2, true),
(3, false),
(4, true),
(5, false);
-- Utilisateur pour les métriques
CREATE USER monitoring WITH PASSWORD 'monitoring123';
GRANT CONNECT ON DATABASE monitoring_db TO monitoring;
GRANT USAGE ON SCHEMA public TO monitoring;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO monitoring;Fichier : test-stack.sh
#!/bin/bash
echo "=== Test de la Stack d'Observabilité ==="
# Test 1: Vérification des services
echo "1. Vérification des services..."
docker-compose ps
# Test 2: Test Prometheus
echo "2. Test de Prometheus..."
curl -f http://localhost:9090/-/ready || { echo "Prometheus non disponible"; exit 1; }
# Test 3: Test des métriques PostgreSQL
echo "3. Test des métriques PostgreSQL..."
curl -s http://localhost:9187/metrics | grep -q "pg_up" || { echo "Métriques PostgreSQL manquantes"; exit 1; }
# Test 4: Test Grafana
echo "4. Test de Grafana..."
curl -f http://localhost:3000/api/health || { echo "Grafana non disponible"; exit 1; }
# Test 5: Test de la base de données
echo "5. Test de la base de données..."
docker exec postgres-db psql -U postgres -d monitoring_db -c "SELECT COUNT(*) FROM user_sessions;" || { echo "Base de données non accessible"; exit 1; }
echo "✅ Tous les tests sont passés avec succès!"Une fois déployé, accédez aux services via :
| Service | URL | Credentials |
|---|---|---|
| Grafana | http://localhost:3000 | admin / admin123 |
| Prometheus | http://localhost:9090 | - |
| PostgreSQL | localhost:5432 | postgres / postgres123 |
| Exporter | http://localhost:9187/metrics | - |
# Vérifier que Prometheus collecte les métriques
curl http://localhost:9090/api/v1/query?query=pg_up
# Vérifier les métriques de l'exporter
curl http://localhost:9187/metrics | grep pg_up# Cloner le repository
git clone <repository-url>
cd cicd-observability-challenge
# Lancer la stack
docker-compose up -d
# Vérifier le statut
docker-compose ps# Arrêter et supprimer les volumes
docker-compose down -v
# Nettoyer le système Docker
docker system prune -f✅ Stack Fonctionnelle
Cette solution répond complètement aux exigences du challenge en déployant une stack d’observabilité fonctionnelle avec un pipeline CI/CD automatisé et testé.