Migrer vos données MySQL d'un disque persistant vers un hyperdisque dans GKE

Ce tutoriel explique comment migrer vos données MySQL existantes d'un disque persistant vers un Hyperdisk sur Google Kubernetes Engine afin d'améliorer les performances de votre stockage. Hyperdisk offre un nombre d'IOPS et un débit plus élevés que Persistent Disk, ce qui peut améliorer les performances de MySQL en réduisant la latence des requêtes et des transactions de base de données. Vous pouvez utiliser des instantanés de disque pour migrer vos données vers différents types de disques en fonction de la compatibilité des types de machines. Par exemple, les volumes Hyperdisk ne sont compatibles qu'avec certains types de machines de troisième, quatrième génération et ultérieures, comme N4, qui ne sont pas compatibles avec les disques persistants. Pour en savoir plus, consultez les séries de machines disponibles.

Pour illustrer la migration de disque persistant vers Hyperdisk, ce tutoriel utilise la base de données Sakila pour fournir un exemple d'ensemble de données. Sakila est un exemple de base de données fourni par MySQL. Vous pouvez l'utiliser comme schéma pour les tutoriels et les exemples. Elle représente un magasin de location de DVD fictif et comprend des tables pour les films, les acteurs, les clients et les locations.

Ce guide s'adresse aux spécialistes et administrateurs du stockage qui créent et attribuent de l'espace de stockage, et qui gèrent la sécurité et l'accès aux données. Pour en savoir plus sur les rôles courants et les exemples de tâches que nous citons dans le contenu Google Cloud , consultez Rôles utilisateur et tâches courantes de GKE.

Architecture de déploiement

Le schéma suivant illustre le processus de migration d'un disque persistant vers un Hyperdisk.

  • Une application MySQL s'exécute sur un pool de nœuds GKE avec des types de machines N2, en stockant ses données sur un disque persistant SSD.
  • Pour assurer la cohérence des données, l'application est réduite pour empêcher les nouvelles écritures.
  • Un instantané du disque persistant est créé, ce qui constitue une sauvegarde complète des données à un moment précis.
  • Un nouveau disque Hyperdisk est provisionné à partir de l'instantané, et une nouvelle instance MySQL est déployée sur un pool de nœuds N4 distinct et compatible avec Hyperdisk. Cette nouvelle instance est associée à l'hyperdisque nouvellement créé, ce qui finalise la migration vers le stockage plus performant.
Schéma d'architecture montrant la migration de données MySQL d'un disque persistant vers un disque Hyperdisk à l'aide d'un instantané.
Figure 1 : Migration des données MySQL d'un disque persistant vers un disque Hyperdisk à l'aide d'un instantané.

Objectifs

Dans ce tutoriel, vous allez apprendre à effectuer les opérations suivantes :

  • Déployez un cluster MySQL.
  • Importer un ensemble de données de test
  • Créez un instantané de vos données.
  • Créez un Hyperdisk à partir de l'instantané.
  • Démarrez un cluster MySQL dans un pool de nœuds de type de machine N4 compatible avec Hyperdisk.
  • Vérifiez l'intégrité des données pour confirmer la réussite de la migration.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

  • GKE
  • Compute Engine, which includes:
    • Storage capacity provisioned for both Persistent Disk and Hyperdisk.
    • Storage costs for the snapshots.

Pour obtenir une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai sans frais.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $de crédits sans frais pour exécuter, tester et déployer des charges de travail.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Compute Engine, GKE, Identity and Access Management Service Account Credentials APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Compute Engine, GKE, Identity and Access Management Service Account Credentials APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  8. Assurez-vous de disposer des rôles suivants sur le projet : roles/container.admin, roles/iam.serviceAccountAdmin, roles/compute.admin

    Vérifier les rôles

    1. Dans la console Google Cloud , accédez à la page IAM.

      Accéder à IAM
    2. Sélectionnez le projet.
    3. Dans la colonne Compte principal, recherchez toutes les lignes qui vous identifient ou identifient un groupe dont vous faites partie. Pour savoir à quels groupes vous appartenez, contactez votre administrateur.

    4. Pour toutes les lignes qui vous spécifient ou vous incluent, consultez la colonne Rôle pour vous assurer que la liste inclut les rôles requis.

    Attribuer les rôles

    1. Dans la console Google Cloud , accédez à la page IAM.

      Accéder à IAM
    2. Sélectionnez le projet.
    3. Cliquez sur  Accorder l'accès.
    4. Dans le champ Nouveaux comptes principaux, saisissez votre identifiant utilisateur. Il s'agit généralement de l'adresse e-mail d'un compte Google.

    5. Cliquez sur Sélectionner un rôle, puis recherchez le rôle.
    6. Pour attribuer des rôles supplémentaires, cliquez sur  Ajouter un autre rôle et ajoutez tous les rôles supplémentaires.
    7. Cliquez sur Enregistrer.

Configurer Cloud Shell

  1. Dans la console Google Cloud , activez Cloud Shell.

    Activer Cloud Shell

    En bas de la console Google Cloud , une session Cloud Shell démarre et affiche une invite de ligne de commande. Cloud Shell est un environnement shell dans lequel Google Cloud CLI est déjà installé, et dans lequel des valeurs sont déjà définies pour votre projet actuel. L'initialisation de la session peut prendre quelques secondes.

  2. Une session Cloud Shell démarre et affiche une invite de ligne de commande. L'initialisation de la session peut prendre quelques secondes.

  3. Définissez le projet par défaut :

      gcloud config set project PROJECT_ID
    

    Remplacez PROJECT_ID par l'ID du projet.

Préparer l'environnement

  1. Dans Cloud Shell, définissez les variables d'environnement pour votre projet, votre emplacement et le préfixe de votre cluster.

    export PROJECT_ID=PROJECT_ID
    export EMAIL_ADDRESS=EMAIL_ADDRESS
    export KUBERNETES_CLUSTER_PREFIX=offline-hyperdisk-migration
    export LOCATION=us-central1-a
    

    Remplacez les éléments suivants :

    • PROJECT_ID : ID de votre projet Google Cloud .
    • EMAIL_ADDRESS : votre adresse e-mail.
    • LOCATION : zone dans laquelle vous souhaitez créer vos ressources de déploiement. Pour les besoins de ce tutoriel, utilisez la zone us-central1-a.
  2. Clonez l'exemple de dépôt de code depuis GitHub :

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. Accédez au répertoire offline-hyperdisk-migration pour commencer à créer des ressources de déploiement :

    cd kubernetes-engine-samples/databases/offline-hyperdisk-migration
    

Créer le cluster GKE et les pools de nœuds

Ce tutoriel utilise un cluster zonal pour plus de simplicité, car les volumes Hyperdisk sont des ressources zonales et ne sont accessibles que dans une seule zone.

  1. Créez un cluster GKE zonal :

    gcloud container clusters create ${KUBERNETES_CLUSTER_PREFIX}-cluster \
        --location ${LOCATION} \
        --node-locations ${LOCATION} \
        --shielded-secure-boot \
        --shielded-integrity-monitoring \
        --machine-type "e2-micro" \
        --num-nodes "1"
    
  2. Ajoutez un pool de nœuds avec un type de machine N2 pour le déploiement initial de MySQL :

    gcloud container node-pools create regular-pool \
        --cluster ${KUBERNETES_CLUSTER_PREFIX}-cluster \
        --machine-type n2-standard-4 \
        --location ${LOCATION} \
        --num-nodes 1
    
  3. Ajoutez un pool de nœuds avec un type de machine N4 sur Hyperdisk, où le déploiement MySQL sera migré et exécuté :

    gcloud container node-pools create hyperdisk-pool \
        --cluster ${KUBERNETES_CLUSTER_PREFIX}-cluster \
        --machine-type n4-standard-4 \
        --location ${LOCATION} \
        --num-nodes 1
    
  4. Connectez-vous au cluster :

    gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --location ${LOCATION}
    

Déployer MySQL sur un disque persistant

Dans cette section, vous allez déployer une instance MySQL qui utilise un disque persistant pour le stockage et la charger avec des exemples de données.

  1. Créez et appliquez un StorageClass pour Hyperdisk. Ce StorageClass sera utilisé plus loin dans le tutoriel.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: balanced-storage
    provisioner: pd.csi.storage.gke.io
    volumeBindingMode: WaitForFirstConsumer
    allowVolumeExpansion: true
    parameters:
      type: hyperdisk-balanced
      provisioned-throughput-on-create: "250Mi"
      provisioned-iops-on-create: "7000"
    kubectl apply -f manifests/01-storage-class/storage-class-hdb.yaml
    
  2. Créez et déployez une instance MySQL qui inclut l'affinité de nœud pour vous assurer que les pods sont planifiés sur les nœuds regular-pool et provisionnez un volume SSD de disque persistant.

    apiVersion: v1
    kind: Service
    metadata:
      name: regular-mysql
      labels:
        app: mysql
    spec:
      ports:
        - port: 3306
      selector:
        app: mysql
      clusterIP: None
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mysql-pv-claim
      labels:
        app: mysql
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 30Gi
      storageClassName: premium-rwo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: existing-mysql
      labels:
        app: mysql
    spec:
      selector:
        matchLabels:
          app: mysql
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: mysql
        spec:
          containers:
          - image: mysql:8.0
            name: mysql
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: migration
            - name: MYSQL_DATABASE
              value: mysql
            - name: MYSQL_USER
              value: app
            - name: MYSQL_PASSWORD
              value: migration
            ports:
            - containerPort: 3306
              name: mysql
            volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
          affinity: 
            nodeAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 1
                preference:
                  matchExpressions:
                  - key: "node.kubernetes.io/instance-type"
                    operator: In
                    values:
                    - "n2-standard-4"
          volumes:
          - name: mysql-persistent-storage
            persistentVolumeClaim:
              claimName: mysql-pv-claim
    kubectl apply -f manifests/02-mysql/mysql-deployment.yaml
    

    Ce fichier manifeste crée un déploiement et un service MySQL, avec un Persistent Disk provisionné de manière dynamique pour le stockage des données. Le mot de passe de l'utilisateur root est migration.

  3. Déployez un pod client MySQL pour charger les données et vérifiez la migration des données :

    apiVersion: v1
    kind: Pod
    metadata:
      name: mysql-client
    spec:
      containers:
      - name: main
        image: mysql:8.0
        command: ["sleep", "360000"]
        resources:
          requests:
            memory: 1Gi
            cpu: 500m
          limits:
            memory: 1Gi
            cpu: "1"
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: migration
    kubectl apply -f manifests/02-mysql/mysql-client.yaml
    kubectl wait pods mysql-client --for condition=Ready --timeout=300s
    
  4. Connectez-vous au pod client :

    kubectl exec -it mysql-client -- bash
    
  5. Dans le shell du pod client, téléchargez et importez l'exemple de jeu de données Sakila :

    # Download the dataset
    curl --output dataset.tgz "https://downloads.mysql.com/docs/sakila-db.tar.gz"
    
    # Extract the dataset
    tar -xvzf dataset.tgz -C /home/mysql
    
    # Import the dataset into MySQL (the password is "migration").
    mysql -u root -h regular-mysql.default -p
        SOURCE /sakila-db/sakila-schema.sql;
        SOURCE /sakila-db/sakila-data.sql;
    
  6. Vérifiez que les données ont été importées :

    USE sakila;
    SELECT      table_name,      table_rows  FROM      INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = 'sakila';
    

    Le résultat affiche une liste de tables avec le nombre de lignes.

    | TABLE_NAME                 | TABLE_ROWS |
    +----------------------------+------------+
    | actor                      |        200 |
    | actor_info                 |       NULL |
    | address                    |        603 |
    | category                   |         16 |
    | city                       |        600 |
    | country                    |        109 |
    | customer                   |        599 |
    | customer_list              |       NULL |
    | film                       |       1000 |
    | film_actor                 |       5462 |
    | film_category              |       1000 |
    | film_list                  |       NULL |
    | film_text                  |       1000 |
    | inventory                  |       4581 |
    | language                   |          6 |
    | nicer_but_slower_film_list |       NULL |
    | payment                    |      16086 |
    | rental                     |      16419 |
    | sales_by_film_category     |       NULL |
    | sales_by_store             |       NULL |
    | staff                      |          2 |
    | staff_list                 |       NULL |
    | store                      |          2 |
    +----------------------------+------------+
    23 rows in set (0.01 sec)
    
  7. Quittez la session mysql :

    exit;
    
  8. Quittez le shell du pod client :

    exit
    
  9. Obtenez le nom du PersistentVolume (PV) créé pour MySQL et stockez-le dans une variable d'environnement :

    export PV_NAME=$(kubectl get pvc mysql-pv-claim -o jsonpath='{.spec.volumeName}')
    

Migrer les données vers un volume Hyperdisk

Vous disposez désormais d'une charge de travail MySQL avec des données stockées sur un volume SSD de disque persistant. Cette section explique comment migrer ces données vers un volume Hyperdisk à l'aide d'un instantané. Cette approche de migration préserve également le volume de disque persistant d'origine, ce qui vous permet de revenir à l'instance MySQL d'origine si nécessaire.

  1. Bien que vous puissiez créer des instantanés à partir de disques sans les dissocier des charges de travail, vous devez arrêter toute nouvelle écriture sur votre disque pendant la création de l'instantané pour garantir l'intégrité des données MySQL. Réduisez le nombre d'instances dupliquées du déploiement MySQL à 0 pour arrêter les écritures :

    kubectl scale deployment regular-mysql --replicas=0
    
  2. Créez un instantané à partir du disque persistant existant :

    gcloud compute disks snapshot ${PV_NAME} --location=${LOCATION} --snapshot-name=original-snapshot --description="snapshot taken from pd-ssd"
    
  3. Créez un volume Hyperdisk nommé mysql-recovery à partir de l'instantané :

    gcloud compute disks create mysql-recovery --project=${PROJECT_ID} \
        --type=hyperdisk-balanced \
        --size=150GB --location=${LOCATION} \
        --source-snapshot=projects/${PROJECT_ID}/global/snapshots/original-snapshot
    
  4. Mettez à jour le fichier manifeste du PV restauré avec l'ID de votre projet :

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: backup
    spec:
      storageClassName: balanced-storage
      capacity:
        storage: 150G
      accessModes:
        - ReadWriteOnce
      claimRef:
        name: hyperdisk-recovery
        namespace: default
      csi:
        driver: pd.csi.storage.gke.io
        volumeHandle: projects/PRJCTID/zones/us-central1-a/disks/mysql-recovery
        fsType: ext4
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      namespace: default
      name: hyperdisk-recovery
    spec:
      storageClassName: balanced-storage
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 150G
    sed -i "s/PRJCTID/$PROJECT_ID/g" manifests/02-mysql/restore_pv.yaml
    
  5. Créez les objets PersistentVolume (PVC) et PersistentVolumeClaim à partir du nouveau disque Hyperdisk :

    kubectl apply -f manifests/02-mysql/restore_pv.yaml
    

Vérifier la migration des données

Déployez une instance MySQL qui utilise le volume Hyperdisk nouvellement créé. Ce pod sera programmé sur le pool de nœuds hyperdisk-pool, qui se compose de nœuds N4.

  1. Déployez la nouvelle instance MySQL :

    apiVersion: v1
    kind: Service
    metadata:
      name: recovered-mysql
      labels:
        app: new-mysql
    spec:
      ports:
        - port: 3306
      selector:
        app: new-mysql
      clusterIP: None
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: new-mysql
      labels:
        app: new-mysql
    spec:
      selector:
        matchLabels:
          app: new-mysql
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: new-mysql
        spec:
          containers:
          - image: mysql:8.0
            name: mysql
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: migration
            - name: MYSQL_DATABASE
              value: mysql
            - name: MYSQL_USER
              value: app
            - name: MYSQL_PASSWORD
              value: migration
            ports:
            - containerPort: 3306
              name: mysql
            volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
          affinity: 
            nodeAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 1
                preference:
                  matchExpressions:
                  - key: "cloud.google.com/gke-nodepool"
                    operator: In
                    values:
                    - "hyperdisk-pool"      
          volumes:
          - name: mysql-persistent-storage
            persistentVolumeClaim:
              claimName: hyperdisk-recovery
    kubectl apply -f manifests/02-mysql/recovery_mysql_deployment.yaml
    
  2. Pour vérifier l'intégrité des données, reconnectez-vous au pod client MySQL :

    kubectl exec -it mysql-client -- bash
    
  3. Dans le pod client, connectez-vous à la nouvelle base de données MySQL (recovered-mysql.default) et vérifiez les données. Le mot de passe est migration.

    mysql -u root -h recovered-mysql.default -p
    USE sakila;
    SELECT table_name, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'sakila';
    

    Les données doivent être identiques à celles de votre instance MySQL d'origine sur le volume de disque persistant.

  4. Quittez la session mysql :

    exit;
    
  5. Quittez le shell du pod client :

    exit
    

Effectuer un nettoyage

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Supprimer le projet

    Supprimer un projet Google Cloud  :

    gcloud projects delete PROJECT_ID

Supprimer des ressources individuelles

Si vous avez utilisé un projet existant et que vous ne souhaitez pas le supprimer, supprimez les ressources individuelles :

  1. Définissez des variables d'environnement pour le nettoyage et récupérez le nom du volume de disque persistant créé par PersistentVolumeClaim mysql-pv-claim :

    export PROJECT_ID=PROJECT_ID
    export KUBERNETES_CLUSTER_PREFIX=offline-hyperdisk-migration
    export location=us-central1-a
    export PV_NAME=$(kubectl get pvc mysql-pv-claim -o jsonpath='{.spec.volumeName}')
    

    Remplacez PROJECT_ID par l'ID du projet.

  2. Supprimez l'instantané :

    gcloud compute snapshots delete original-snapshot --quiet
    
  3. Supprimez le cluster GKE :

    gcloud container clusters delete ${KUBERNETES_CLUSTER_PREFIX}-cluster --location=${LOCATION} --quiet
    
  4. Supprimez les volumes Persistent Disk et Hyperdisk :

    gcloud compute disks delete ${PV_NAME} --location=${LOCATION} --quiet
    gcloud compute disks delete mysql-recovery --location=${LOCATION} --quiet
    

Étapes suivantes