安排备份

本教程介绍如何使用 Cloud Scheduler 和 Cloud Run functions 安排 Filestore 实例的备份。

为 Cloud Scheduler 和 Cloud Run 函数创建客户端服务账号

  1. 如果您尚未这样做,请在 Google Cloud 控制台中点击激活 Cloud Shell

  2. 创建 Cloud Scheduler 用于调用 Cloud Run functions 函数的客户端服务账号运行身份。在此示例中,使用 iam service-accounts create 命令将账号命名为 schedulerunner,并将显示名设置为“FS Backups-Scheduler 的服务账号”:

    gcloud iam service-accounts create schedulerunner \
        --display-name="Service Account for FS Backups-Scheduler"
    
  3. 创建一个 Cloud Run functions 运行身份用以调用 Filestore 端点的客户端服务账号。在此示例中,我们将账号命名为 backupagent,并将显示名设置为“FS Backups-GCF 的服务账号”:

    gcloud iam service-accounts create backupagent \
        --display-name="Service Account for FS Backups-GCF"
    

    您可以通过运行 iam service-accounts list 命令来检查是否已创建服务账号:

    gcloud iam service-accounts list
    

    该命令会返回如下内容:

    NAME                                         EMAIL                                                   DISABLED
    Service Account for FS Backups-GCF           backupagent@$PROJECT_ID.         False
    Service Account for FS Backups-Scheduler     schedulerunner@$PROJECT_ID.      False
    

设置环境变量

在本地环境中设置以下环境变量:

  • Google Cloud 项目 ID 和项目:

    export PROJECT_ID=`gcloud config get-value core/project`
    export PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format="value(projectNumber)"`
    
  • Cloud Scheduler 服务代理和 Cloud Scheduler 及 Cloud Run functions 的客户端服务账号

    export SCHEDULER_SA=service-$PROJECT_NUMBER@gcp-sa-cloudscheduler.
    export SCHEDULER_CLIENT_SA=schedulerunner@$PROJECT_ID.
    export GCF_CLIENT_SA=backupagent@$PROJECT_ID.
    
  • 您的 Filestore 实例:

    export SOURCE_INSTANCE_LOCATION=fs-location
    export SOURCE_INSTANCE_NAME=instance-id
    export SHARE_NAME=file-share-name
    

    替换以下内容:

    • fs-location 替换为源 Filestore 实例所在的可用区或区域。
    • instance-id 替换为来源 Filestore 实例的 ID。
    • file-share-name 替换为您为从实例提供的 NFS 文件共享所指定的名称。
  • 为 Filestore 备份设置环境变量:

    export BACKUP_REGION=backup-region
    

    backup-region 替换为要存储备份的区域。

创建用于创建备份的函数

  1. 在 Google Cloud 控制台中,前往 Cloud Run functions 页面。

    前往 Cloud Run functions 页面

  2. 点击编写函数并按如下所示配置函数:

    • 配置
      • 服务名称:在此示例中,我们将函数命名为 fsbackup
      • 区域:在此示例中,选择 us-central1
      • 运行时:从菜单中选择Cloud Run functions 完全支持的任何受支持的 Python 3 运行时。
    • 触发器
      • 此示例无需设置触发器。
    • 鉴别:选择 Require authentication
    • 入站:选择 All
    • 容器、卷、网络、安全性
      • 前往安全标签页,然后从菜单中选择 Service Account for FS Backups-GCF (backupagent@$PROJECT_ID.)。
  3. 点击创建,然后继续按如下所示进行配置:

    • 函数入口点:输入 create_backup
    • 将以下依赖项添加到 requirements.txt 文件中:

      functions-framework==3.*
      google-auth==2.29.0
      requests==2.31.0
      

      根据您的使用情形,您可能需要指定其他依赖项及其对应的版本号。如需了解详情,请参阅预安装的软件包

    • 使用内嵌编辑器将以下 Python 代码示例复制到 main.py 文件中:

      创建备份

      此代码示例会创建附加有创建时间的 mybackup- 备份。

      PROJECT_ID = 'project-id'
      SOURCE_INSTANCE_LOCATION = 'fs-location'
      SOURCE_INSTANCE_NAME = 'instance-id'
      SOURCE_FILE_SHARE_NAME = 'file-share-name'
      BACKUP_REGION = 'backup-region'
      
      import functions_framework
      import google.auth
      import google.auth.transport.requests
      from google.auth.transport.requests import AuthorizedSession
      import time
      import requests
      import json
      
      credentials, project = google.auth.default()
      request = google.auth.transport.requests.Request()
      credentials.refresh(request)
      authed_session = AuthorizedSession(credentials)
      
      def get_backup_id():
          return "mybackup-" + time.strftime("%Y%m%d-%H%M%S")
      
      @functions_framework.http
      def create_backup(request):
          trigger_run_url = "https://file.googleapis.com/v1/projects/{}/locations/{}/backups?backupId={}".format(PROJECT_ID, BACKUP_REGION, get_backup_id())
          headers = {
            'Content-Type': 'application/json'
          }
          post_data = {
            "description": "my new backup",
            "source_instance": "projects/{}/locations/{}/instances/{}".format(PROJECT_ID, SOURCE_INSTANCE_LOCATION, SOURCE_INSTANCE_NAME),
            "source_file_share": "{}".format(SOURCE_FILE_SHARE_NAME)
          }
          print("Making a request to " + trigger_run_url)
          r = authed_session.post(url=trigger_run_url, headers=headers, data=json.dumps(post_data))
          data = r.json()
          print(data)
          if r.status_code == requests.codes.ok:
            print(str(r.status_code) + ": The backup is uploading in the background.")
          else:
            raise RuntimeError(data['error'])
          return "Backup creation has begun!"
      

      替换以下内容:

      • project-id 替换为来源 Filestore 实例的 Google Cloud 项目 ID。
      • fs-location 替换为来源 Filestore 实例的可用区或区域。
      • instance-id 替换为来源 Filestore 实例的名称。
      • file-share-name 替换为文件共享的名称。
      • backup-region 替换为存储备份的地区。
      1. 点击测试

        系统会在 Cloud Shell 中打开一个新的标签页会话。如果成功,系统会返回以下消息:

        Backup creation has begun!
        
      2. 点击保存并重新部署,然后等待部署完成。

      3. 切换回之前的 Cloud Shell 标签页。

      删除备份

      此代码示例会删除早于预定义时段的备份。

      您一次只能删除每个源实例的一个备份。如需了解详情,请参阅备份

      按照与用于创建备份的函数相同的方式配置此函数,但需进行以下修改:

      • 函数名称deletefsbackup
      • 入口点delete_backup
      PROJECT_ID = 'project-id'
      BACKUP_REGION = 'region'
      BACKUP_RETENTION_TIME_HRS = hours
      
      import functions_framework
      import google.auth
      import google.auth.transport.requests
      from google.auth.transport.requests import AuthorizedSession
      import time
      import requests
      import json
      
      credentials, project = google.auth.default()
      request = google.auth.transport.requests.Request()
      credentials.refresh(request)
      authed_session = AuthorizedSession(credentials)
      
      retention_seconds = BACKUP_RETENTION_TIME_HRS * 60 * 60
      
      @functions_framework.http
      def delete_backup(request):
          now = time.time()
          backup_list = []
          trigger_run_url = "https://file.googleapis.com/v1/projects/{}/locations/{}/backups".format(PROJECT_ID, BACKUP_REGION)
          r = authed_session.get(trigger_run_url)
          data = r.json()
          if not data:
              print("No backups to delete.")
              return "No backups to delete."
          else:
              backup_list.extend(data['backups'])
              while "nextPageToken" in data.keys():
                  nextPageToken = data['nextPageToken']
                  trigger_run_url_next = "https://file.googleapis.com/v1/projects/{}/locations/{}/backups?pageToken={}".format(PROJECT_ID, BACKUP_REGION, nextPageToken)
                  r = authed_session.get(trigger_run_url_next)
                  data = r.json()
                  backup_list.extend(data['backups'])
          for i in backup_list:
              backup_time = i['createTime']
              backup_time = backup_time[:-4]
              backup_time = float(time.mktime(time.strptime(backup_time, "%Y-%m-%dT%H:%M:%S.%f")))
              i['backup_timestamp'] = backup_time
          sorted_backup_list = sorted(backup_list, key=lambda d: d['backup_timestamp'])
          oldest_backup = sorted_backup_list[0]
          if now - oldest_backup['backup_timestamp'] > retention_seconds:
              print(oldest_backup['name'] + " is older than the indicated retention time.")
              r = authed_session.delete("https://file.googleapis.com/v1/{}".format(oldest_backup['name']))
              data = r.json()
              print(data)
              if r.status_code == requests.codes.ok:
                  print(str(r.status_code) + ": Deleting " + oldest_backup['name'] + " in the background.")
              else:
                  raise RuntimeError(data['error'])
              return "Backup deletion has begun!"
          return "All backups are within the indicated retention period."
      

      替换以下内容:

      • project-id 替换为备份的 Google Cloud 项目 ID。
      • region 替换为备份所在的区域。备份、调度器作业和函数应位于同一位置。
      • hours 替换为保留备份的小时数。例如,如果您要将备份保留 10 天,请输入 240

将 IAM 角色分配给客户端服务账号

  1. 将 Cloud Scheduler 服务代理添加到 Cloud Scheduler 客户端服务账号的 IAM 政策中,并授予 roles/cloudscheduler.serviceAgent 角色。这样,服务代理就可以模拟客户端服务账号,以便调用用以创建备份的函数。运行 iam service-accounts add-iam-policy-binding 命令:

    gcloud iam service-accounts add-iam-policy-binding $SCHEDULER_CLIENT_SA \
        --member=serviceAccount:$SCHEDULER_SA \
        --role=roles/cloudscheduler.serviceAgent
    
  2. 为 Cloud Run 函数的客户端服务账号授予 roles/file.editor 角色,以便它可以调用 Filestore 端点。运行 projects add-iam-policy-binding 命令:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member=serviceAccount:$GCF_CLIENT_SA \
        --role=roles/file.editor
    
  3. 向 Cloud Scheduler 的客户端服务账号授予您要使用的函数的 roles/run.invoker 角色。运行以下 run services add-iam-policy-binding 命令:

    创建备份

    gcloud run services add-iam-policy-binding fsbackup \
        --member serviceAccount:$SCHEDULER_CLIENT_SA \
        --role roles/run.invoker \
        --region=us-central1
    

    现在,只有 Cloud Scheduler 的客户端服务账号可以调用 fsbackup

    删除备份

    gcloud run services add-iam-policy-binding deletefsbackup \
        --member serviceAccount:$SCHEDULER_CLIENT_SA \
        --role roles/run.invoker
    

    现在,只有 Cloud Scheduler 的客户端服务账号可以调用 deletefsbackup

创建 Cloud Scheduler 作业,以便按指定的时间表触发函数

创建备份

  1. 在本教程的示例中,如果您希望在每个工作日的晚上 10 点安排一次备份,则可以使用 scheduler jobs create http 命令:

    gcloud scheduler jobs create http fsbackupschedule \
        --schedule "0 22 * * 1-5" \
        --http-method=GET \
        --uri=https://fsbackup-$PROJECT_NUMBER.us-central1.run.app \
        --oidc-service-account-email=$SCHEDULER_CLIENT_SA \
        --location=us-central1
    

    --schedule 标志用于使用 unix-cron 格式指定作业运行的频率。如需了解详情,请参阅配置 Cron 作业时间表

    您每小时最多可以为每个实例创建 6 个备份。

  2. 启动上一步中创建的 Cloud Scheduler 作业。在我们的示例中,使用 scheduler jobs runs 命令立即运行该脚本:

    gcloud scheduler jobs run fsbackupschedule
    

    执行命令后,fsbackupschedule 作业会立即调用 fsbackup 函数,然后每个工作日的晚上 10 点再调用一次,直到作业暂停为止。

  3. 检查 fsbackup 函数的日志,看看该函数是否执行正确并返回 status 200

    如需在 Google Cloud 控制台中查看日志,请使用 Logs Explorer:

    1. 在 Google Cloud 控制台中,转到 Logs Explorer 页面:

      前往 Logs Explorer

      如果您使用搜索栏查找此页面,请选择子标题为 Logging 的结果。

      最近的日志会显示在查询结果窗格中。

  4. 使用 backups list 命令检查现有备份的状态:

    gcloud filestore backups list
    

    该命令会返回类似如下的内容:

    NAME                      LOCATION     SRC_INSTANCE                        SRC_FILE_SHARE  STATE
    mybackup-20201123-184500  us-central1  us-central1-c/instances/nfs-server  vol1            READY
    

删除备份

  1. 在本教程的示例中,如果您希望安排一项操作,以在每个工作日的晚上 10 点删除备份,则可以使用 scheduler jobs create http 命令:

    gcloud scheduler jobs create http deletefsbackupschedule \
        --schedule "0 22 * * 1-5" \
        --http-method=GET \
        --uri=https://us-central1-$PROJECT_ID.cloudfunctions.net/deletefsbackup \
        --oidc-service-account-email=$SCHEDULER_CLIENT_SA    \
        --oidc-token-audience=https://us-central1-$PROJECT_ID.cloudfunctions.net/deletefsbackup
    

    --schedule 标志用于使用 unix-cron 格式指定作业运行的频率。如需了解详情,请参阅配置 Cron 作业时间表

    与同一来源实例关联的备份 delete 操作必须一次执行一个。如需了解详情,请参阅备份

  2. 启动上一步中创建的 Cloud Scheduler 作业。在我们的示例中,我们使用 scheduler jobs runs 命令立即运行它:

    gcloud scheduler jobs run deletefsbackupschedule
    

    执行命令后,deletefsbackupschedule 作业会立即调用 deletefsbackup 函数,然后每到工作日晚上 10 点再调用一次,直到作业暂停为止。

  3. 检查 deletefsbackup 函数的日志,看看该函数是否执行正确并返回 status 200

    如需在 Google Cloud 控制台中查看日志,请使用 Logs Explorer:

    1. 在 Google Cloud 控制台中,转到 Logs Explorer 页面:

      前往 Logs Explorer

      如果您使用搜索栏查找此页面,请选择子标题为 Logging 的结果。

      最近的日志会显示在查询结果窗格中。

  4. 使用 backups list 命令检查现有备份的状态:

    gcloud filestore backups list
    

    该命令会返回类似如下的内容:

    NAME                      LOCATION     SRC_INSTANCE                        SRC_FILE_SHARE  STATE
    mybackup-20201123-184500  us-central1  us-central1-c/instances/nfs-server  vol1            READY
    

备份配额过低提醒

如果您在安排备份时实施备份配额,可能会用尽备份配额,我们建议您设置备份配额过低提醒。这样,您会在备份配额即将用尽时收到通知。