# Guide de Monitoring - Container Incus (Application Web PHP + MariaDB) ## Vue d'ensemble Ce guide décrit les métriques essentielles à surveiller pour un container Incus hébergeant une application web PHP avec API mobile et base de données MariaDB. --- ## 1. Ressources Système ### CPU **Pourquoi ?** Identifier les pics de charge et les processus gourmands ```bash # Utilisation CPU globale du container incus info nx4 | grep "CPU utilisé" # Détail par processus (dans le container) top -bn1 | head -20 htop ``` **Métriques à surveiller :** - Load average (devrait être < nombre de CPU) - % CPU par processus (MariaDB, PHP-FPM, nginx) **Seuils d'alerte :** - ⚠️ Warning : Load average > 70% des CPU - 🚨 Critical : Load average > 150% des CPU pendant >5min --- ### Mémoire RAM **Pourquoi ?** Éviter les OOM (Out of Memory) qui tuent les processus ```bash # Vue globale depuis le host incus info nx4 | grep "Mémoire" # Détail dans le container free -h ps aux --sort=-%mem | head -10 ``` **Métriques à surveiller :** - RAM utilisée / totale - Swap utilisé (devrait rester minimal) - Top processus consommateurs **Seuils d'alerte :** - ⚠️ Warning : RAM > 85% - 🚨 Critical : RAM > 95% ou Swap > 1GB --- ### Disque I/O **Pourquoi ?** MariaDB est très sensible aux lenteurs disque ```bash # Sur le host iostat -x 2 5 # Dans le container iostat -x 1 3 iotop -oa ``` **Métriques à surveiller :** - Latence disque (await) - IOPS (r/s, w/s) - % utilisation disque **Seuils d'alerte :** - ⚠️ Warning : await > 50ms - 🚨 Critical : await > 200ms ou %util > 90% --- ### Espace Disque **Pourquoi ?** MariaDB ne peut plus écrire si disque plein ```bash df -h du -sh /var/lib/mysql ``` **Seuils d'alerte :** - ⚠️ Warning : > 80% utilisé - 🚨 Critical : > 90% utilisé --- ## 2. PHP-FPM (Application Web) ### Pool de Workers **Pourquoi ?** Cause #1 des timeouts et coupures de service (votre cas !) ```bash # Nombre de workers actifs ps aux | grep "php-fpm: pool www" | wc -l # Config du pool grep "^pm" /etc/php/8.3/fpm/pool.d/www.conf # Logs d'alertes tail -f /var/log/php8.3-fpm.log | grep "max_children" ``` **Métriques critiques :** - Nombre de workers actifs vs `pm.max_children` - Warnings "max_children reached" - Slow requests (>2s) **Seuils d'alerte :** - ⚠️ Warning : Workers actifs > 80% de max_children - 🚨 Critical : Warning "max_children reached" apparaît **Configuration recommandée pour votre cas :** ```ini pm = dynamic pm.max_children = 50-100 (selon RAM disponible) pm.start_servers = 10-20 pm.min_spare_servers = 5-10 pm.max_spare_servers = 20-35 pm.max_requests = 500 ``` --- ### Temps de Réponse PHP **Pourquoi ?** Scripts lents = workers bloqués ```bash # Activer le slow log PHP-FPM # Dans /etc/php/8.3/fpm/pool.d/www.conf slowlog = /var/log/php8.3-fpm-slow.log request_slowlog_timeout = 3s # Voir les requêtes lentes tail -f /var/log/php8.3-fpm-slow.log ``` **Seuils d'alerte :** - ⚠️ Warning : Requêtes > 3s - 🚨 Critical : Requêtes > 10s ou timeouts fréquents --- ## 3. MariaDB / MySQL ### Connexions **Pourquoi ?** Trop de connexions = refus de nouvelles connexions ```bash mysql -e "SHOW STATUS LIKE 'Threads_connected';" mysql -e "SHOW STATUS LIKE 'Max_used_connections';" mysql -e "SHOW VARIABLES LIKE 'max_connections';" mysql -e "SHOW FULL PROCESSLIST;" ``` **Métriques critiques :** - Connexions actives vs max_connections - Connexions en attente / bloquées - Requêtes longues (>5s) **Seuils d'alerte :** - ⚠️ Warning : Connexions > 80% de max_connections - 🚨 Critical : Connexions = max_connections **Config recommandée :** ```ini max_connections = 200-500 (selon votre trafic) ``` --- ### Slow Queries **Pourquoi ?** Requêtes lentes = workers PHP bloqués ```bash # Activer le slow query log mysql -e "SET GLOBAL slow_query_log = 'ON';" mysql -e "SET GLOBAL long_query_time = 2;" mysql -e "SET GLOBAL log_queries_not_using_indexes = 'ON';" # Voir les slow queries tail -f /var/lib/mysql/slow-query.log # ou mysqldumpslow /var/lib/mysql/slow-query.log ``` **Seuils d'alerte :** - ⚠️ Warning : Requêtes > 2s - 🚨 Critical : Requêtes > 10s ou >50 slow queries/min --- ### InnoDB Buffer Pool **Pourquoi ?** Si trop petit, beaucoup de lectures disque (lent) ```bash mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" mysql -e "SHOW STATUS LIKE 'Innodb_buffer_pool_read%';" ``` **Métriques critiques :** - Buffer pool hit ratio (devrait être >99%) - Read requests vs reads from disk **Config recommandée :** - `innodb_buffer_pool_size` = 70-80% de la RAM dédiée à MySQL - Pour 20GB de données : `innodb_buffer_pool_size = 16G` --- ### Deadlocks et Locks **Pourquoi ?** Peuvent causer des timeouts ```bash mysql -e "SHOW ENGINE INNODB STATUS\G" | grep -A 50 "LATEST DETECTED DEADLOCK" mysql -e "SHOW OPEN TABLES WHERE In_use > 0;" ``` **Seuils d'alerte :** - ⚠️ Warning : >1 deadlock/heure - 🚨 Critical : Tables lockées >30s --- ## 4. Nginx / Serveur Web ### Connexions et Erreurs **Pourquoi ?** Identifier les 502/504 (backend timeout) ```bash # Connexions actives netstat -an | grep :80 | wc -l netstat -an | grep :443 | wc -l # Erreurs récentes tail -100 /var/log/nginx/error.log | grep -E "502|504|timeout" tail -100 /var/log/nginx/access.log | grep -E " 502 | 504 " ``` **Métriques critiques :** - Erreurs 502 Bad Gateway (PHP-FPM down) - Erreurs 504 Gateway Timeout (PHP-FPM trop lent) - Connexions actives **Seuils d'alerte :** - ⚠️ Warning : >5 erreurs 502/504 en 5min - 🚨 Critical : >20 erreurs 502/504 en 5min --- ### Worker Connections **Pourquoi ?** Limite le nombre de connexions simultanées ```bash # Config nginx grep worker_connections /etc/nginx/nginx.conf ps aux | grep nginx | wc -l ``` **Config recommandée :** ```nginx worker_processes auto; worker_connections 2048; ``` --- ## 5. Réseau ### Bande Passante **Pourquoi ?** Identifier les pics de trafic ```bash # Depuis le host incus info nx4 | grep -A 10 "eth0:" # Dans le container iftop -i eth0 vnstat -i eth0 ``` **Métriques :** - Octets reçus/émis - Paquets reçus/émis - Erreurs réseau --- ### Connexions TCP **Pourquoi ?** Trop de connexions TIME_WAIT = problème ```bash netstat -an | grep -E "ESTABLISHED|TIME_WAIT|CLOSE_WAIT" | wc -l ss -s ``` **Seuils d'alerte :** - ⚠️ Warning : >1000 connexions TIME_WAIT - 🚨 Critical : >5000 connexions TIME_WAIT --- ## 6. Logs et Événements ### Logs Système ```bash # Container Debian journalctl -u nginx -n 100 journalctl -u php8.3-fpm -n 100 journalctl -u mariadb -n 100 # Container Alpine (si pas de systemd) tail -100 /var/log/messages ``` ### Logs Applicatifs ```bash # PHP errors tail -100 /var/log/php8.3-fpm.log tail -100 /var/www/html/logs/*.log # Nginx tail -100 /var/log/nginx/error.log tail -100 /var/log/nginx/access.log ``` --- ## 7. Scripts de Monitoring Automatisés ### Script de Monitoring Global Créer `/root/monitor.sh` : ```bash #!/bin/bash LOG_FILE="/var/log/system-monitor.log" ALERT_FILE="/var/log/alerts.log" echo "=== Monitoring $(date) ===" >> $LOG_FILE # 1. CPU LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}') echo "Load: $LOAD" >> $LOG_FILE # 2. RAM RAM_PERCENT=$(free | awk '/Mem:/ {printf("%.1f"), ($3/$2)*100}') echo "RAM: ${RAM_PERCENT}%" >> $LOG_FILE if (( $(echo "$RAM_PERCENT > 85" | bc -l) )); then echo "[WARNING] RAM > 85%: ${RAM_PERCENT}%" >> $ALERT_FILE fi # 3. PHP-FPM Workers PHP_WORKERS=$(ps aux | grep "php-fpm: pool www" | wc -l) PHP_MAX=$(grep "^pm.max_children" /etc/php/8.3/fpm/pool.d/www.conf | awk '{print $3}') echo "PHP Workers: $PHP_WORKERS / $PHP_MAX" >> $LOG_FILE if [ $PHP_WORKERS -gt $(echo "$PHP_MAX * 0.8" | bc) ]; then echo "[WARNING] PHP Workers > 80%: $PHP_WORKERS / $PHP_MAX" >> $ALERT_FILE fi # 4. MySQL Connexions MYSQL_CONN=$(mysql -e "SHOW STATUS LIKE 'Threads_connected';" | awk 'NR==2 {print $2}') MYSQL_MAX=$(mysql -e "SHOW VARIABLES LIKE 'max_connections';" | awk 'NR==2 {print $2}') echo "MySQL Connections: $MYSQL_CONN / $MYSQL_MAX" >> $LOG_FILE if [ $MYSQL_CONN -gt $(echo "$MYSQL_MAX * 0.8" | bc) ]; then echo "[WARNING] MySQL Connections > 80%: $MYSQL_CONN / $MYSQL_MAX" >> $ALERT_FILE fi # 5. Disque DISK_PERCENT=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//') echo "Disk: ${DISK_PERCENT}%" >> $LOG_FILE if [ $DISK_PERCENT -gt 80 ]; then echo "[WARNING] Disk > 80%: ${DISK_PERCENT}%" >> $ALERT_FILE fi # 6. Erreurs nginx NGINX_ERRORS=$(grep -c "error" /var/log/nginx/error.log | tail -100) if [ $NGINX_ERRORS -gt 10 ]; then echo "[WARNING] Nginx errors: $NGINX_ERRORS in last 100 lines" >> $ALERT_FILE fi echo "" >> $LOG_FILE ``` **Installation :** ```bash chmod +x /root/monitor.sh # Exécuter toutes les 5 minutes (crontab -l 2>/dev/null; echo "*/5 * * * * /root/monitor.sh") | crontab - ``` --- ### Script de Monitoring PHP-FPM Spécifique Créer `/root/monitor-php-fpm.sh` : ```bash #!/bin/bash LOG="/var/log/php-fpm-monitor.log" TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') # Compter les workers (sans grep lui-même) WORKERS=$(ps aux | grep 'php-fpm: pool www' | grep -v grep | wc -l) MAX_CHILDREN=$(grep '^pm.max_children' /etc/php/8.3/fpm/pool.d/www.conf | awk '{print $3}') PERCENT=$(echo "scale=1; ($WORKERS / $MAX_CHILDREN) * 100" | bc) # Log au format: timestamp,workers,max,percentage echo "$TIMESTAMP,$WORKERS,$MAX_CHILDREN,$PERCENT%" >> $LOG # Alerte si >80% if (( $(echo "$PERCENT > 80" | bc -l) )); then echo "[$TIMESTAMP] [ALERT] PHP Workers > 80%: $WORKERS / $MAX_CHILDREN ($PERCENT%)" >> /var/log/alerts.log fi # Vérifier si max_children atteint dans les logs récents if tail -10 /var/log/php8.3-fpm.log | grep -q "max_children"; then echo "[$TIMESTAMP] [CRITICAL] MAX_CHILDREN REACHED!" >> /var/log/alerts.log tail -3 /var/log/php8.3-fpm.log >> /var/log/alerts.log fi ``` **Installation :** ```bash chmod +x /root/monitor-php-fpm.sh # Exécuter toutes les minutes (crontab -l 2>/dev/null; echo "* * * * * /root/monitor-php-fpm.sh") | crontab - ``` **Visualiser les données :** ```bash # Afficher les dernières 60 minutes tail -60 /var/log/php-fpm-monitor.log # Voir l'évolution graphique (nécessite gnuplot) echo 'set datafile separator ","; plot "/var/log/php-fpm-monitor.log" using 2 with lines title "Workers"' | gnuplot -p # Statistiques rapides echo "Max workers last hour: $(tail -60 /var/log/php-fpm-monitor.log | cut -d',' -f2 | sort -n | tail -1)" echo "Min workers last hour: $(tail -60 /var/log/php-fpm-monitor.log | cut -d',' -f2 | sort -n | head -1)" echo "Avg workers last hour: $(tail -60 /var/log/php-fpm-monitor.log | cut -d',' -f2 | awk '{sum+=$1} END {print sum/NR}')" # Alertes récentes tail -20 /var/log/alerts.log | grep "PHP Workers" ``` **Rotation automatique des logs :** Créer `/etc/logrotate.d/php-fpm-monitor` : ``` /var/log/php-fpm-monitor.log { daily rotate 30 compress missingok notifempty } ``` --- ## 8. Solutions de Monitoring Automatisées ### Option 1 : Netdata (Recommandé) **Avantages :** Installation simple, interface web, détection auto des services ```bash # Installation bash <(curl -Ss https://get.netdata.cloud/kickstart.sh) --dont-wait # Accessible sur http://IP:19999 # Détecte automatiquement : PHP-FPM, MariaDB, Nginx, ressources système ``` **Métriques auto-détectées :** - ✅ CPU, RAM, I/O, réseau - ✅ PHP-FPM (workers, slow requests) - ✅ MariaDB (connexions, queries, locks) - ✅ Nginx (connexions, erreurs) --- ### Option 2 : Prometheus + Grafana **Avantages :** Professionnel, historique long terme, alerting avancé ```bash # Exposer les métriques Incus incus config set core.metrics_address :8443 # Installer Prometheus + Grafana # (plus complexe, voir doc officielle) ``` --- ### Option 3 : Scripts + Monitoring Simple Si vous préférez rester léger, surveillez manuellement avec : ```bash # Dashboard temps réel watch -n 2 'echo "=== RESSOURCES ==="; free -h | head -2; echo ""; echo "=== PHP-FPM ==="; ps aux | grep "php-fpm: pool" | wc -l; echo ""; echo "=== MySQL ==="; mysql -e "SHOW STATUS LIKE \"Threads_connected\";" 2>/dev/null; echo ""; echo "=== NGINX ==="; netstat -an | grep :80 | wc -l' ``` --- ## 9. Checklist de Diagnostic en Cas de Problème ### Coupures / Timeouts 1. ✅ **Vérifier PHP-FPM** : `tail /var/log/php8.3-fpm.log | grep max_children` 2. ✅ **Vérifier MySQL** : `mysql -e "SHOW PROCESSLIST;"` 3. ✅ **Vérifier nginx** : `tail /var/log/nginx/error.log | grep -E "502|504"` 4. ✅ **Vérifier RAM** : `free -h` 5. ✅ **Vérifier I/O** : `iostat -x 1 5` ### Lenteurs 1. ✅ **Slow queries MySQL** : `tail /var/lib/mysql/slow-query.log` 2. ✅ **Slow PHP** : `tail /var/log/php8.3-fpm-slow.log` 3. ✅ **CPU** : `top -bn1 | head -20` 4. ✅ **I/O disque** : `iotop -oa` ### Crashes / Erreurs 502 1. ✅ **PHP-FPM status** : `systemctl status php8.3-fpm` 2. ✅ **OOM Killer** : `dmesg | grep -i "out of memory"` 3. ✅ **Logs PHP** : `tail -100 /var/log/php8.3-fpm.log` --- ## 10. Optimisations Recommandées ### PHP-FPM ```ini # /etc/php/8.3/fpm/pool.d/www.conf pm = dynamic pm.max_children = 50-100 pm.start_servers = 10-20 pm.min_spare_servers = 5-10 pm.max_spare_servers = 20-35 pm.max_requests = 500 request_slowlog_timeout = 3s ``` ### MariaDB ```ini # /etc/mysql/mariadb.conf.d/50-server.cnf max_connections = 200-500 innodb_buffer_pool_size = 16G # 70-80% de la RAM MySQL slow_query_log = 1 long_query_time = 2 log_queries_not_using_indexes = 1 ``` ### Nginx ```nginx # /etc/nginx/nginx.conf worker_processes auto; worker_connections 2048; keepalive_timeout 30; ``` --- ## Résumé des Seuils Critiques | Métrique | Warning | Critical | |----------|---------|----------| | **RAM** | >85% | >95% | | **CPU Load** | >70% CPU count | >150% CPU count | | **Disk I/O await** | >50ms | >200ms | | **Disk Space** | >80% | >90% | | **PHP Workers** | >80% max | max_children reached | | **MySQL Connections** | >80% max | = max_connections | | **Slow Queries** | >2s | >10s ou >50/min | | **Nginx 502/504** | >5 en 5min | >20 en 5min | --- ## Contacts et Escalade En cas d'incident critique : 1. Vérifier les logs (`/var/log/alerts.log`) 2. Identifier le goulot (CPU/RAM/PHP/MySQL) 3. Appliquer le correctif approprié 4. Documenter l'incident --- **Date de création :** 2025-10-18 **Dernière mise à jour :** 2025-10-18 **Version :** 1.0