使用 Cloud Scheduler 安排 Cloud SQL 数据库导出

本教程介绍如何使用 Cloud SchedulerCloud FunctionsCloud SQL for MySQL 数据库自动导出到 Cloud Storage。通过将数据库导出到 Cloud Storage,您可以创建可靠且多样的灾难恢复计划。例如,您可以导出到其他地区,以及导入到其他 Cloud SQL 实例或其他 MySQL 数据库。

架构

本教程涉及以下 Google Cloud 组件:

Cloud Scheduler 作业会在 Pub/Sub 主题上发布一条消息,其中包含有关 Cloud SQL 实例名称、数据库、项目 ID 以及存储备份的 Cloud Storage 位置的信息。此事件会触发 Cloud Functions 函数,该函数获取此载荷并通过 SQL Admin API 在 Cloud SQL 上启动数据库导出。数据库会生成导出并将其保存到 Cloud Storage。下图展示了此过程。

从 Cloud Scheduler 到 Pub/Sub 的工作流,该工作流会触发启动导出的 Cloud Functions 函数。

目标

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 在 Cloud Console 的项目选择器页面上,选择或创建 Cloud 项目。

    转到项目选择器页面

  2. 确保您的 Google Cloud 项目已启用结算功能。 了解如何确认您的项目已启用结算功能

  3. 在 Cloud Console 中,激活 Cloud Shell。

    激活 Cloud Shell

  4. 启用 Cloud SQL Admin、Cloud Functions、Cloud Scheduler 和 App Engine API。

    启用 API

在本教程中,您将通过 Cloud Shell 运行所有命令。

设置环境

首先,您需要克隆包含示例数据的代码库。然后,您需要配置环境并创建具有本教程所需权限的自定义角色。

  1. 克隆包含示例数据的代码库:

    git clone https://github.com/GoogleCloudPlatform/training-data-analyst.git
    

    您将使用 training-data-analyst 代码库中的数据创建包含一些模拟记录的数据库。

  2. 配置以下环境变量:

    export PROJECT_ID=`gcloud config get-value project`
    export DEMO="sql-export-tutorial"
    export BUCKET_NAME=${USER}-mysql-$(date +%s)
    export SQL_INSTANCE="${DEMO}-sql"
    export GCF_NAME="${DEMO}-gcf"
    export PUBSUB_TOPIC="${DEMO}-topic"
    export SCHEDULER_JOB="${DEMO}-job"
    export SQL_ROLE="sqlExporter"
    export STORAGE_ROLE="simpleStorageRole"
    export REGION="us-west2"
    
  3. 创建两个仅具有本教程所需权限的自定义角色:

    gcloud iam roles create ${STORAGE_ROLE} --project ${PROJECT_ID} \
        --title "Simple Storage Role" \
        --description "Grant permissions to view and create objects in Cloud Storage" \
        --permissions "storage.objects.create,storage.objects.get"
    
    gcloud iam roles create ${SQL_ROLE} --project ${PROJECT_ID} \
        --title "SQL Exporter Role" \
        --description "Grant permissions to export data from a Cloud SQL instance to a Cloud Storage bucket as a SQL dump or CSV file" \
        --permissions "cloudsql.instances.export"
    

    这些角色可以缩小 Cloud Functions 和 Cloud SQL 服务帐号的访问权限范围,从而遵循最小权限原则

创建 Cloud Storage 存储分区和 Cloud SQL 实例

在本部分中,您首先需要创建一个 Cloud Storage 存储分区和一个 Cloud SQL for MySQL 实例。然后,您需要创建一个示例数据库并使用示例数据填充该数据库。

创建 Cloud Storage 存储分区

您将使用 gsutil 命令行工具创建 Cloud Storage 存储分区。

  • 在您要保存数据导出的位置创建 Cloud Storage 存储分区:

    gsutil mb -l ${REGION} gs://${BUCKET_NAME}
    

创建 Cloud SQL 实例并向其服务帐号授予权限

接下来,您将创建 Cloud SQL 实例并向其服务帐号授予将数据导出到 Cloud Storage 的权限。

  1. 创建 Cloud SQL for MySQL 5.7 实例

    gcloud sql instances create ${SQL_INSTANCE} --database-version MYSQL_5_7 --region ${REGION}
    

    此操作需要几分钟时间才能完成。

  2. 验证 Cloud SQL 实例是否正在运行:

    gcloud sql instances list --filter name=${SQL_INSTANCE}
    

    输出类似于以下内容:

    NAME                     DATABASE_VERSION  LOCATION    TIER              PRIMARY_ADDRESS  PRIVATE_ADDRESS  STATUS
    sql-export-tutorial-sql  MYSQL_5_7         us-west2-b  db-n1-standard-1  34.94.173.98     -                RUNNABLE
    
  3. 使用 Simple Storage 角色向您的 Cloud SQL 服务帐号授予将数据导出到 Cloud Storage 的权限:

    export SQL_SA=(`gcloud sql instances describe ${SQL_INSTANCE} \
        --project ${PROJECT_ID} \
        --format "value(serviceAccountEmailAddress)"`)
    
    gsutil iam ch serviceAccount:${SQL_SA}:projects/${PROJECT_ID}/roles/${STORAGE_ROLE} gs://${BUCKET_NAME}
    

使用示例数据填充 Cloud SQL 实例

现在,您可以将文件上传到存储分区并创建和填充示例数据库。

  1. 转到您克隆的代码库:

    cd training-data-analyst/CPB100/lab3a/cloudsql
    
  2. 将目录中的文件上传到新的存储分区:

    gsutil cp * gs://${BUCKET_NAME}
    
  3. 创建并填充示例数据库;遇到系统提示时,请点击 yes 以继续:

    gcloud sql import sql ${SQL_INSTANCE} gs://${BUCKET_NAME}/table_creation.sql --project ${PROJECT_ID}
    
    gcloud sql import csv ${SQL_INSTANCE} gs://${BUCKET_NAME}/accommodation.csv \
        --database recommendation_spark \
        --table Accommodation
    
    gcloud sql import csv ${SQL_INSTANCE} gs://${BUCKET_NAME}/rating.csv \
        --database recommendation_spark \
        --table Rating
    

创建 Pub/Sub 主题、Cloud Functions 函数和 Cloud Scheduler 作业

在本部分中,您将创建一个自定义服务帐号并将其绑定到您创建的自定义 SQL 角色。然后,您将创建一个用于触发 Cloud Functions 函数执行的 Pub/Sub 主题。您还将创建一个 Cloud Scheduler 作业以定期执行数据导出函数。

为 Cloud Functions 函数创建服务帐号

第一步是创建一个自定义服务帐号并将其绑定到您创建的自定义 SQL 角色。

  1. 创建一个供 Cloud Functions 函数使用的 IAM 服务帐号:

    gcloud iam service-accounts create ${GCF_NAME} \
        --display-name "Service Account for GCF and SQL Admin API"
    
  2. 向 Cloud Functions 函数服务帐号授予对自定义 SQL 角色的访问权限:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${GCF_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
        --role="projects/${PROJECT_ID}/roles/${SQL_ROLE}"
    

创建 Pub/Sub 主题

下一步是创建一个 Pub/Sub 主题,用于触发与 Cloud SQL 数据库交互的 Cloud Functions 函数。

  • 创建 Pub/Sub 主题:

    gcloud pubsub topics create ${PUBSUB_TOPIC}
    

创建 Cloud Functions 函数

接下来,您将创建 Cloud Functions 函数。

  1. 通过将以下内容粘贴到 Cloud Shell 中来创建 main.py 文件:

    cat <<EOF > main.py
    
    import base64
    import logging
    import json
    
    from datetime import datetime
    from httplib2 import Http
    
    from googleapiclient import discovery
    from googleapiclient.errors import HttpError
    from oauth2client.client import GoogleCredentials
    
    def main(event, context):
        pubsub_message = json.loads(base64.b64decode(event['data']).decode('utf-8'))
        credentials = GoogleCredentials.get_application_default()
    
        service = discovery.build('sqladmin', 'v1beta4', http=credentials.authorize(Http()), cache_discovery=False)
    
        datestamp = datetime.now().strftime("%Y%m%d%H%M") # format timestamp: YearMonthDayHourMinute
        uri = "{0}/backup-{1}-{2}.gz".format(pubsub_message['gs'], pubsub_message['db'], datestamp)
    
        instances_export_request_body = {
          "exportContext": {
            "kind": "sql#exportContext",
            "fileType": "SQL",
            "uri": uri,
            "databases": [
              pubsub_message['db']
            ]
          }
        }
    
        try:
          request = service.instances().export(
                project=pubsub_message['project'],
                instance=pubsub_message['instance'],
                body=instances_export_request_body
            )
          response = request.execute()
        except HttpError as err:
            logging.error("Could NOT run backup. Reason: {}".format(err))
        else:
          logging.info("Backup task status: {}".format(response))
    EOF
    
  2. 通过将以下内容粘贴到 Cloud Shell 中来创建 requirements.txt 文件:

    cat <<EOF > requirements.txt
    google-api-python-client
    Oauth2client
    EOF
    
  3. 部署代码。如果系统询问您是否要允许对新函数进行未经身份验证的调用,请回答 no

    gcloud functions deploy ${GCF_NAME} \
        --trigger-topic ${PUBSUB_TOPIC} \
        --runtime python37 \
        --entry-point main \
        --service-account ${GCF_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
    

创建 Cloud Scheduler 作业

最后,您将创建一个 Cloud Scheduler 作业以定期执行数据导出函数。

  1. 为 Cloud Scheduler 作业创建 App Engine 实例:

    gcloud app create --region=${REGION}
    
  2. 创建一个 Cloud Scheduler 作业以定期执行数据导出函数:

    gcloud scheduler jobs create pubsub ${SCHEDULER_JOB} --schedule '0 23 * * *' --topic ${PUBSUB_TOPIC} --message-body '{"db":"recommendation_spark","instance":'\"${SQL_INSTANCE}\"',"project":'\"${PROJECT_ID}\"',"gs":'\"gs://${BUCKET_NAME}\"'}' --time-zone 'America/Los_Angeles'
    

    此作业安排在每天晚上 11 点运行。

测试您的解决方案

最后一步是测试您的解决方案。首先,您需要运行 Cloud Scheduler 作业。

  1. 手动运行 Cloud Scheduler 作业以触发数据库的 MySQL 转储。

    gcloud scheduler jobs run ${SCHEDULER_JOB}
    
  2. 列出在 MySQL 实例上执行的操作,并验证是否存在类型为 EXPORT 的操作:

    gcloud sql operations list --instance ${SQL_INSTANCE} --limit 1
    

    输出会显示已完成的导出作业,例如:

    NAME                                  TYPE    START                          END                            ERROR  STATUS
    8b031f0b-9d66-47fc-ba21-67dc20193749  EXPORT  2020-02-06T21:55:22.240+00:00  2020-02-06T21:55:32.614+00:00  -      DONE
    
  3. 检查 Cloud Storage 存储分区,看看是否创建了数据库转储文件:

    gsutil ls gs://${BUCKET_NAME} | grep backup-recommendation_spark
    

    在上一步的 STATUS 操作返回 DONE 之后,您会看到一个名为 backup-database_name-timestamp.gz 的文件。

清理

您可以按照以下步骤操作,以避免系统因本教程中使用的资源而向您的 Google Cloud 帐号收取费用。为避免支付费用,最简单的方法是删除您为本教程创建的项目。

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”页面

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

后续步骤