存储事件函数应用

架构

Storage Event Function App 是一个图片目录和缩略图制作工具。它由以下组件组成:

  • 用户可以上传图片的客户端应用。
    • 容器托管的 API 和静态网站 - Golang - Cloud Run
    • 存储 - 文件存储 - Cloud Storage
  • 用于创建图片缩略图的图像处理器。
    • 函数即服务 - Golang - Cloud Functions
  • 部署流水线。
    • 部署 - Cloud Build

开始使用

点击以下链接,在 Cloud Shell 中查看源代码的副本。进入该环境后,只需一个命令即可在项目中启动应用的工作副本。

在 Cloud Shell 中打开

在 GitHub 上查看源代码


存储事件函数应用组件

存储事件函数应用架构使用了多种产品。 以下列出了这些组件,以及有关这些组件的更多信息,包括指向相关视频、产品文档和互动式演示文稿的链接。
视频 文档 演示
Cloud Run 借助 Cloud Run,您可以在容器中以无服务器方式运行应用,而无需配置实例数量、处理器或内存。上传容器,获取网址。
Cloud Storage Cloud Storage 通过 http(s) 提供文件存储和图片公开传送服务。
Cloud Functions Cloud Functions 是一项函数服务平台,可让您监听 Cloud Storage 文件上传事件并运行代码来创建文件缩略图。
Cloud Build Cloud Build 是一款工具,可将容器打包并进行部署,以 Cloud Run 服务的形式提供。

脚本

安装脚本使用使用 go 和 Terraform CLI 工具编写的可执行文件,获取一个空项目并在其中安装应用。输出应为一个正常运行的应用和负载均衡 IP 地址的网址。

./main.tf

启用服务

Google Cloud 服务在项目中默认处于停用状态。如需使用此处的任何解决方案,我们必须启用以下功能:

  • Cloud Build - 创建容器映像并部署到 Cloud Run
  • Cloud Storage - 托管静态文件
  • Cloud Functions - 函数即服务平台
  • Cloud Run:这是一个无服务器工具,用于托管容器并提供用于访问应用的网址。
  • Artifact Registry - 存储要与 Cloud Build 搭配使用的 Docker 映像。
variable "gcp_service_list" {
    description = "The list of apis necessary for the project"
    type        = list(string)
    default = [
        "cloudbuild.googleapis.com",
        "storage.googleapis.com",
        "cloudfunctions.googleapis.com",
        "run.googleapis.com",
        "artifactregistry.googleapis.com",
    ]
}

resource "google_project_service" "all" {
    for_each                   = toset(var.gcp_service_list)
    project                    = var.project_number
    service                    = each.key
    disable_dependent_services = false
    disable_on_destroy         = false
}

设置权限

设置 IAM 角色和权限,以允许 Cloud Build 部署所有服务。

  • 允许 Cloud Build 服务账号部署到 Cloud Run
  • 让 Cloud Build 服务账号能够执行服务账号活动
  • 允许 Cloud Build 服务账号发布到 Cloud Run
  • 让 Cloud Build 服务账号能够在 Artifact Registry 中存储容器
variable "build_roles_list" {
    description = "The list of roles that build needs for"
    type        = list(string)
    default = [
        "roles/run.developer",
        "roles/iam.serviceAccountUser",
        "roles/run.admin",
        "roles/cloudfunctions.admin",
        "roles/artifactregistry.admin",
    ]
}

resource "google_project_iam_member" "allbuild" {
    for_each   = toset(var.build_roles_list)
    project    = var.project_number
    role       = each.key
    member     = "serviceAccount:${local.sabuild}"
    depends_on = [google_project_service.all]
}

创建存储分区

为上传的图片和缩略图创建存储位置,并为 Cloud Functions 上传提供临时存储位置。

resource "google_storage_bucket" "target_bucket" {
    name     = var.bucket
    project  = var.project_number
    location = var.location
}

resource "google_storage_bucket" "function_bucket" {
    name     = "${var.project_id}-function-deployer"
    project  = var.project_number
    location = var.location
}

创建 Artifact Registry 代码库

以下代码概述了存储容器的 Artifact Registry 仓库的参数。

resource "google_artifact_registry_repository" "app" {
    provider      = google-beta
    format        = "DOCKER"
    location      = var.region
    project       = var.project_id
    repository_id = "${var.basename}-app"
    depends_on    = [google_project_service.all]
}

为 Cloud Run 应用构建容器

以下脚本会构建映像并将其上传到 Artifact Registry,以便与 Cloud Build 搭配使用。

resource "null_resource" "cloudbuild_app" {
    provisioner "local-exec" {
        working_dir = "${path.module}/code/app"
        command     = "gcloud builds submit . --substitutions=_REGION=${var.region},_BASENAME=${var.basename}"
    }

    depends_on = [
        google_artifact_registry_repository.app,
        google_project_service.all
    ]
}

部署到 Cloud Run

以下脚本使用 Cloud Build 将客户端 Web 应用部署到 Cloud Run。

resource "google_cloud_run_service" "app" {
    name     = "${var.basename}-app"
    location = var.region
    project  = var.project_id

    template {
        spec {
            containers {
                image = "${var.region}-docker.pkg.dev/${var.project_id}/${var.basename}-app/prod"
                env {
                name  = "BUCKET"
                value = var.bucket
                }
            }
        }

        metadata {
            annotations = {
                "autoscaling.knative.dev/maxScale" = "1000"
                "run.googleapis.com/client-name"   = "terraform"
            }
        }
    }
    autogenerate_revision_name = true
    depends_on = [
        null_resource.cloudbuild_app,
    ]
}

data "google_iam_policy" "noauth" {
    binding {
        role = "roles/run.invoker"
        members = [
        "allUsers",
        ]
    }
}

resource "google_cloud_run_service_iam_policy" "noauth_app" {
    location    = google_cloud_run_service.app.location
    project     = google_cloud_run_service.app.project
    service     = google_cloud_run_service.app.name
    policy_data = data.google_iam_policy.noauth.policy_data
}

将函数代码部署到 Cloud Functions

直接推送到函数并激活。

resource "google_storage_bucket_object" "archive" {
    name   = "index.zip"
    bucket = google_storage_bucket.function_bucket.name
    source = "index.zip"
    depends_on = [
        google_project_service.all,
        google_storage_bucket.function_bucket,
        null_resource.cloudbuild_function
    ]
}

resource "google_cloudfunctions_function" "function" {
    name    = var.basename
    project = var.project_id
    region  = var.region
    runtime = "go116"

    available_memory_mb   = 128
    source_archive_bucket = google_storage_bucket.function_bucket.name
    source_archive_object = google_storage_bucket_object.archive.name
    entry_point           = "OnFileUpload"
    event_trigger {
        event_type = "google.storage.object.finalize"
        resource   = google_storage_bucket.target_bucket.name
    }

    depends_on = [
        google_storage_bucket.function_bucket,
        google_storage_bucket.target_bucket,
        google_storage_bucket_object.archive,
        google_project_service.all
    ]
}

./code/app/cloudbuild.yaml

Build API 容器

以下命令会为 Web 应用创建 Docker 映像。

- name: "gcr.io/cloud-builders/docker"
  args: [ "build", "-t", "$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/prod", ".", ]

将 API 容器推送到 Artifact Registry

将容器推送到 Artifact Registry 后,Cloud Run 便可以获取映像并进行分发。

- name: "gcr.io/cloud-builders/docker"
  args: ["push", "$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/prod"]

替换

创建一个具有默认值的变量,以便在部署时更改这些值。

substitutions:
  _REGION: us-central1
  _BASENAME: scaler

总结

现在,您的项目中运行着一个缩略图创建解决方案,该解决方案使用 Cloud Functions 函数来响应存储分区中的更改。您还拥有修改或扩展此解决方案的所有代码