OPTRALIS - Specifications Infrastructure & Scaling
Document technique : Architecture DB, optimisations, et plan de scaling
1. Architecture Actuelle
Stack Technique
| Composant |
Technologie |
Version |
| Base de donnees |
PostgreSQL + TimescaleDB |
16 |
| Cache |
Redis |
7-alpine |
| Backend API |
Go + Fiber v2 |
1.23+ |
| Dashboard |
Next.js 14 |
App Router |
| AI Service |
Go + Claude API |
Sonnet 4 |
| Reverse Proxy |
Caddy |
2-alpine |
| Conteneurisation |
Docker Compose |
- |
Hebergement Production
- Provider : Hetzner Cloud
- Region : EU (Falkenstein/Nuremberg)
- VPS actuel : CX22 (2vCPU, 4GB RAM)
- Cout actuel : ~5 EUR/mois
2. Optimisations Base de Donnees
2.1 TimescaleDB - Hypertables
Les tables time-series sont converties en hypertables pour le partitionnement automatique :
| Table |
Colonne temps |
Chunk interval |
Compression |
metrics |
recorded_at |
1 day |
Oui (2j) |
disk_info |
recorded_at |
1 day |
Oui (2j) |
event_logs |
recorded_at |
1 day |
Oui (2j) |
smart_data |
recorded_at |
1 day |
Oui (2j) |
activity_logs |
timestamp |
auto |
Non |
service_uptime |
checked_at |
auto |
Non |
2.2 Compression
-- Configuration compression (segmentby machine_id pour queries efficaces)
ALTER TABLE metrics SET (
timescaledb.compress,
timescaledb.compress_segmentby = 'machine_id'
);
-- Politique : compresser apres 2 jours
SELECT add_compression_policy('metrics', INTERVAL '2 days');
Gain typique : 80-95% de reduction de stockage
2.3 Politiques de Retention
Retention TimescaleDB (filet de securite)
| Table |
Retention max |
| metrics, disk_info, event_logs, smart_data |
365 jours |
| activity_logs |
30 jours |
| service_uptime |
30 jours |
Retention par Licence (cleanup Go)
| Licence |
Metriques |
Events |
Aggregates |
| Trial |
7 jours |
7 jours |
30 jours |
| Starter |
30 jours |
30 jours |
90 jours |
| Essentials |
30 jours |
30 jours |
90 jours |
| Pro |
90 jours |
90 jours |
180 jours |
| Business |
90 jours |
90 jours |
180 jours |
| Enterprise |
365 jours |
365 jours |
730 jours |
2.4 Continuous Aggregates (Vues Materialisees)
Pre-calcul des agregations horaires pour accelerer les dashboards :
-- metrics_hourly : CPU, RAM, temperature
CREATE MATERIALIZED VIEW metrics_hourly
WITH (timescaledb.continuous) AS
SELECT
machine_id,
time_bucket('1 hour', recorded_at) AS bucket,
AVG(cpu_percent) as cpu_avg,
MAX(cpu_percent) as cpu_max,
AVG(ram_percent) as ram_avg,
MAX(ram_percent) as ram_max,
COUNT(*) as data_points
FROM metrics
GROUP BY machine_id, bucket;
-- Refresh policy : toutes les heures
SELECT add_continuous_aggregate_policy('metrics_hourly',
start_offset => INTERVAL '31 days',
end_offset => INTERVAL '1 hour',
schedule_interval => INTERVAL '1 hour'
);
Vues disponibles :
- metrics_hourly - CPU, RAM, temperature
- disk_hourly - Utilisation disque
- network_hourly - Bande passante, latence, packet loss
2.5 Connection Pool
DB.SetMaxOpenConns(25) // Max connexions simultanees
DB.SetMaxIdleConns(10) // Connexions idle en reserve
DB.SetConnMaxLifetime(5 * time.Minute) // Recyclage connexions
2.6 Index Strategiques
| Type |
Exemple |
Usage |
| Standard |
idx_metrics_machine_time |
Queries temporelles |
| Fonctionnel |
idx_machines_hostname_lower |
Recherche case-insensitive |
| Partiel |
WHERE revoked_at IS NULL |
Certificats actifs |
| GIN |
label_selector JSONB |
Filtrage par labels |
Total : 30+ index optimises
3. Plan de Scaling
3.1 Paliers VPS Hetzner
| Machines |
VPS |
Specs |
Prix/mois |
Bottleneck |
| 1-50 |
CX22 |
2vCPU, 4GB RAM, 40GB SSD |
~5 EUR |
- |
| 50-150 |
CX32 |
4vCPU, 8GB RAM, 80GB SSD |
~13 EUR |
TimescaleDB RAM |
| 150-400 |
CX42 |
8vCPU, 16GB RAM, 160GB SSD |
~25 EUR |
TimescaleDB + API |
| 400-800 |
CX52 |
16vCPU, 32GB RAM, 320GB SSD |
~50 EUR |
I/O disque |
| 800-1500 |
CCX33 |
8 dCPU, 32GB RAM, 240GB NVMe |
~75 EUR |
Separer services |
| 1500+ |
Multi-VPS |
Architecture distribuee |
~120 EUR+ |
- |
RAM minimale = 2GB + (machines x 0.02GB)
CPU minimale = 2 + (machines / 100)
Stockage/mois = machines x 0.5GB (avec compression)
3.3 Points de Vigilance par Palier
50-150 machines
- [ ] Passer a 8GB RAM (index TimescaleDB en memoire)
- [ ] Activer
timescaledb.compress si pas deja fait
- [ ] Verifier que les continuous aggregates sont actifs
150-400 machines
- [ ] CPU : les requetes d'agregation deviennent lourdes
- [ ] Redis : augmenter a 256MB si beaucoup de cache AI
- [ ] Monitoring : activer les alertes de performance DB
400-800 machines
- [ ] Stockage : prevoir ~500MB-1GB/machine/mois (compresse)
- [ ] I/O : passer en NVMe obligatoire
- [ ] Backup : temps de backup augmente significativement
800+ machines
Architecture distribuee recommandee :
VPS 1 (DB) : PostgreSQL/TimescaleDB dedié
VPS 2 (API) : API + Dashboard + Redis
VPS 3 (AI) : AI-service (si usage intensif)
3.4 Metriques de Surveillance
Commandes pour monitorer la DB :
-- Taille totale de la base
SELECT pg_size_pretty(pg_database_size('monitoring'));
-- Top 10 tables par taille
SELECT
schemaname || '.' || tablename AS table,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
LIMIT 10;
-- Etat des chunks TimescaleDB
SELECT
hypertable_name,
chunk_name,
pg_size_pretty(total_bytes) as size,
is_compressed
FROM timescaledb_information.chunks
ORDER BY total_bytes DESC
LIMIT 20;
-- Taux de compression
SELECT
hypertable_name,
pg_size_pretty(before_compression_total_bytes) as before,
pg_size_pretty(after_compression_total_bytes) as after,
ROUND(100 - (after_compression_total_bytes::numeric / before_compression_total_bytes * 100), 1) as compression_ratio
FROM timescaledb_information.compression_settings cs
JOIN timescaledb_information.hypertables h USING (hypertable_schema, hypertable_name)
LEFT JOIN LATERAL (
SELECT
SUM(before_compression_total_bytes) as before_compression_total_bytes,
SUM(after_compression_total_bytes) as after_compression_total_bytes
FROM timescaledb_information.compressed_chunk_stats
WHERE hypertable_name = h.hypertable_name
) stats ON true;
4. Couts Infrastructure
4.1 Couts Fixes (VPS)
| Nb Clients |
Machines estimees |
VPS |
Cout/mois |
| 10 |
~100 |
CX22 |
5 EUR |
| 50 |
~500 |
CX32 |
13 EUR |
| 100 |
~1000 |
CX42 |
25 EUR |
| 500 |
~5000 |
Multi-VPS |
120 EUR |
4.2 Couts Variables (par machine)
| Composant |
Cout/machine/mois |
| Stockage TimescaleDB (compresse) |
0.02 EUR |
| Processing CPU |
0.01 EUR |
| Bande passante |
inclus (20TB/mois Hetzner) |
| Total |
~0.03 EUR |
4.3 Cout Total par Plan
| Plan |
Machines max |
Cout Infra |
Cout API |
Cout Total |
Prix |
Marge |
| Starter |
25 |
0.75 EUR |
3.50 EUR |
4.25 EUR |
79 EUR |
95% |
| Essentials |
75 |
2.25 EUR |
7 EUR |
9.25 EUR |
169 EUR |
95% |
| Pro |
200 |
6 EUR |
35 EUR |
41 EUR |
349 EUR |
88% |
| Business |
500 |
15 EUR |
115 EUR |
130 EUR |
649 EUR |
80% |
| Enterprise |
1000+ |
30 EUR+ |
350 EUR |
380 EUR+ |
Devis |
Variable |
5. Checklist Pre-Production
Base de Donnees
- [x] TimescaleDB extension activee
- [x] Hypertables configurees (metrics, disk_info, event_logs, smart_data)
- [x] Compression activee (segmentby machine_id)
- [x] Politiques de retention configurees
- [x] Continuous aggregates crees (metrics_hourly, disk_hourly, network_hourly)
- [x] Index optimises (30+)
- [x] Connection pool configure (25 max, 10 idle)
Securite
- [x] Statement timeout (30s)
- [x] SSL/TLS sur connexion DB (en production)
- [x] Backups automatiques
Monitoring
- [ ] Alertes taille DB (seuil 80%)
- [ ] Alertes connexions DB (seuil 20/25)
- [ ] Dashboard performance DB (Grafana optionnel)
6. Commandes Utiles
Docker
# Taille base de donnees
docker exec optralis-db psql -U postgres -d monitoring -c \
"SELECT pg_size_pretty(pg_database_size('monitoring'));"
# Forcer compression des chunks
docker exec optralis-db psql -U postgres -d monitoring -c \
"SELECT compress_chunk(c) FROM show_chunks('metrics') c WHERE NOT is_compressed;"
# Vacuum analyze (maintenance)
docker exec optralis-db psql -U postgres -d monitoring -c \
"VACUUM ANALYZE;"
Backup
# Backup complet
docker exec optralis-db pg_dump -U postgres monitoring | gzip > backup_$(date +%Y%m%d).sql.gz
# Restore
gunzip -c backup_20260106.sql.gz | docker exec -i optralis-db psql -U postgres monitoring
7. Features Infrastructure Avancées
Gateway Locale (Pro+)
Composant permettant le monitoring de machines sans accès Internet direct.
| Plan |
Nombre de gateways |
| Pro |
1 site |
| Business |
3 sites |
| Enterprise |
Illimité |
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Site isolé (LAN) │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Agent 1 │ │ Agent 2 │ │ Agent N │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Gateway Locale │ (buffer + relay) │
│ └───────┬────────┘ │
│ │ │
└──────────────────────┼───────────────────────────────────────────┘
│ HTTPS (quand disponible)
▼
┌────────────────┐
│ Optralis Cloud │
└────────────────┘
Fonctionnalités
| Fonctionnalité |
Description |
| Buffer offline |
Stockage local des métriques pendant les coupures Internet |
| Compression |
Réduction de la bande passante (gzip) |
| Agrégation |
Regroupement des données avant envoi |
| Retry automatique |
Réessai avec backoff exponentiel |
| Chiffrement |
mTLS entre agents et gateway |
Installation
# Télécharger la gateway
curl -O https://dl.optralis.com/gateway/optralis-gateway-linux-amd64
# Configuration
cat > /etc/optralis/gateway.yml << EOF
server:
port: 8443
tls:
cert: /etc/optralis/gateway.crt
key: /etc/optralis/gateway.key
upstream:
url: https://api.optralis.com
timeout: 30s
retry_max: 5
buffer:
path: /var/lib/optralis/buffer
max_size_mb: 500
retention_hours: 72
EOF
# Démarrer
systemctl enable optralis-gateway
systemctl start optralis-gateway
Configuration Agent
# agent.yml - pointer vers la gateway locale
api:
endpoint: https://gateway.local:8443
# La gateway relaye vers le cloud
Provider Terraform pour gérer l'infrastructure Optralis as Code.
Installation
terraform {
required_providers {
optralis = {
source = "2lacs-it/optralis"
version = "~> 1.0"
}
}
}
provider "optralis" {
api_key = var.optralis_api_key
# ou via OPTRALIS_API_KEY env var
}
Ressources disponibles
| Ressource |
Description |
optralis_group |
Groupe de machines |
optralis_label |
Label (tag key=value) |
optralis_alert_rule |
Règle d'alerte |
optralis_notification_channel |
Canal de notification |
optralis_user |
Utilisateur client |
Exemples
# Créer un groupe
resource "optralis_group" "production" {
name = "Production"
description = "Serveurs de production"
color = "#ef4444"
}
# Créer une règle d'alerte
resource "optralis_alert_rule" "high_cpu" {
name = "CPU > 90%"
metric = "cpu_percent"
operator = ">"
threshold = 90
severity = "critical"
target_type = "group"
target_id = optralis_group.production.id
notification_channels = [
optralis_notification_channel.teams.id
]
}
# Canal Teams
resource "optralis_notification_channel" "teams" {
name = "Teams - IT"
type = "teams"
webhook = var.teams_webhook_url
enabled = true
}
Data Sources
# Récupérer les machines d'un groupe
data "optralis_machines" "prod" {
group_id = optralis_group.production.id
}
# Récupérer les métriques
data "optralis_metrics" "cpu" {
machine_id = data.optralis_machines.prod.machines[0].id
metric = "cpu_percent"
period = "24h"
}
Intégration Ansible (Business+)
Collection Ansible pour automatiser la gestion Optralis.
Installation
ansible-galaxy collection install twolacs.optralis
Modules disponibles
| Module |
Description |
optralis_machine_info |
Récupérer les infos d'une machine |
optralis_group |
Gérer les groupes |
optralis_label |
Assigner des labels |
optralis_maintenance |
Activer/désactiver le mode maintenance |
optralis_alert_rule |
Gérer les règles d'alertes |
Exemples
---
# Playbook : maintenance.yml
- name: Activer le mode maintenance avant déploiement
hosts: localhost
tasks:
- name: Mode maintenance ON
twolacs.optralis.optralis_maintenance:
hostname: "{{ target_server }}"
state: enabled
duration: 30 # minutes
reason: "Déploiement applicatif"
- name: Déployer l'application
include_role:
name: deploy_app
- name: Mode maintenance OFF
twolacs.optralis.optralis_maintenance:
hostname: "{{ target_server }}"
state: disabled
---
# Playbook : labeling.yml
- name: Labelliser les machines par rôle
hosts: localhost
tasks:
- name: Assigner label role=webserver
twolacs.optralis.optralis_label:
hostname: "{{ item }}"
labels:
role: webserver
env: production
loop: "{{ groups['webservers'] }}"
Inventaire dynamique
# inventory_optralis.yml
plugin: twolacs.optralis.inventory
api_key: "{{ lookup('env', 'OPTRALIS_API_KEY') }}"
# Grouper par labels
keyed_groups:
- key: labels.env
prefix: env
- key: labels.role
prefix: role
# Filtrer
filters:
- labels.env == "production"
# Utilisation
ansible-inventory -i inventory_optralis.yml --list
ansible -i inventory_optralis.yml env_production -m ping
VMware Monitoring (Essentials+)
Surveillance des environnements VMware vSphere.
| Plan |
Fonctionnalités |
| Essentials |
Détection VM, métriques de base |
| Pro |
vCenter integration, datastores |
| Business+ |
Cluster monitoring, DRS/HA alerts |
Métriques VMware
| Métrique |
Description |
Source |
vm_cpu_ready |
CPU ready time (%) |
vCenter API |
vm_memory_balloon |
Memory ballooning (MB) |
vCenter API |
datastore_usage |
Utilisation datastore (%) |
vCenter API |
host_cpu_usage |
CPU ESXi host (%) |
vCenter API |
cluster_ha_status |
Statut HA cluster |
vCenter API |
Configuration vCenter
# Settings > Intégrations > VMware
vmware:
vcenter_url: "https://vcenter.local"
username: "optralis@vsphere.local"
password: "********"
insecure_ssl: false
# Filtres optionnels
datacenter: "DC1"
cluster: "Cluster-Prod"
# Intervalle de collecte
poll_interval: 60s
Détection automatique
L'agent Optralis détecte automatiquement s'il s'exécute sur une VM VMware :
// Patterns de détection
| Méthode | Pattern | Résultat |
|---------|---------|----------|
| SCSI vendor | "VMware" | is_virtual=true, hypervisor="vmware" |
| DMI system | "VMware Virtual Platform" | is_virtual=true |
| CPU features | "VMwareVMware" | is_virtual=true |
Document genere janvier 2026