E-NO
Sauvegarde Apache Hop 6 min de lecture

Apache Hop : Sauvegarde et restauration avec exemples pratiques — Guide d'implémentation

calendar_today Publié : 2026-08-18
update Dernière mise à jour : 2026-08-18
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Apache Hop : Sauvegarde et restauration avec exemples pratiques — Guide d'implémentation ».

Les pipelines et workflows Apache Hop constituent une infrastructure de données critique pour de nombreuses organisations. Lorsqu'un référentiel de métadonnées se corrompt, qu'un pipeline échoue silencieusement ou qu'une migration d'environnement tourne mal, la capacité à restaurer un état sain connu détermine le temps de récupération. Ce guide couvre les procédures pratiques de sauvegarde et de restauration pour les déploiements Apache Hop, des instances de développement autonomes aux clusters Kubernetes en production. Vous apprendrez quoi sauvegarder, comment l'automatiser, comment vérifier l'intégrité de la restauration et comment récupérer en cas d'incident.

Comprendre ce qui doit être protégé

Apache Hop stocke sa configuration, ses métadonnées et son état d'exécution à plusieurs endroits distincts. Omettre l'un d'eux crée des lacunes de restauration qui ne surgissent qu'au moment d'un incident réel.

Référentiel de métadonnées — La colonne vertébrale de tout projet Hop. Que vous utilisiez un référentiel basé sur des fichiers (fichiers JSON dans un répertoire de projet) ou un référentiel de base de données (PostgreSQL, MySQL, MariaDB ou H2), celui-ci contient les pipelines, workflows, transformations, variables et définitions de connexions. Les référentiels basés sur fichiers résident dans votre dossier de projet ; les référentiels de base de données nécessitent des vidages au niveau du schéma.

Fichiers de configuration — Le fichier hop-config.json (généralement dans ~/.hop/ ou $HOP_CONFIG_DIRECTORY) contient les préférences de l'interface graphique, les projets récents et les configurations de plugins. Les fichiers d'environnement (hop-environments.json) définissent les contextes de développement, test et production avec leurs remplacements de variables. Le répertoire projects/ contient les fichiers project-config.json spécifiques à chaque projet qui associent des noms logiques à des chemins physiques.

Artefacts d'exécution — Fichiers journaux, résultats d'exécution et fichiers temporaires dans $HOP_LOG_DIRECTORY ou le dossier logs/ du projet. Bien que non strictement requis pour la restauration, ils accélèrent l'analyse des causes racines après un échec.

Dépendances externes — Pilotes JDBC dans plugins/databases/, plugins personnalisés dans plugins/, et tout fichier référencé par des chemins relatifs dans les métadonnées du pipeline (entrées CSV, schémas Avro, scripts Python). Ces éléments se trouvent en dehors de l'installation principale de Hop mais sont essentiels à l'exécution des pipelines.

Alignement des versions — Enregistrez la version exacte de Hop (hop-gui --version ou hop-run --version), la version de Java (java -version) et la version du schéma du référentiel de base de données. Une restauration sur une version incompatible échoue souvent silencieusement ou produit une corruption de données subtile.

Exécutez cette commande d'inventaire sur tout nœud Hop pour capturer la ligne de base :

#!/usr/bin/env bash
# capture-hop-inventory.sh — exécuter en tant que compte de service propriétaire de l'installation Hop
set -euo pipefail

HOP_HOME="${HOP_HOME:-/opt/hop}"
HOP_CONFIG_DIR="${HOP_CONFIG_DIR:-$HOME/.hop}"
PROJECT_DIR="${PROJECT_DIR:-/data/hop-projects}"
TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")
OUT_DIR="/var/backups/hop/inventory/$TIMESTAMP"

mkdir -p "$OUT_DIR"

echo "=== Version Apache Hop ===" > "$OUT_DIR/versions.txt"
"$HOP_HOME/hop-run" --version >> "$OUT_DIR/versions.txt" 2>&1
java -version >> "$OUT_DIR/versions.txt" 2>&1

echo "=== Répertoire de configuration ===" >> "$OUT_DIR/versions.txt"
ls -la "$HOP_CONFIG_DIR" >> "$OUT_DIR/versions.txt"

echo "=== Structure du projet ===" >> "$OUT_DIR/versions.txt"
find "$PROJECT_DIR" -maxdepth 3 -type f -name "*.json" | head -50 >> "$OUT_DIR/versions.txt"

echo "=== Référentiel de base de données (si configuré) ===" >> "$OUT_DIR/versions.txt"
if  -f "$HOP_CONFIG_DIR/hop-config.json" ; then
  grep -A5 -B5 "databaseRepository" "$HOP_CONFIG_DIR/hop-config.json" >> "$OUT_DIR/versions.txt" || true
fi

echo "Inventaire sauvegardé dans $OUT_DIR"

Stratégies de sauvegarde par modèle de déploiement

Déploiement autonome ou basé sur VM

Pour les déploiements mono-nœud ou actif-passif sur VM, un instantané du système de fichiers combiné à un vidage de base de données offre une couverture complète.

Sauvegarde de référentiel basé sur fichiers

#!/usr/bin/env bash
# backup-hop-file-repo.sh — cron quotidien à 02:00 UTC
set -euo pipefail

PROJECT_ROOT="/data/hop-projects"
BACKUP_ROOT="/var/backups/hop/file-repo"
RETENTION_DAYS=14
TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")
DEST="$BACKUP_ROOT/$TIMESTAMP"

mkdir -p "$DEST"

# Exclure les journaux et fichiers temporaires ; ils gonflent les sauvegardes et restaurent un état obsolète
rsync -av --delete \
  --exclude="*/logs/*" \
  --exclude="*/tmp/*" \
  --exclude="*.tmp" \
  --exclude="*.bak" \
  "$PROJECT_ROOT/" "$DEST/projects/"

# Sauvegarder le répertoire de configuration séparément (peu volumineux, change peu souvent)
rsync -av "$HOME/.hop/" "$DEST/config/"

# Créer un manifeste pour la vérification
find "$DEST" -type f -exec sha256sum {} + > "$DEST/manifest.sha256"

# Nettoyer les anciennes sauvegardes
find "$BACKUP_ROOT" -mindepth 1 -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} +

echo "Sauvegarde terminée : $DEST"

Sauvegarde de référentiel de base de données (exemple PostgreSQL)

#!/usr/bin/env bash
# backup-hop-db-repo.sh — s'exécute sur l'hôte de la base de données ou via pg_dump à distance
set -euo pipefail

DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_NAME="${DB_NAME:-hop_repo}"
DB_USER="${DB_USER:-hop_backup}"
BACKUP_ROOT="/var/backups/hop/db-repo"
RETENTION_DAYS=30
TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")
DEST="$BACKUP_ROOT/$TIMESTAMP"

mkdir -p "$DEST"

# Utiliser --no-owner --no-privileges pour des restaurations portables ; --format=custom active la restauration parallèle
pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" \
  --no-owner --no-privileges --format=custom \
  --file="$DEST/hop_repo.dump" "$DB_NAME"

# Vérifier l'intégrité du vidage
pg_restore --list "$DEST/hop_repo.dump" > /dev/null

# Compléter avec la sauvegarde de configuration
rsync -av "$HOME/.hop/" "$DEST/config/"

find "$DEST" -type f -exec sha256sum {} + > "$DEST/manifest.sha256"
find "$BACKUP_ROOT" -mindepth 1 -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} +

echo "Sauvegarde de base de données terminée : $DEST"

Planifiez les deux via des minuteries systemd ou cron. Testez les restaurations mensuellement — une sauvegarde non testée est un passif.

Déploiement Kubernetes (Helm ou Operator)

Dans Kubernetes, Hop s'exécute généralement comme un Deployment ou StatefulSet avec un PersistentVolumeClaim pour le répertoire de projet et une base de données distincte (CloudSQL, RDS ou PostgreSQL en cluster) pour le référentiel de métadonnées.

Sauvegarde basée sur Velero (recommandée)

# velero-hop-backup.yaml — appliquer hebdomadairement via CronJob
apiVersion: velero.io/v1
kind: Schedule
metadata:
  name: hop-weekly-backup
  namespace: velero
spec:
  schedule: "0 2 * * 0"  # Dimanches 02:00 UTC
  template:
    includedNamespaces:
      - hop-prod
    labelSelector:
      matchLabels:
        app.kubernetes.io/name: hop
    snapshotVolumes: true
    ttl: 720h0m0s  # 30 jours
    storageLocation: default
    hooks:
      resources:
        - name: hop-db-dump
          includedNamespaces:
            - hop-prod
          labelSelector:
            matchLabels:
              app: hop-postgres
          pre:
            - exec:
                container: postgres
                command:
                  - /bin/bash
                  - -c
                  - |
                    pg_dump -U hop_backup -Fc hop_repo > /tmp/hop_repo.dump
                    cat /tmp/hop_repo.dump
                onError: Fail
                timeout: 300s

Sauvegarde manuelle de PVC (sans Velero)

#!/usr/bin/env bash
# backup-hop-pvc.sh — exécuter depuis un pod avec le PVC monté
set -euo pipefail

PVC_MOUNT="/data/hop-projects"
BACKUP_BUCKET="s3://my-org-hop-backups/prod/"
TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")

# Synchroniser les fichiers de projet vers le stockage objet
aws s3 sync "$PVC_MOUNT" "$BACKUP_BUCKET$TIMESTAMP/projects/" \
  --exclude "*/logs/*" --exclude "*/tmp/*" --delete

# Vider la base de données depuis un sidecar ou un conteneur d'initialisation
kubectl exec -n hop-prod deploy/hop-postgres -- \
  pg_dump -U hop_backup -Fc hop_repo | \
  aws s3 cp - "$BACKUP_BUCKET$TIMESTAMP/hop_repo.dump"

echo "Sauvegarde Kubernetes terminée : $BACKUP_BUCKET$TIMESTAMP"

Incluez la version de Hop dans les métadonnées de sauvegarde (annotations Velero ou étiquettes S3) pour éviter les restaurations avec incompatibilité de version.

Déploiement Docker Compose

# docker-compose.backup.yml — exécuter via `docker compose -f docker-compose.yml -f docker-compose.backup.yml up hop-backup`
services:
  hop-backup:
    image: alpine:3.20
    volumes:
      - hop-projects:/data/hop-projects:ro
      - hop-config:/root/.hop:ro
      - ./backups:/backups
    environment:
      - DB_HOST=hop-postgres
      - DB_NAME=hop_repo
      - DB_USER=hop_backup
      - DB_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    command: >
      /bin/sh -c "
        set -euo pipefail
        TIMESTAMP=$$(date -u +'%Y%m%dT%H%M%SZ')
        DEST=/backups/$$TIMESTAMP
        mkdir -p $$DEST
        rsync -av --exclude='*/logs/*' --exclude='*/tmp/*' /data/hop-projects/ $$DEST/projects/
        rsync -av /root/.hop/ $$DEST/config/
        pg_dump -h $$DB_HOST -U $$DB_USER -Fc $$DB_NAME > $$DEST/hop_repo.dump
        find $$DEST -type f -exec sha256sum {} + > $$DEST/manifest.sha256
        echo 'Sauvegarde complète : '$$DEST
      "
    depends_on:
      - hop-postgres
volumes:
  hop-projects:
  hop-config:
secrets:
  db_password:
    external: true

Procédures de restauration avec vérification

Une restauration n'est pas complète tant que vous n'avez pas vérifié que les artefacts restaurés s'exécutent correctement.

Restauration de référentiel basé sur fichiers

#!/usr/bin/env bash
# restore-hop-file-repo.sh — interactif, nécessite une confirmation
set -euo pipefail

BACKUP_ROOT="/var/backups/hop/file-repo"
PROJECT_ROOT="/data/hop-projects"
CONFIG_DIR="$HOME/.hop"

echo "Sauvegardes disponibles :"
ls -1dt "$BACKUP_ROOT"/*/ | head -10 | nl

read -rp "Entrez le numéro de la sauvegarde à restaurer (1-10) : " SELECTION
SELECTED=$(ls -1dt "$BACKUP_ROOT"/*/ | sed -n "${SELECTION}p")

if  -z "$SELECTED" ; then
  echo "Sélection invalide"
  exit 1
fi

echo "Sélectionnée : $SELECTED"
echo "Vérification du manifeste..."
cd "$SELECTED"
sha256sum -c manifest.sha256 --quiet || {
  echo "Vérification du manifeste ÉCHOUÉE. Abandon."
  exit 1
}

read -rp "Manifeste OK. Arrêter les services Hop et continuer ? [o/N] " CONFIRM
[[ "$CONFIRM" =~ ^[Oo]$ ]] || { echo "Abandonné."; exit 1; }

# Arrêter les services (adapter à votre système d'initialisation)
systemctl stop hop-server || true

# Sauvegarder l'état actuel comme point de retour
ROLLBACK="/var/backups/hop/pre-restore-$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$ROLLBACK"
rsync -av "$PROJECT_ROOT/" "$ROLLBACK/projects/"
rsync -av "$CONFIG_DIR/" "$ROLLBACK/config/"

# Restaurer
rsync -av --delete "$SELECTED/projects/" "$PROJECT_ROOT/"
rsync -av "$SELECTED/config/" "$CONFIG_DIR/"

# Vérifier que Hop peut charger le projet
"$HOP_HOME/hop-run" --version
"$HOP_HOME/hop-gui" --help > /dev/null 2>&1 || true

# Tester un pipeline connu
TEST_PIPELINE="$PROJECT_ROOT/my-project/pipelines/daily-etl.hpl"
if  -f "$TEST_PIPELINE" ; then
  echo "Exécution du test de fumée sur $TEST_PIPELINE..."
  "$HOP_HOME/hop-run" --file "$TEST_PIPELINE" --log-level Basic || {
    echo "TEST DE FUMÉE ÉCHOUÉ. Retour en arrière..."
    rsync -av --delete "$ROLLBACK/projects/" "$PROJECT_ROOT/"
    rsync -av "$ROLLBACK/config/" "$CONFIG_DIR/"
    exit 1
  }
fi

systemctl start hop-server
echo "Restauration terminée et vérifiée."

Restauration de référentiel de base de données

#!/usr/bin/env bash
# restore-hop-db-repo.sh — restaure le référentiel PostgreSQL
set -euo pipefail

DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_NAME="${DB_NAME:-hop_repo}"
DB_USER="${DB_USER:-hop_admin}"
BACKUP_FILE="${1:-}"

if  -z "$BACKUP_FILE" || ! -f "$BACKUP_FILE" ; then
  echo "Usage : $0 /chemin/vers/hop_repo.dump"
  exit 1
fi

echo "Restauration de $BACKUP_FILE vers $DB_HOST:$DB_PORT/$DB_NAME"
read -rp "Cela va SUPPRIMER et RECréer la base de données. Continuer ? [o/N] " CONFIRM
[[ "$CONFIRM" =~ ^[Oo]$ ]] || exit 1

# Terminer les connexions actives
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "
  SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DB_NAME' AND pid <> pg_backend_pid();
"

# Supprimer et recréer
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS $DB_NAME;"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE $DB_NAME;"

# Restaurer avec des tâches parallèles pour la vitesse
pg_restore -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -j 4 "$BACKUP_FILE"

# Vérifier que le nombre de tables correspond à la ligne de base attendue
TABLE_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "
  SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';
")
echo "Nombre de tables restaurées : $TABLE_COUNT"

# Vérifier la connectivité Hop
"$HOP_HOME/hop-run" --help > /dev/null
echo "Restauration de base de données terminée."

Restauration Kubernetes (Velero)

# Restaurer depuis la planification Velero
velero restore create --from-schedule hop-weekly-backup --namespace hop-prod

# Surveiller
velero restore get
velero restore logs <nom-restauration> --follow

# Vérifier que les pods sont prêts
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=hop -n hop-prod --timeout=300s

# Exécuter le pipeline de test de fumée via hop-run dans un pod temporaire
kubectl run hop-smoke-test --rm -i --restart=Never \
  --image=my-org/hop:2.12.0 \
  --env="HOP_PROJECT=my-project" \
  --env="HOP_ENVIRONMENT=production" \
  -- /opt/hop/hop-run --file /data/hop-projects/my-project/pipelines/daily-etl.hpl --log-level Basic

Validation, surveillance et modes de défaillance

Vérification automatisée des sauvegardes

Ne supposez pas que les sauvegardes fonctionnent. Exécutez une tâche de vérification hebdomadaire qui restaure vers un emplacement temporaire et exécute un pipeline de test de fumée.

#!/usr/bin/env bash
# verify-hop-backup.sh — s'exécute hebdomadairement via cron
set -euo pipefail

LATEST_BACKUP=$(ls -1dt /var/backups/hop/file-repo/*/ | head -1)
VERIFY_DIR="/tmp/hop-verify-$(date -u +%Y%m%dT%H%M%SZ)"
SMOKE_PIPELINE="pipelines/health-check.hpl"
HOP_HOME="/opt/hop"

mkdir -p "$VERIFY_DIR"
rsync -av "$LATEST_BACKUP/projects/" "$VERIFY_DIR/projects/"
rsync -av "$LATEST_BACKUP/config/" "$VERIFY_DIR/config/"

# Vérifier le manifeste
cd "$LATEST_BACKUP"
sha256sum -c manifest.sha256 --quiet || {
  echo "VÉRIFICATION ÉCHOUÉE : incompatibilité du manifeste dans $LATEST_BACKUP"
  exit 1
}

# Exécuter le test de fumée avec une configuration isolée
export HOP_CONFIG_DIRECTORY="$VERIFY_DIR/config"
export HOP_PROJECT_DIRECTORY="$VERIFY_DIR/projects/my-project"

"$HOP_HOME/hop-run" --file "$VERIFY_DIR/projects/my-project/$SMOKE_PIPELINE" --log-level Basic

# Nettoyage
rm -rf "$VERIFY_DIR"
echo "Vérification de sauvegarde RÉUSSIE : $LATEST_BACKUP"

Alertez en cas d'échec via votre pile de surveillance (Prometheus Alertmanager, PagerDuty, Opsgenie).

Modes de défaillance courants et récupération

Mode de défaillanceDétectionAction de récupération
Incompatibilité de la somme de contrôle du manifesteÉchec de la tâche de vérificationEnquêter sur la corruption de la sauvegarde ; restaurer depuis la sauvegarde précédente connue saine ; vérifier l'état du disque
Incompatibilité de version lors de la restauration de base de donnéesAvertissements pg_restore ou erreurs au démarrage de HopAligner la version de Hop avec la version du schéma du référentiel ; exécuter les scripts de migration si disponibles
Pilotes JDBC manquants après restaurationÉchec du pipeline avec ClassNotFoundExceptionRestaurer plugins/databases/ depuis la sauvegarde ou retélécharger les versions correspondantes des pilotes
Dérive des variables d'environnementLes pipelines se connectent à la mauvaise base de donnéesComparer le hop-environments.json restauré avec l'actuel ; réappliquer les variables spécifiques à l'environnement
Restauration partielle de PVC (K8s)Certains fichiers de projet manquantsVérifier la completion de l'instantané de volume Velero ; vérifier la liaison PVC et la classe de stockage
Référentiel de métadonnées corrompuL'interface graphique Hop affiche un projet vide ou des erreurs à l'ouvertureRestaurer depuis la dernière sauvegarde vérifiée ; ne pas tenter de réparation manuelle du JSON

Procédure de retour en arrière

Lorsqu'un changement planifié (mise à niveau, migration, mise à jour de configuration) provoque une régression :

  1. Arrêter les services Hop affectés.
  2. Capturer l'état actuel dans un répertoire de retour en arrière (comme indiqué dans le script de restauration).
  3. Restaurer depuis la dernière sauvegarde vérifiée.
  4. Vérifier avec le pipeline de test de fumée.
  5. Documenter la cause de l'échec dans votre système de suivi d'incidents avant de réessayer le changement.

Conservez au moins trois générations de sauvegardes vérifiées. Une seule génération n'offre aucune protection si la défaillance s'est produite avant la dernière sauvegarde.

Liste de contrôle opérationnelle

Utilisez cette liste lors de l'intégration, des revues trimestrielles et des post-mortems d'incidents.

Quotidien

  • [ ] Tâche de sauvegarde terminée avec succès (vérifier les journaux/surveillance)
  • [ ] Vérification du manifeste réussie
  • [ ] ge de la sauvegarde < 26 heures (pour planification quotidienne)

Hebdomadaire

  • [ ] Tâche de vérification automatisée réussie (restauration complète + test de fumée)
  • [ ] Capacité de stockage de sauvegarde > 20 % libre
  • [ ] Examiner la tendance de la durée de sauvegarde (alerter si > 2x la ligne de base)

Mensuel

  • [ ] Exercice de restauration manuelle vers l'environnement de préproduction
  • [ ] Vérifier que la version du schéma du référentiel de base de données correspond à la version de Hop
  • [ ] Confirmer que les pilotes JDBC et plugins personnalisés sont inclus dans la sauvegarde
  • [ ] Tester la restauration inter-régions (si stratégie multi-régions existe)

Trimestriel

  • [ ] Exercice complet de reprise après sinistre : simuler la perte de la région primaire
  • [ ] Réviser et mettre à jour la politique de rétention selon les exigences de conformité
  • [ ] Valider les manuels de restauration avec les nouveaux membres de l'équipe
  • [ ] Confirmer le chiffrement au repos et en transit pour les données de sauvegarde

À chaque mise à niveau de Hop

  • [ ] Effectuer une sauvegarde pré-mise à niveau (étiquetée avec la version)
  • [ ] Vérifier que la sauvegarde inclut tous les répertoires de plugins
  • [ ] Tester la restauration sur la même version en préproduction
  • [ ] Après la mise à niveau, exécuter la tâche de vérification contre la nouvelle version
  • [ ] Mettre à jour les manuels si les drapeaux CLI ou chemins de configuration ont changé

Conclusion

Une sauvegarde et une restauration fiables d'Apache Hop exigent la protection de quatre classes d'artefacts distinctes : le référentiel de métadonnées (fichier ou base de données), les répertoires de configuration, les plugins et pilotes d'exécution, et les métadonnées d'alignement des versions. Automatisez les sauvegardes avec vérification du manifeste, planifiez des exercices de restauration hebdomadaires qui exécutent un pipeline de test de fumée, et maintenez au moins trois générations de sauvegardes vérifiées. Traitez une sauvegarde non testée comme une lacune, et non comme un filet de sécurité. Lorsqu'un incident survient — qu'il s'agisse d'un référentiel corrompu, d'une mise à niveau échouée ou d'une perte de cluster — la différence entre une récupération de 30 minutes et une panne de plusieurs jours réside dans une procédure de restauration vérifiée et pratiquée. Commencez cette semaine en exécutant le script d'inventaire, en configurant une sauvegarde automatisée avec vérification, et en planifiant votre premier exercice de restauration.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO