使用 Kubernetes Engine 上的 Spark 处理 BigQuery 中的数据

本教程介绍如何创建和执行使用 BigQuery 存储数据并使用 Google Kubernetes Engine (GKE) 上的 Spark 处理该数据的数据流水线。此流水线适合已在 GKE 上标准化其计算基础架构并正在寻找移植其现有工作流的方法的团队。对于大多数团队而言,要运行其 Spark 应用,最简单、可伸缩性最强的方式是运行 Cloud Dataproc 上的 Spark。本教程将评估公共 BigQuery 数据集 GitHub 数据,找出从贡献中受益最多的项目。本教程假设您熟悉 GKE 和 Apache Spark。以下概要架构图展示了您将用到的技术。

架构图

GitHub 上的许多项目都是采用 Go 编写的,但极少有指标可以告知贡献者项目是否需要帮助或者代码库在哪些方面最需要注意。

在本教程中,您将使用以下指标来判断项目是否需要贡献:

  • 未结问题的数量。
  • 贡献者数量。
  • 其他项目导入某个项目软件包的次数。
  • FIXMETODO 注释的频率。

下图显示了 Spark 应用的流水线:

Spark 应用流水线

目标

  • 创建 Kubernetes Engine 集群以运行 Spark 应用。
  • 在 Kubernetes Engine 上部署 Spark 应用。
  • 在 Spark 应用中查询和写入 BigQuery 表。
  • 使用 BigQuery 分析结果。

费用

本教程使用 Google Cloud 的如下计费组件:

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

准备工作

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

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

  4. 启用 Kubernetes Engine and BigQuery API。

    启用 API

设置环境

在本部分中,您将配置完成本教程所需的项目设置。

启动 Cloud Shell 实例

打开 Cloud Shell

您将在 Cloud Shell 中执行本教程的其余部分。

手动运行流水线

在以下步骤中,您将使用 BigQuery 从 sample_files 表(该表是 [bigquery-public-data:github_repos.files] 的一部分)中提取扩展名为 .go 的所有文件,以此来启动流水线。使用部分数据可以让实验更经济实惠。

  1. 在 Cloud Shell 中运行以下命令,在 BigQuery 中新建数据集和表来存储中间查询结果:

    export PROJECT=$(gcloud info --format='value(config.project)')
    bq mk --project_id $PROJECT spark_on_k8s_manual
    bq mk --project_id $PROJECT spark_on_k8s_manual.go_files
    
  2. 查看 GitHub 代码库数据集中 Go 文件的示例,然后使用 --destination_table 选项将这些文件存储在中间表中:

    export PROJECT=$(gcloud info --format='value(config.project)')
    bq query --project_id $PROJECT --replace \
             --destination_table spark_on_k8s_manual.go_files \
        'SELECT id, repo_name, path FROM
    [bigquery-public-data:github_repos.sample_files]
         WHERE RIGHT(path, 3) = ".go"'
    

    您应该会看到列出的文件路径及其所属的代码库。例如:

    Waiting on bqjob_r311c807f17003279_0000015fb8007c47_1 ... (0s) Current status: DONE
    +------------------------------------------+------------------+-------------------------+
    |                    id                    |    repo_name     |          path           |
    +------------------------------------------+------------------+-------------------------+
    | 31a4559c1e636e | mandelsoft/spiff | spiff++/spiff.go        |
    | 15f7611dd21a89 | bep/gr           | examples/router/main.go |
    | 15cbb0b0f096a2 | knq/xo           | internal/fkmode.go      |
    +------------------------------------------+------------------+-------------------------+
    

    所有已识别的 Go 文件的列表现存储在 spark_on_k8s_manual.go_files 表中。

  3. 运行以下查询,以显示每个文件的前 10 个字符:

    export PROJECT=$(gcloud info --format='value(config.project)')
    bq query --project_id $PROJECT 'SELECT sample_repo_name as
    repo_name, SUBSTR(content, 0, 10) FROM
    [bigquery-public-data:github_repos.sample_contents] WHERE id IN
    (SELECT id FROM spark_on_k8s_manual.go_files)'
    

使用 Kubernetes 上的 Spark 运行流水线

接下来,您将使用 Spark 应用自动执行类似的过程,该应用使用 spark-bigquery 连接器直接针对 BigQuery 运行 SQL 查询。然后,应用使用 Spark SQL 和 DataFrames API 处理结果并将其保存到 BigQuery。

创建一个 Kubernetes Engine 集群

要部署 Spark 和示例应用,请运行以下命令以创建 Kubernetes Engine 集群:

gcloud config set compute/zone us-central1-f
gcloud container clusters create spark-on-gke --machine-type n1-standard-2

下载示例代码

克隆示例应用代码库:

git clone https://github.com/GoogleCloudPlatform/spark-on-k8s-gcp-examples.git
cd spark-on-k8s-gcp-examples/github-insights

配置身份和访问权限管理

为了向 Spark 授予访问 BigQuery 的权限,您必须创建 Identity and Access Management (IAM) 服务帐号

  1. 创建服务帐号:

    gcloud iam service-accounts create spark-bq --display-name spark-bq
    
  2. 将服务帐号电子邮件地址和当前项目 ID 存储在环境变量中,以便用于后续命令:

    export SA_EMAIL=$(gcloud iam service-accounts list --filter="displayName:spark-bq" --format='value(email)')
    export PROJECT=$(gcloud info --format='value(config.project)')
    
  3. 示例应用必须创建和处理 BigQuery 数据集和表,并从 Cloud Storage 中移除工件。将 bigquery.dataOwnerbigQuery.jobUserstorage.admin 角色绑定到该服务帐号:

    gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:$SA_EMAIL --role roles/storage.admin
    gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:$SA_EMAIL --role roles/bigquery.dataOwner
    gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:$SA_EMAIL --role roles/bigquery.jobUser
    
  4. 下载服务帐号 JSON 密钥并将其存储在 Kubernetes Secret中。您的 Spark 驱动程序和执行程序会使用此密钥向 BigQuery 进行身份验证:

    gcloud iam service-accounts keys create spark-sa.json --iam-account $SA_EMAIL
    kubectl create secret generic spark-sa --from-file=spark-sa.json
    
  5. 为 Spark 添加权限,使其能够在 Kubernetes 集群中启动作业。

    kubectl create clusterrolebinding user-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
    kubectl create clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:default spark-admin
    

配置并运行 Spark 应用

现在,您可以下载、安装和配置 Spark,以便在 Kubernetes Engine 集群中执行示例 Spark 应用

  1. 安装用于管理示例应用构建过程的 Maven

    sudo apt-get install -y maven
  2. 构建示例应用 jar:

    mvn clean package
  3. 创建 Cloud Storage 存储分区,以存储应用 jar 和 Spark 流水线的结果:

    export PROJECT=$(gcloud info --format='value(config.project)')
    gsutil mb gs://$PROJECT-spark-on-k8s
    
  4. 将应用 jar 上传到 Cloud Storage 存储分区:

    gsutil cp target/github-insights-1.0-SNAPSHOT-jar-with-dependencies.jar \
                   gs://$PROJECT-spark-on-k8s/jars/
    
  5. 创建一个新的 BigQuery 数据集:

    bq mk --project_id $PROJECT spark_on_k8s
  6. 下载官方 Spark 2.3 发行版并取消归档:

    wget https://archive.apache.org/dist/spark/spark-2.3.0/spark-2.3.0-bin-hadoop2.7.tgz
    tar xvf spark-2.3.0-bin-hadoop2.7.tgz
    cd spark-2.3.0-bin-hadoop2.7
    
  7. 通过创建包含项目特定信息的属性文件来配置 Spark 应用:

    cat > properties << EOF
    spark.app.name  github-insights
    spark.kubernetes.namespace default
    spark.kubernetes.driverEnv.GCS_PROJECT_ID $PROJECT
    spark.kubernetes.driverEnv.GOOGLE_APPLICATION_CREDENTIALS /mnt/secrets/spark-sa.json
    spark.kubernetes.container.image gcr.io/cloud-solutions-images/spark:v2.3.0-gcs
    spark.kubernetes.driver.secrets.spark-sa  /mnt/secrets
    spark.kubernetes.executor.secrets.spark-sa /mnt/secrets
    spark.driver.cores 0.1
    spark.executor.instances 3
    spark.executor.cores 1
    spark.executor.memory 512m
    spark.executorEnv.GCS_PROJECT_ID    $PROJECT
    spark.executorEnv.GOOGLE_APPLICATION_CREDENTIALS /mnt/secrets/spark-sa.json
    spark.hadoop.google.cloud.auth.service.account.enable true
    spark.hadoop.google.cloud.auth.service.account.json.keyfile /mnt/secrets/spark-sa.json
    spark.hadoop.fs.gs.project.id $PROJECT
    EOF
    
  8. 使用以下命令在示例 GitHub 数据集上运行 Spark 应用:

    export KUBERNETES_MASTER_IP=$(gcloud container clusters list --filter name=spark-on-gke --format='value(MASTER_IP)')
    bin/spark-submit \
    --properties-file properties \
    --deploy-mode cluster \
    --class spark.bigquery.example.github.NeedingHelpGoPackageFinder \
    --master k8s://https://$KUBERNETES_MASTER_IP:443 \
    --jars http://central.maven.org/maven2/com/databricks/spark-avro_2.11/4.0.0/spark-avro_2.11-4.0.0.jar \
    gs://$PROJECT-spark-on-k8s/jars/github-insights-1.0-SNAPSHOT-jar-with-dependencies.jar \
    $PROJECT spark_on_k8s $PROJECT-spark-on-k8s --usesample
    
  9. 点击添加 Cloud Shell 会话按钮,打开新的 Cloud Shell 会话:

    添加 Cloud Shell 会话按钮

  10. 在新的 Cloud Shell 会话中,使用以下命令查看驱动程序 pod 的日志,跟踪应用的进度。该应用大约需要五分钟才能完成执行。

    kubectl logs -l spark-role=driver
  11. 应用执行完毕后,运行以下命令检查 10 个最常用的软件包:

    bq query "SELECT * FROM spark_on_k8s.popular_go_packages
    ORDER BY popularity DESC LIMIT 10"
    

通过移除步骤 8 中的 --usesample 选项,您可以在 GitHub 数据集中的所有表上运行同一流水线。注意,由于完整数据集的大小远远大于样本数据集的大小,因此您可能需要更大的集群才能在合理的时间范围内完成流水线的运行。

清除数据

为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

完成本教程后,您可以清理您创建的资源,让它们停止使用配额,以免产生费用。以下部分介绍如何删除或关闭这些资源。

删除项目

为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

如需删除项目,请执行以下操作:

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

    转到“管理资源”

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

后续步骤

  • 查看将 Spark 与 BigQuery 和 Dataproc 结合使用的其他示例
  • 查看本教程,使用 Cloud Dataproc、BigQuery 和 Apache Spark ML 进行机器学习。

  • 探索有关 Google Cloud 的参考架构、图表、教程和最佳做法。查看我们的云架构中心