Cost Sentry

+

Arquitetura

O Cost Sentry é um conjunto de scripts e configurações que lhe permitem encerrar recursos quando os orçamentos de faturação do Google Cloud são excedidos.

Este script é composto pelos seguintes componentes :

  • Eventos – Fila – Pub/Sub
  • Faturação – Controlos de custos – Orçamentos
  • Eventos – Processamento de eventos – Cloud Functions
  • Computação – VMs – Compute Engine
  • Computação – Sem servidor – Cloud Run

Este script vai configurar um orçamento, uma fila de mensagens e uma função do Google Cloud para gerir tudo isto. Em seguida, inicia uma VM de exemplo e um serviço suportado por contentores que é gerido pelo sistema.


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 do Cost Sentry

A arquitetura do Cost Sentry 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
Google Cloud Pub/Sub O Google Cloud Pub/Sub é um barramento de mensagens para integrar aplicações em diferentes serviços em diferentes componentes da nuvem num sistema integrado.
Orçamentos de faturação Os orçamentos de faturação permitem-lhe receber notificações e tomar medidas quando a sua faturação ultrapassa os limites que definiu.
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.
Compute Engine O Compute Engine é a tecnologia virtual do Google Cloud. Com ele, pode criar muitas configurações diferentes de VMs para se adequarem às suas necessidades de computação.
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.

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 o Cost Sentry, ative os seguintes serviços:

  • Orçamentos de faturação: acompanhe a faturação e faça a gestão dos alertas de faturação.
  • Cloud Build: crie imagens de contentores e implemente-as no Cloud Run.
  • Compute Engine: implemente máquinas virtuais e serviços de rede, como o balanceamento de carga.
  • Cloud Functions: responda a eventos da plataforma de serviços.
  • Cloud Run: aloja contentores num ambiente sem servidor e fornece URLs para aceder à aplicação.
variable "gcp_service_list" {
        description = "The list of apis necessary for the project"
        type        = list(string)
        default = [
            "cloudresourcemanager.googleapis.com",
            "cloudbilling.googleapis.com",
            "billingbudgets.googleapis.com",
            "cloudbuild.googleapis.com",
            "compute.googleapis.com",
            "cloudfunctions.googleapis.com",
            "storage.googleapis.com",
            "run.googleapis.com"
        ]
}

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

Crie um canal do Pub/Sub

Cria um canal do Pub/Sub para ouvir eventos de orçamentos de faturação e responder com as Cloud Functions

resource "google_pubsub_topic" "costsentry" {
    name = "${var.basename}-billing-channel"
    project    = var.project_number
}

Crie um serviço do Cloud Run para aplicar

Crie um serviço do Cloud Run de exemplo no qual executar a aplicação da faturação.

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

    metadata {
        labels = {"${var.label}"=true}
    }

    template {
        spec {
            containers {
                image = "us-docker.pkg.dev/cloudrun/container/hello"
            }
        }

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

Crie uma instância de VM

Crie uma instância de exemplo do Compute Engine na qual executar a aplicação.

resource "google_compute_instance" "example" {
    name         = "${var.basename}-example"
    machine_type = "n1-standard-1"
    zone         = var.zone
    project      = var.project_id
    tags                    = ["http-server"]
    labels = {"${var.label}"=true}

    boot_disk {
        auto_delete = true
        device_name = "${var.basename}-example"
        initialize_params {
            image = "family/debian-10"
            size  = 200
            type  = "pd-standard"
        }
    }   

    network_interface {
        network = "default"
        access_config {
        // Ephemeral public IP
        }
    }

    depends_on = [google_project_service.all]
}

Crie um orçamento

Cria um orçamento para monitorizar os gastos nos seus projetos.

provisioner "local-exec" {
    command = <<-EOT
    gcloud beta billing budgets create --display-name ${var.basename}-budget \
    --billing-account ${var.billing_account} --budget-amount ${var.budgetamount} \
    --all-updates-rule-pubsub-topic=projects/${var.project_id}/topics/${var.basename}-billing-channel
    EOT
}

Crie uma conta de serviço e defina autorizações

Cria uma conta de serviço para as chamadas da função do Google Cloud.

resource "google_service_account" "functions_accounts" {
    account_id   = local.safunctionuser
    description  = "Service Account for the costsentry to run as"
    display_name = local.safunction
    project      = var.project_number
}

Defina autorizações

O comando seguinte define as funções e as autorizações da IAM que permitem ao Cloud Build implementar os serviços necessários.

A série de comandos implementa o seguinte: Concede autorização à conta de serviço da função do Cloud para gerir o Cloud Run. Concede autorização à conta de serviço da função do Cloud para parar instâncias do Compute Engine. Concede autorização à conta de serviço do Cloud Build para agir em nome da conta de serviço do Compute.

variable "build_roles_list" {
        description = "The list of roles that fucntions needs for"
        type        = list(string)
        default = [
            "roles/run.admin",
            "roles/compute.instanceAdmin",
            "roles/iam.serviceAccountUser"
        ]
}

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

Implemente uma função do Cloud

O comando seguinte implementa uma função do Cloud que desativa recursos quando é acionado um alerta.

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

resource "null_resource" "cloudbuild_function" {
    provisioner "local-exec" {
        command = <<-EOT
        cp code/function/function.go .
        cp code/function/go.mod .
        zip index.zip function.go
        zip index.zip go.mod
        rm go.mod
        rm function.go
        EOT
    }

    depends_on = [
        google_project_service.all
    ]
}

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"
    service_account_email = google_service_account.functions_accounts.email
    available_memory_mb   = 128
    source_archive_bucket = google_storage_bucket.function_bucket.name
    source_archive_object = google_storage_bucket_object.archive.name
    entry_point           = "LimitUsage"
    event_trigger {
        event_type = "google.pubsub.topic.publish"
        resource   = google_pubsub_topic.costsentry.name
    }

    environment_variables = {
        GOOGLE_CLOUD_PROJECT = var.project_id
        LABEL= var.label
    }

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

Conclusão

Depois de executada, deve ter uma solução de controlo de custos em execução no seu projeto. Além disso, deve ter todo o código para modificar ou expandir esta solução de forma a adequar-se ao seu ambiente.