pv-migrate : architecture interne et mécanismes d'implémentation

Vue d'ensemble de l'architecture

pv-migrate repose sur une architecture en couches et modulaire, pensée pour isoler les responsabilités et faciliter l'évolution du code. Le cœur du projet se situe dans le répertoire internal, découpé en plusieurs espaces fonctionnels qui collaborent lors d'une opération de migration.

Les principaux composants sont les suivants :

  • app : gestion du lancement et orchestration des commandes
  • migration : définition des entités et états liés à une migration
  • migrator : moteur d'exécution des transferts
  • k8s : abstraction des appels à l'API Kubernetes
  • helm : gestion du déploiement des chartes Helm
  • strategy : implémentations des différentes stratégies de migration
  • rclone / rsync : intégration des outils de synchronisation de données

Cette séparation permet de remplacer ou d'enrichir facilement une stratégie sans impacter les autres couches.

Modèles de données fondamentaux

Le fichier internal/migration/types.go définit les structures centrales utilisées pendant tout le cycle de vie d'une migration.

La structure PVCReference représente un volume cible ou source :

type PVCReference struct {
    ClusterConfig string
    ContextName   string
    Namespace     string
    PVCName       string
    MountPath     string
}

La structure TransferRequest encapsule l'ensemble des paramètres nécessaires à une migration :

type TransferRequest struct {
    MigrationID       string
    ImageReference    string
    Source            PVCReference
    Destination       PVCReference
    DeleteExtraFiles  bool
    IgnoreMountedFlag bool
}

Enfin, les structures Migration et Attempt permettent de suivre une tâche et ses tentatives d'exécution respectives, incluant les versions de chartes Helm déployées et l'état courant du transfert.

Point d'entrée et initialisation

Le fichier cmd/pv-migrate/main.go constitue le point d'entrée du programme. Son rôle se limite généralement à déléguer le traitement au package app :

package main

func main() {
    if err := app.Run(); err != nil {
        // journalisation et arrêt
    }
}

La fonction Run() du package internal/app se charge ensuite de :

  1. parser les arguments de la ligne de commande et construire un objet TransferRequest ;
  2. initialiser les clients Kubernetes pour les clusters source et destination ;
  3. configurer le système de logs et la sortie utilisateur ;
  4. sélectionner la stratégie de migration la plus appropriée ;
  5. lancer le transfert et traiter le résultat.

Moteur de stratégies

Le répertoire internal/strategy/ contient plusieurs stratégies qui partagent toutes une interface commune. Cette uniformité permet au moteur de choisir dynamiquement la meilleure approche en fonction de la topologie des clusters.

Les stratégies principales sont :

  • ClusterIP : communication interne via un service Kubernetes de type ClusterIP
  • LoadBalancer : exposition d'un point d'entrée réseau pour les migrations inter-clusters
  • NodePort : utilisation d'un port fixe sur les nœuds workers
  • Local : migration directe sans déploiement réseau supplémentaire
  • Mount : montage direct du PVC sur un pod temporaire

Le choix s'effectue en analysant la proximité des PVCs, la connectivité réseau et les autorisations disponibles.

Cycle de vie d'une migrasion

Une migration typique se déroule en cinq phases :

  1. Validation : vérification de l'existence et de l'état des PVCs source et destination, contrôle de l'espace disponible et du statut de montage.
  2. Déploiement Helm : création des ressources éphémères dans les clusters concernés à l'aide des chartes situées dans internal/helm/pv-migrate/.
  3. Transfert de données : exécution de la synchronisation via rclone ou rsync selon la stratégie retenue.
  4. Nettoyage : suppression des ressources temporaires, sauf si l'option --no-cleanup est active.
  5. Retour d'information : affichage du statut, du volume transféré et de la durée totale.

Modules d'infrastructure

Couche d'abstraction Kubernetes

Le package internal/k8s/ fournit les primitives pour interagir avec l'API Kubernetes : création de Jobs et de Services, port-forward, vérification des statuts de pods, etc. Cette abstraction masque la complexité des opérations récurrentes.

Intégration Helm

Le package internal/helm/ gère le chargement des chartes, la fusion des fichiers de valeurs, le rendu des templates et le suivi des releases. L'utilisation de Helm évite de manipuler directement de longs manifestes YAML et simplifie le nettoyage.

Journal et progression

Le package internal/progresslog/ offre des primitives d'affichgae de la progression : barres de progression, logs détaillés et messages d'erreur. Il assure la liaison entre les événements internes et le retour utilisateur.

Exemple d'utilisation

La commande suivante lance une migration entre deux namespaces en ignorant le statut de montage :

pv-migrate --ignore-mounted \
  --source-ns data-prod \
  --source pvc-db-legacy \
  --dest-ns data-new \
  --dest pvc-db-target

Contribuer au projet

Pour participer au développement de pv-migrate, les étapes recommandées sont :

  1. Cloner le dépôt officiel et se familiariser avec la structure du répertoire internal.
  2. Étudier les types définis dans internal/migration/types.go et les implémentations de stratégies dans internal/strategy/.
  3. Respecter le style de code existant et les conevntions du projet.
  4. Ajouter ou modifier des tests dans les fichiers *_test.go correspondants.
  5. Mettre à jour la documentation située dans le répertoire docs/ si nécessaire.

Étiquettes: pv-migrate kubernetes Helm PersistentVolumeClaim rsync

Publié le 5 juillet à 20h10