Google Kubernetes Engine 上 Parallelstore 的数据备份和恢复

Parallelstore 仅限受邀者使用。如果您想在 Google Cloud 项目中申请访问 Parallelstore,请与您的销售代表联系。

本指南介绍了如何将已关联的 Parallelstore 实例 (GKE) 中的数据备份到 Cloud Storage 存储桶,以及如何通过配置 GKE CronJob 来按计划自动备份数据,从而防止潜在的数据丢失。本指南还介绍了如何恢复 Parallelstore 实例的数据。

准备工作

按照从 GKE 创建并连接到 Parallelstore 实例中的步骤设置 GKE 集群和 Parallelstore 实例。

数据备份

以下部分介绍了如何设置 GKE CronJob,以持续将 GKE 集群中 Parallelstore 实例的数据备份到 Cloud Storage,从而防止数据丢失。

连接到 GKE 集群

获取 GKE 集群的凭据:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --project=PROJECT_ID \
      --location=CLUSTER_LOCATION

替换以下内容:

  • CLUSTER_NAME:GKE 集群名称。
  • PROJECT_ID: Google Cloud 项目 ID。
  • CLUSTER_LOCATION:包含该集群的 Compute Engine 可用区。您的集群必须位于 Parallelstore CSI 驱动程序支持的可用区中。

提供所需权限

您的 GKE CronJob 需要 roles/parallelstore.adminroles/storage.admin 角色才能在 Cloud Storage 和 Parallelstore 之间导入和导出数据。

创建 Google Cloud 服务账号

    gcloud iam service-accounts create parallelstore-sa \
      --project=PROJECT_ID

授予 Google Cloud 服务账号角色

向服务账号授予 Parallelstore Admin 和 Cloud Storage Admin 角色。

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:parallelstore-sa@PROJECT_ID.iam.gserviceaccount.com \
      --role=roles/parallelstore.admin
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member serviceAccount:parallelstore-sa@PROJECT_ID.iam.gserviceaccount.com \
      --role=roles/storage.admin

设置 GKE 服务账号

您需要设置一个 GKE 服务账号,并允许该账号模拟 Google Cloud 服务账号。按照以下步骤操作,以允许 GKE 服务账号绑定到 Google Cloud 服务账号。

  1. 创建以下 parallelstore-sa.yaml 服务账号清单:

      # GKE service account used by workload and will have access to Parallelstore and GCS
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: parallelstore-sa
        namespace: default
    

    接下来,使用以下命令将其部署到 GKE 集群:

      kubectl apply -f parallelstore-sa.yaml
    
  2. 允许 GKE 服务账号模拟 Google Cloud 服务账号。

      # Bind the GCP SA and GKE SA
      gcloud iam service-accounts add-iam-policy-binding parallelstore-sa@PROJECT_ID.iam.gserviceaccount.com \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:PROJECT_ID.svc.id.goog[default/parallelstore-sa]"
    
      # Annotate the GKE SA with GCP SA
      kubectl annotate serviceaccount parallelstore-sa \
          --namespace default \
      iam.gke.io/gcp-service-account=parallelstore-sa@PROJECT_ID.iam.gserviceaccount.com
    

向 Parallelstore Agent 服务账号授予权限

    gcloud storage buckets add-iam-policy-binding GCS_BUCKET \
      --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-parallelstore.iam.gserviceaccount.com \
      --role=roles/storage.admin

替换以下内容:

  • GCS_BUCKET:Cloud Storage 存储桶 URI,格式为 gs://<bucket_name>
  • PROJECT_NUMBER: Google Cloud 项目编号。

启动 CronJob

配置并启动 GKE CronJob,以定期将数据从 Parallelstore 导出到 Cloud Storage。

为 CronJob 创建配置文件 ps-to-gcs-backup.yaml

  apiVersion: batch/v1
  kind: CronJob
  metadata:
    name: ps-to-gcs-backup
  spec:
    concurrencyPolicy: Forbid
    failedJobsHistoryLimit: 1
    schedule: "0 * * * *"
    successfulJobsHistoryLimit: 3
    suspend: false
    jobTemplate:
      spec:
        template:
          metadata:
            annotations:
              gke-parallelstore/cpu-limit: "0"
              gke-parallelstore/ephemeral-storage-limit: "0"
              gke-parallelstore/memory-limit: "0"
              gke-parallelstore/volumes: "true"
          spec:
            serviceAccountName: parallelstore-sa
            containers:
            - name: pstore-backup
              image: google/cloud-sdk:slim
              imagePullPolicy: IfNotPresent
              command:
              - /bin/bash
              - -c
              - |
                #!/bin/bash
                set -ex

                # Retrieve modification timestamp for the latest file up to the minute
                latest_folder_timestamp=$(find $PSTORE_MOUNT_PATH/$SOURCE_PARALLELSTORE_PATH -type d -printf  '%T@ %p\n'| sort -n | tail -1 | cut -d' ' -f2- | xargs -I{} stat -c %x {} | xargs -I {} date -d {} +"%Y-%m-%d %H:%M")

                # Start exporting from PStore to GCS
                operation=$(gcloud beta parallelstore instances export-data $PSTORE_NAME \
                  --location=$PSTORE_LOCATION \
                  --source-parallelstore-path=$SOURCE_PARALLELSTORE_PATH \
                  --destination-gcs-bucket-uri=$DESTINATION_GCS_URI \
                  --async \
                  --format="value(name)")

                # Wait until operation complete
                while true; do
                  status=$(gcloud beta parallelstore operations describe $operation \
                    --location=$PSTORE_LOCATION \
                    --format="value(done)")
                  if [ "$status" == "True" ]; then
                    break
                  fi
                  sleep 60
                done

                # Check if export succeeded
                error=$(gcloud beta parallelstore operations describe $operation \
                  --location=$PSTORE_LOCATION \
                  --format="value(error)")
                if [ "$error" != "" ]; then
                  echo "!!! ERROR while exporting data !!!"
                fi

                # Delete the old files from PStore if requested
                # This will not delete the folder with the latest modification timestamp
                if $DELETE_AFTER_BACKUP && [ "$error" == "" ]; then
                  find $PSTORE_MOUNT_PATH/$SOURCE_PARALLELSTORE_PATH -type d -mindepth 1 |
                    while read dir; do
                        # Only delete folders that is modified earlier than the latest modification timestamp
                        folder_timestamp=$(stat -c %y $dir)
                        if [ $(date -d "$folder_timestamp" +%s) -lt $(date -d "$latest_folder_timestamp" +%s) ]; then
                          echo "Deleting $dir"
                          rm -rf "$dir"
                        fi
                    done
                fi
              env:
              - name: PSTORE_MOUNT_PATH # mount path of the Parallelstore instance, should match the volumeMount defined for this container
                value: "PSTORE_MOUNT_PATH"
              - name: PSTORE_NAME # name of the Parallelstore instance that need backup
                value: "PSTORE_NAME"
              - name: PSTORE_LOCATION # location/zone of the Parallelstore instance that need backup
                value: "PSTORE_LOCATION"
              - name: SOURCE_PARALLELSTORE_PATH # absolute path from the PStore instance, without volume mount path
                value: "SOURCE_PARALLELSTORE_PATH"
              - name: DESTINATION_GCS_URI # GCS bucket uri used for storing backups, starting with "gs://"
                value: "DESTINATION_GCS_URI"
              - name: DELETE_AFTER_BACKUP # will delete old data from Parallelstore if true
                value: "DELETE_AFTER_BACKUP"
              volumeMounts:
              - mountPath: PSTORE_MOUNT_PATH # should match the value of env var PSTORE_MOUNT_PATH
                name: PSTORE_PV_NAME
            dnsPolicy: ClusterFirst
            restartPolicy: OnFailure
            terminationGracePeriodSeconds: 30
            volumes:
            - name: PSTORE_PV_NAME
              persistentVolumeClaim:
                claimName: PSTORE_PVC_NAME

执行以下变量替换操作:

  • PSTORE_MOUNT_PATH:Parallelstore 实例的装载路径,应与为此容器定义的 volumeMount 匹配。
  • PSTORE_PV_NAME:指向 Parallelstore 实例的 GKE PersistentVolume 的名称。这应已在 GKE 集群中作为前提条件的一部分进行设置。
  • PSTORE_PVC_NAME:请求使用 Parallelstore PersistentVolume 的 GKE PersistentVolumeClaim 的名称。这应该已在 GKE 集群中作为前提条件的一部分进行设置。
  • PSTORE_NAME:需要备份的 Parallelstore 实例的名称。
  • PSTORE_LOCATION:需要备份的 Parallelstore 实例的位置。
  • SOURCE_PARALLELSTORE_PATH:Parallelstore 实例中的绝对路径(不含卷装载路径),且必须以 / 开头。
  • DESTINATION_GCS_URI:Cloud Storage 存储桶的 Cloud Storage 存储桶 URI 或存储桶中的路径,格式为 gs://<bucket_name>/<optional_path_inside_bucket>
  • DELETE_AFTER_BACKUP:用于决定是否在备份后从 Parallelstore 中删除旧数据并释放空间的配置,支持的值:truefalse

使用以下命令将 CronJob 部署到 GKE 集群:

  kubectl apply -f ps-to-gcs-backup.yaml

如需详细了解如何设置 CronJob,请参阅 CronJob

检测数据丢失

当 Parallelstore 实例的状态为 FAILED 时,该实例上的数据可能无法再访问。您可以使用以下 Google Cloud CLI 命令来检查 Parallelstore 实例的状态:

    gcloud beta parallelstore instances describe PARALLELSTORE_NAME \
    --location=PARALLELSTORE_LOCATION \
    --format="value(state)"

数据恢复

发生灾难或 Parallelstore 实例因任何原因发生故障时,您可以选择使用 GKE VolumePopulator 自动将数据从 Cloud Storage 预加载到 GKE 管理的 Parallelstore 实例中,也可以手动创建新的 Parallelstore 实例并从 Cloud Storage 备份导入数据。

如果您要从工作负载的检查点恢复,则需要通过提供 Cloud Storage 存储桶区内的路径来决定要从哪个检查点恢复。

如果 Parallelstore 实例在导出操作中途失败,则 Cloud Storage 中的 Parallelstore 导出数据可能包含部分数据。在将数据导入 Parallelstore 并恢复工作负载之前,请检查目标 Cloud Storage 位置中的数据是否完整。

GKE Volume Populator

GKE Volume Populator 可用于将数据从 Cloud Storage 存储桶路径预加载到新创建的 Parallelstore 实例中。如需了解相关说明,请参阅预加载 Parallelstore

手动恢复

您还可以手动创建 Parallelstore 实例,并按照以下步骤从 Cloud Storage 存储桶导入数据。

  1. 创建新的 Parallelstore 实例:

      gcloud beta parallelstore instances create PARALLELSTORE_NAME \
        --capacity-gib=CAPACITY_GIB \
        --location=PARALLELSTORE_LOCATION \
        --network=NETWORK_NAME \
        --project=PROJECT_ID
    
  2. 从 Cloud Storage 导入数据:

      gcloud beta parallelstore instances import-data PARALLELSTORE_NAME \
        --location=PARALLELSTORE_LOCATION \
        --source-gcs-bucket-uri=SOURCE_GCS_URI \
        --destination-parallelstore-path=DESTINATION_PARALLELSTORE_PATH \
        --async
    

替换以下内容:

  • PARALLELSTORE_NAME:相应 Parallelstore 实例的名称。
  • CAPACITY_GIB:Parallelstore 实例的存储空间容量(以 GB 为单位),值介于 12000100000 之间,且为 4000 的倍数。
  • PARALLELSTORE_LOCATION:需要备份的 Parallelstore 实例的位置,必须位于支持的可用区中。
  • NETWORK_NAME:您在配置 VPC 网络期间创建的 VPC 网络的名称,它必须与您的 GKE 集群使用的网络相同,并且已启用 Private Services Access
  • SOURCE_GCS_URI:Cloud Storage 存储桶的 Cloud Storage 存储桶 URI,或您要从中导入数据的存储桶中的路径,格式为 gs://<bucket_name>/<optional_path_inside_bucket>
  • DESTINATION_PARALLELSTORE_PATH:要将数据导入到的 Parallelstore 实例中的绝对路径,必须以 / 开头。

如需详细了解如何将数据导入 Parallelstore 实例,请参阅将数据转移到 Cloud Storage 或从 Cloud Storage 转移数据