App de funções de eventos de armazenamento

+

Arquitetura

A Storage Event Function App é um diretório de imagens e um criador de miniaturas. É composto pelos seguintes componentes:

  • Uma aplicação cliente onde os utilizadores podem carregar imagens.
    • API alojada em contentor e site estático – Golang – Cloud Run
    • Armazenamento – Armazenamento de ficheiros – Cloud Storage
  • Um processador de imagens que cria miniaturas das imagens.
    • Funções como serviço – Golang – Cloud Functions
  • Um pipeline de implementação.
    • Implementação – Cloud Build

Começar

Clique no seguinte link para aceder a uma cópia do código fonte no Cloud Shell. Quando estiver lá, um único comando vai iniciar uma cópia funcional da aplicação no seu projeto.

Abra no Cloud Shell

Veja o código fonte no GitHub


Componentes da app de funções de eventos de armazenamento

A arquitetura da app de funções de eventos de armazenamento usa vários produtos. A lista seguinte apresenta os componentes, juntamente com mais informações sobre os componentes, incluindo links para vídeos relacionados, documentação do produto e visitas guiadas interativas.
Vídeo Docs Instruções passo a passo
Cloud Run O Cloud Run permite-lhe executar aplicações num contentor, mas de forma sem servidor, sem ter de configurar o número de instâncias, processadores ou memória. Carregue um contentor e obtenha um URL.
Cloud Storage O Cloud Storage oferece armazenamento de ficheiros e publicação pública de imagens através de http(s).
Cloud Functions O Cloud Functions é uma plataforma de funções como serviço que lhe permite ouvir carregamentos de ficheiros do Cloud Storage e executar código para criar miniaturas dos mesmos.
Cloud Build O Cloud Build é a ferramenta que agrupa os contentores e os implementa para ficarem disponíveis como serviços do Cloud Run.

Scripts

O script de instalação usa um executável escrito em go e ferramentas da CLI do Terraform para usar um projeto vazio e instalar a aplicação no mesmo. A saída deve ser uma aplicação funcional e um URL para o endereço IP de equilíbrio de carga.

./main.tf

Ative os serviços

Os serviços Google Cloud estão desativados num projeto por predefinição. Para usar qualquer uma das soluções aqui, temos de ativar o seguinte:

  • Cloud Build: cria imagens de contentores e implementa no Cloud Run
  • Cloud Storage: aloja ficheiros estáticos
  • Cloud Functions: plataforma de funções como serviço
  • Cloud Run: a ferramenta sem servidor que vai alojar o contentor e fornecer URLs a partir dos quais aceder à aplicação.
  • Artifact Registry: armazena as imagens Docker para utilização com o Cloud Build.
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
}

Defina autorizações

Define funções e autorizações da IAM que permitem ao Cloud Build implementar todos os serviços.

  • Ative a conta de serviço do Cloud Build para implementar no Cloud Run
  • Ative a conta de serviço do Cloud Build para realizar atividades da conta de serviço
  • Ative a conta de serviço do Cloud Build para publicar no Cloud Run
  • Permita que a conta de serviço do Cloud Build armazene contentores no 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]
}

Crie contentores de armazenamento

Cria a localização de armazenamento para as imagens e as miniaturas carregadas, e fornece uma localização de armazenamento temporária para o carregamento das 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
}

Crie um repositório do Artifact Registry

O código seguinte descreve os parâmetros do repositório do Artifact Registry no qual os contentores estão armazenados.

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]
}

Crie um contentor para a aplicação do Cloud Run

O comando seguinte cria uma imagem e carrega-a para o Artifact Registry para utilização com o 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
    ]
}

Implemente no Cloud Run

O exemplo seguinte usa o Cloud Build para implementar a app Web do cliente no 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
}

Implemente código de funções no Cloud Functions

Enviar diretamente para as funções e ativar.

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

Crie um contentor da API

O seguinte cria uma imagem do Docker para a app Web.

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

Envie o contentor da API para o Artifact Registry

O envio do contentor para o Artifact Registry permite que o Cloud Run obtenha a imagem e a publique.

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

Substituições

Crie uma variável com uma predefinição para que estes valores possam ser alterados no momento da implementação.

substitutions:
  _REGION: us-central1
  _BASENAME: scaler

Conclusão

Agora, tem uma solução de criação de miniaturas em execução no seu projeto que usa o Cloud Functions para responder a alterações num contentor de armazenamento. Também tem todo o código para modificar ou expandir esta solução