Esegui la migrazione dei dati MySQL da Persistent Disk a Hyperdisk in GKE

Questo tutorial mostra come eseguire la migrazione dei dati MySQL esistenti da un Persistent Disk (DP) a Hyperdisk su Google Kubernetes Engine per migliorare le prestazioni di archiviazione. Hyperdisk offre un numero di IOPS e un throughput superiori rispetto a Persistent Disk, il che può migliorare le prestazioni di MySQL riducendo la latenza per le query e le transazioni del database. Puoi utilizzare gli snapshot del disco per eseguire la migrazione dei dati a tipi di dischi diversi a seconda della compatibilità del tipo di macchina. Ad esempio, i volumi Hyperdisk sono compatibili solo con alcuni tipi di macchine di terza, quarta e successive generazioni, come N4, che non supportano i dischi permanenti. Per ulteriori informazioni, consulta le serie di macchine disponibili.

Per dimostrare la migrazione da Persistent Disk a Hyperdisk, questo tutorial utilizza il database Sakila per fornire un set di dati di esempio. Sakila è un database di esempio fornito da MySQL che puoi utilizzare come schema per tutorial ed esempi. Rappresenta un negozio di noleggio di DVD fittizio e include tabelle per film, attori, clienti e noleggi.

Questa guida è destinata agli specialisti e agli amministratori dell'archiviazione che creano e allocano spazio di archiviazione e gestiscono la sicurezza e l'accesso ai dati. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei contenuti di Google Cloud , consulta Ruoli utente e attività comuni di GKE.

Architettura di deployment

Il seguente diagramma illustra la procedura di migrazione da un Persistent Disk a un Hyperdisk.

  • Un'applicazione MySQL viene eseguita su un pool di nodi GKE con tipi di macchina N2, memorizzando i dati su un disco permanente SSD.
  • Per garantire la coerenza dei dati, l'applicazione viene ridimensionata per impedire nuove scritture.
  • Viene creato uno snapshot del Persistent Disk, che funge da backup point-in-time completo dei dati.
  • Viene eseguito il provisioning di un nuovo Hyperdisk dallo snapshot e viene eseguito il deployment di una nuova istanza MySQL su un pool di nodi N4 separato e compatibile con Hyperdisk. Questa nuova istanza viene collegata all'Hyperdisk appena creato, completando la migrazione all'archiviazione con prestazioni più elevate.
Diagramma dell'architettura che mostra la migrazione dei dati MySQL dal Persistent Disk a Hyperdisk utilizzando uno snapshot.
Figura 1: migrazione dei dati MySQL da Persistent Disk a Hyperdisk utilizzando uno snapshot.

Obiettivi

In questo tutorial imparerai a:

  • Esegui il deployment di un cluster MySQL.
  • Carica un set di dati di test.
  • Crea uno snapshot dei tuoi dati.
  • Crea un Hyperdisk dallo snapshot.
  • Avvia un nuovo cluster MySQL in un pool di nodi di tipo di macchina N4 abilitato per Hyperdisk.
  • Verifica l'integrità dei dati per confermare la riuscita della migrazione.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

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

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi utenti di Google Cloud potrebbero avere diritto a una prova senza costi.

Prima di iniziare

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  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 (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 (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. Make sure that you have the following role or roles on the project: roles/container.admin, roles/iam.serviceAccountAdmin, roles/compute.admin

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      Vai a IAM
    2. Seleziona il progetto.
    3. Fai clic su Concedi l'accesso.
    4. Nel campo Nuove entità, inserisci il tuo identificatore dell'utente. In genere si tratta dell'indirizzo email di un Account Google.

    5. Nell'elenco Seleziona un ruolo, seleziona un ruolo.
    6. Per concedere altri ruoli, fai clic su Aggiungi un altro ruolo e aggiungi ogni ruolo aggiuntivo.
    7. Fai clic su Salva.
    8. Configura Cloud Shell

      1. In the Google Cloud console, activate Cloud Shell.

        Activate Cloud Shell

        Viene avviata una sessione di Cloud Shell e viene visualizzato un prompt della riga di comando. L'inizializzazione della sessione può richiedere alcuni secondi.

      2. Imposta il progetto predefinito:

          gcloud config set project PROJECT_ID
        

        Sostituisci PROJECT_ID con l'ID progetto.

      3. Prepara l'ambiente

        1. In Cloud Shell, imposta le variabili di ambiente per il progetto, la località e il prefisso del cluster.

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

          Sostituisci quanto segue:

          • PROJECT_ID: il tuo Google Cloud ID progetto.
          • EMAIL_ADDRESS: il tuo indirizzo email.
          • LOCATION: la zona in cui vuoi creare le risorse di deployment. Ai fini di questo tutorial, utilizza la zona us-central1-a.
        2. Clona il repository del codice campione da GitHub:

          git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
          
        3. Vai alla directory offline-hyperdisk-migration per iniziare a creare risorse di deployment:

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

        Crea il cluster GKE e i node pool

        Questo tutorial utilizza un cluster di zona per semplicità, perché i volumi Hyperdisk sono risorse di zona e sono accessibili solo all'interno di una singola zona.

        1. Crea un cluster GKE di zona:

          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. Aggiungi un pool di nodi con un tipo di macchina N2 per il deployment iniziale di MySQL:

          gcloud container node-pools create regular-pool \
              --cluster ${KUBERNETES_CLUSTER_PREFIX}-cluster \
              --machine-type n2-standard-4 \
              --location ${LOCATION} \
              --num-nodes 1
          
        3. Aggiungi un pool di nodi con un tipo di macchina N4 su Hyperdisk in cui verrà eseguita la migrazione e l'esecuzione del deployment di MySQL:

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

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

        Esegui il deployment di MySQL sul Persistent Disk

        In questa sezione, esegui il deployment di un'istanza MySQL che utilizza un Persistent Disk per l'archiviazione e caricala con dati di esempio.

        1. Crea e applica un StorageClass per Hyperdisk. Questo StorageClass verrà utilizzato più avanti nel tutorial.

          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. Crea ed esegui il deployment di un'istanza MySQL che includa l'affinità dei nodi per garantire che i pod vengano pianificati sui nodi regular-pool e che venga eseguito il provisioning di un volume SSD del disco permanente.

          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
          

          Questo manifest crea un deployment e un servizio MySQL, con un Persistent Disk di cui viene eseguito il provisioning dinamico per l'archiviazione dei dati. La password per l'utente root è migration.

        3. Esegui il deployment di un pod client MySQL per caricare i dati e verificare la migrazione dei dati:

          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. Connettiti al pod client:

          kubectl exec -it mysql-client -- bash
          
        5. Dalla shell del pod client, scarica e importa il set di dati di esempio 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. Verifica che i dati siano stati importati:

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

          L'output mostra un elenco di tabelle con il conteggio delle righe.

          | 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. Esci dalla sessione mysql:

          exit;
          
        8. Esci dalla shell del pod client:

          exit
          
        9. Recupera il nome del PersistentVolume (PV) creato per MySQL e archivialo in una variabile di ambiente:

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

        Esegui la migrazione dei dati a un volume Hyperdisk

        Ora hai un workload MySQL con dati archiviati su un volume SSD Persistent Disk. Questa sezione descrive come eseguire la migrazione di questi dati a un volume Hyperdisk utilizzando uno snapshot. Questo approccio di migrazione conserva anche il volume Persistent Disk originale, il che ti consente di eseguire il rollback all'utilizzo dell'istanza MySQL originale, se necessario.

        1. Anche se puoi creare snapshot dai dischi senza scollegarli dai carichi di lavoro, per garantire l'integrità dei dati per MySQL devi interrompere qualsiasi nuova scrittura sul disco durante la creazione dello snapshot. Ridimensiona il deployment MySQL a 0 repliche per interrompere le scritture:

          kubectl scale deployment regular-mysql --replicas=0
          
        2. Crea uno snapshot dal Persistent Disk esistente:

          gcloud compute disks snapshot ${PV_NAME} --location=${LOCATION} --snapshot-name=original-snapshot --description="snapshot taken from pd-ssd"
          
        3. Crea un nuovo volume Hyperdisk denominato mysql-recovery dallo snapshot:

          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. Aggiorna il file manifest per il PV ripristinato con l'ID progetto:

          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. Crea PersistentVolume (PVC) e PersistentVolumeClaim dal nuovo Hyperdisk:

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

        Verificare la migrazione dei dati

        Esegui il deployment di una nuova istanza MySQL che utilizza il volume Hyperdisk appena creato. Questo pod verrà pianificato sul pool di nodi hyperdisk-pool, costituito da nodi N4.

        1. Esegui il deployment della nuova istanza 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. Per verificare l'integrità dei dati, connettiti di nuovo al pod client MySQL:

          kubectl exec -it mysql-client -- bash
          
        3. All'interno del pod client, connettiti al nuovo database MySQL (recovered-mysql.default) e verifica i dati. La password è migration.

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

          I dati devono essere gli stessi dell'istanza MySQL originale sul volume Persistent Disk.

        4. Esci dalla sessione mysql:

          exit;
          
        5. Esci dalla shell del pod client:

          exit
          

        Esegui la pulizia

        Per evitare che al tuo Account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

        Elimina il progetto

        1. In the Google Cloud console, go to the Manage resources page.

          Go to Manage resources

        2. In the project list, select the project that you want to delete, and then click Delete.
        3. In the dialog, type the project ID, and then click Shut down to delete the project.

        Elimina singole risorse

        Se hai utilizzato un progetto esistente e non vuoi eliminarlo, elimina le singole risorse:

        1. Imposta le variabili di ambiente per la pulizia e recupera il nome del volume di Persistent Disk creato da 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}')
          

          Sostituisci PROJECT_ID con l'ID progetto.

        2. Elimina lo snapshot:

          gcloud compute snapshots delete original-snapshot --quiet
          
        3. Elimina il cluster GKE:

          gcloud container clusters delete ${KUBERNETES_CLUSTER_PREFIX}-cluster --location=${LOCATION} --quiet
          
        4. Elimina i volumi Persistent Disk e Hyperdisk:

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

        Passaggi successivi